[AVR] Add support for the -mdouble=x flag

This flag is used by avr-gcc (starting with v10) to set the width of the
double type. The double type is by default interpreted as a 32-bit
floating point number in avr-gcc instead of a 64-bit floating point
number as is common on other architectures. Starting with GCC 10, a new
option has been added to control this behavior:
https://gcc.gnu.org/wiki/avr-gcc#Deviations_from_the_Standard

This commit keeps the default double at 32 bits but adds support for the
-mdouble flag (-mdouble=32 and -mdouble=64) to control this behavior.

Differential Revision: https://reviews.llvm.org/D76181
This commit is contained in:
Ayke van Laethem 2020-03-14 18:55:13 +01:00
parent 0818e6cf1d
commit 4add249205
No known key found for this signature in database
GPG Key ID: E97FF5335DFDFDED
7 changed files with 46 additions and 0 deletions

View File

@ -176,6 +176,7 @@ VALUE_LANGOPT(PackStruct , 32, 0,
VALUE_LANGOPT(MaxTypeAlign , 32, 0, VALUE_LANGOPT(MaxTypeAlign , 32, 0,
"default maximum alignment for types") "default maximum alignment for types")
VALUE_LANGOPT(AlignDouble , 1, 0, "Controls if doubles should be aligned to 8 bytes (x86 only)") 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") VALUE_LANGOPT(LongDoubleSize , 32, 0, "width of long double")
LANGOPT(PPCIEEELongDouble , 1, 0, "use IEEE 754 quadruple-precision for 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(PICLevel , 2, 0, "__PIC__ level")

View File

@ -2179,6 +2179,8 @@ def mbranches_within_32B_boundaries : Flag<["-"], "mbranches-within-32B-boundari
def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group<clang_ignored_m_Group>; def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group<clang_ignored_m_Group>;
def mlong_calls : Flag<["-"], "mlong-calls">, Group<m_Group>, def mlong_calls : Flag<["-"], "mlong-calls">, Group<m_Group>,
HelpText<"Generate branches with extended addressability, usually via indirect jumps.">; HelpText<"Generate branches with extended addressability, usually via indirect jumps.">;
def mdouble_EQ : Joined<["-"], "mdouble=">, Group<m_Group>, Values<"32,64">, Flags<[CC1Option]>,
HelpText<"Force double to be 32 bits or 64 bits">;
def LongDouble_Group : OptionGroup<"<LongDouble group>">, Group<m_Group>, def LongDouble_Group : OptionGroup<"<LongDouble group>">, Group<m_Group>,
DocName<"Long double flags">, DocName<"Long double flags">,
DocBrief<[{Selects the long double implementation}]>; DocBrief<[{Selects the long double implementation}]>;

View File

@ -380,6 +380,20 @@ void TargetInfo::adjust(LangOptions &Opts) {
LongDoubleFormat = &llvm::APFloat::IEEEquad(); 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) {
if (Opts.LongDoubleSize == DoubleWidth) { if (Opts.LongDoubleSize == DoubleWidth) {
LongDoubleWidth = DoubleWidth; LongDoubleWidth = DoubleWidth;

View File

@ -4580,6 +4580,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs, RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs,
JA.getOffloadingDeviceKind()); 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 (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) {
if (TC.getTriple().isX86()) if (TC.getTriple().isX86())
A->render(Args, CmdArgs); A->render(Args, CmdArgs);

View File

@ -2937,6 +2937,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags); Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags);
Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags); Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags);
Opts.AlignDouble = Args.hasArg(OPT_malign_double); Opts.AlignDouble = Args.hasArg(OPT_malign_double);
Opts.DoubleSize = getLastArgIntValue(Args, OPT_mdouble_EQ, 0, Diags);
Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_128) Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_128)
? 128 ? 128
: Args.hasArg(OPT_mlong_double_64) ? 64 : 0; : Args.hasArg(OPT_mlong_double_64) ? 64 : 0;

View File

@ -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

View File

@ -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'