Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -146,6 +146,12 @@ "the clang compiler does not support '%0'">; def warn_drv_assuming_mfloat_abi_is : Warning< "unknown platform, assuming -mfloat-abi=%0">; +def warn_drv_implied_soft_float_assumed : Warning< + "%0 implies soft-float, ignoring conflicting option '%1'">, + InGroup>; +def warn_drv_implied_soft_float_conflict : Warning< + "%0 implies soft-float, which conflicts with option '%1'">, + InGroup>, DefaultError; def warn_ignoring_ftabstop_value : Warning< "ignoring invalid -ftabstop value '%0', using default value %1">; def warn_drv_overriding_flag_option : Warning< Index: lib/Driver/Tools.h =================================================================== --- lib/Driver/Tools.h +++ lib/Driver/Tools.h @@ -614,7 +614,8 @@ namespace arm { StringRef getARMFloatABI(const Driver &D, const llvm::opt::ArgList &Args, - const llvm::Triple &Triple); + const llvm::Triple &Triple, + bool *ExplicitNoFloat = NULL); } namespace XCore { // For XCore, we do not need to instantiate tools for PreProcess, PreCompile and Compile. Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -581,14 +581,24 @@ D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } -// Select the float ABI as determined by -msoft-float, -mhard-float, and -// -mfloat-abi=. +// Select the float ABI as determined by -msoft-float, -mhard-float, +// -mfpu=... and -mfloat-abi=... StringRef tools::arm::getARMFloatABI(const Driver &D, const ArgList &Args, - const llvm::Triple &Triple) { + const llvm::Triple &Triple, + bool *ExplicitNoFloat) { + + // FIXME: -msoft-float and -mhard-float identify the nature of floating point + // ops, whereas -mfloat-abi=... identifies the floating point argument passing + // convention. But here we are mushing them together into FloatABI = soft/ + // softfp/hard, which is a bit confusing. For example, this means -msoft-float + // and -mfloat-abi=soft are equivalent options to clang. But when we pass + // arguments to the backend (AddARMTargetArgs), these two options take their + // original interpretations. StringRef FloatABI; - if (Arg *A = Args.getLastArg(options::OPT_msoft_float, - options::OPT_mhard_float, - options::OPT_mfloat_abi_EQ)) { + const Arg *A = Args.getLastArg(options::OPT_msoft_float, + options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ); + if (A) { if (A->getOption().matches(options::OPT_msoft_float)) FloatABI = "soft"; else if (A->getOption().matches(options::OPT_mhard_float)) @@ -603,6 +613,31 @@ } } + // Some -mfpu=... options are incompatible with some mfloat-abi=... options + if (Arg *B = Args.getLastArg(options::OPT_mfpu_EQ)) { + StringRef FPU = B->getValue(); + if (FPU == "none") { + // Signal incompatible -mfloat-abi=... options + if (FloatABI == "hard") + D.Diag(diag::warn_drv_implied_soft_float_conflict) + << B->getAsString(Args) << A->getAsString(Args); + else if (FloatABI == "softfp") + D.Diag(diag::warn_drv_implied_soft_float_assumed) + << B->getAsString(Args) << A->getAsString(Args); + // Assume soft-float + FloatABI = "soft"; + } else if (FloatABI.empty() || FloatABI == "soft") { + // Need -mhard-float for floating point ops + FloatABI = "softfp"; + } + } + + // This allows us to differentiate between a user specified soft-float and + // an inferred soft-float. The latter may be overridden under other conditions + // but the former has higher priority. + if (FloatABI == "soft" && ExplicitNoFloat) + *ExplicitNoFloat = true; + // If unspecified, choose the default based on the platform. if (FloatABI.empty()) { switch (Triple.getOS()) { @@ -681,7 +716,8 @@ const ArgList &Args, std::vector &Features, bool ForAS) { - StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple); + bool ExplicitNoFloat = false; + StringRef FloatABI = tools::arm::getARMFloatABI(D, Args, Triple, &ExplicitNoFloat); if (!ForAS) { // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these // yet (it uses the -mfloat-abi and -msoft-float options), and it is @@ -716,6 +752,14 @@ Features.push_back("-neon"); // Also need to explicitly disable features which imply NEON. Features.push_back("-crypto"); + // Disable remaining floating-point features if soft-float is explicitly + // requested. + if (ExplicitNoFloat) { + Features.push_back("-vfp2"); + Features.push_back("-vfp3"); + Features.push_back("-vfp4"); + Features.push_back("-fp-armv8"); + } } // En/disable crc Index: test/Driver/arm-mfpu.c =================================================================== --- test/Driver/arm-mfpu.c +++ test/Driver/arm-mfpu.c @@ -122,12 +122,12 @@ // RUN: %clang -target armv8-linux-gnueabi -mfpu=none %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-NO-FP %s +// CHECK-NO-FP: "-target-feature" "-neon" +// CHECK-NO-FP: "-target-feature" "-crypto" // CHECK-NO-FP: "-target-feature" "-vfp2" // CHECK-NO-FP: "-target-feature" "-vfp3" // CHECK-NO-FP: "-target-feature" "-vfp4" // CHECK-NO-FP: "-target-feature" "-fp-armv8" -// CHECK-NO-FP: "-target-feature" "-crypto" -// CHECK-NO-FP: "-target-feature" "-neon" // RUN: %clang -target arm-linux-gnueabihf %s -### 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-HF %s @@ -136,3 +136,114 @@ // RUN: %clang -target armv7-apple-darwin -x assembler %s -### -c 2>&1 \ // RUN: | FileCheck --check-prefix=ASM %s // ASM-NOT: -target-feature + +// RUN: %clang -target armv8-linux-gnueabi -mfpu=none -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv7-linux-gnueabi -mfpu=none -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv6-linux-gnueabi -mfpu=none -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv5-linux-gnueabi -mfpu=none -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv4-linux-gnueabi -mfpu=none -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv8-linux-gnueabi -mfpu=none -msoft-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv7-linux-gnueabi -mfpu=none -msoft-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv6-linux-gnueabi -mfpu=none -msoft-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv5-linux-gnueabi -mfpu=none -msoft-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv4-linux-gnueabi -mfpu=none -msoft-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv8-linux-gnueabi -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv7-linux-gnueabi -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv6-linux-gnueabi -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv5-linux-gnueabi -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv4-linux-gnueabi -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv8-linux-gnueabi -msoft-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv7-linux-gnueabi -msoft-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv6-linux-gnueabi -msoft-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv5-linux-gnueabi -msoft-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv4-linux-gnueabi -msoft-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv8-linux-gnueabi -mfpu=none %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv7-linux-gnueabi -mfpu=none %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv6-linux-gnueabi -mfpu=none %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv5-linux-gnueabi -mfpu=none %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// RUN: %clang -target armv4-linux-gnueabi -mfpu=none %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI-FP %s +// SOFT-ABI-FP-NOT: error: +// SOFT-ABI-FP-NOT: warning: +// SOFT-ABI-FP-NOT: "-target-feature" "+{{[^ ]*fp[^ ]*}}" +// SOFT-ABI-FP: "-target-feature" "-neon" +// SOFT-ABI-FP: "-target-feature" "-crypto" +// SOFT-ABI-FP: "-target-feature" "-vfp2" +// SOFT-ABI-FP: "-target-feature" "-vfp3" +// SOFT-ABI-FP: "-target-feature" "-vfp4" +// SOFT-ABI-FP: "-target-feature" "-fp-armv8" +// SOFT-ABI-FP-NOT: "-target-feature" "+{{[^ ]*fp[^ ]*}}" +// SOFT-ABI-FP: "-msoft-float" +// SOFT-ABI-FP: "-mfloat-abi" "soft" +// SOFT-ABI-FP-NOT: "-target-feature" "+{{[^ ]*fp[^ ]*}}" + +// RUN: %clang -target armv8-linux-gnueabi -mfpu=none -mfloat-abi=softfp %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=ABI-IGNORE %s +// ABI-IGNORE: warning: -mfpu=none implies soft-float, ignoring conflicting option '-mfloat-abi=softfp' + +// RUN: %clang -target armv8-linux-gnueabi -mfpu=none -mfloat-abi=hard %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=ABI-ERROR %s +// ABI-ERROR: error: -mfpu=none implies soft-float, which conflicts with option '-mfloat-abi=hard' + +// RUN: %clang -target armv8-linux-gnueabi -mfpu=none -mhard-float %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=FP-ERROR %s +// FP-ERROR: error: -mfpu=none implies soft-float, which conflicts with option '-mhard-float' + +// RUN: %clang -target armv8-linux-gnueabi -mfpu=vfp4 -mfloat-abi=soft %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI %s +// RUN: %clang -target armv8-linux-gnueabi -mfpu=vfp4 -mfloat-abi=softfp %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI %s +// RUN: %clang -target armv8-freebsd-gnueabi -mfpu=vfp4 %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=SOFT-ABI %s +// SOFT-ABI-NOT: error: +// SOFT-ABI-NOT: warning: +// SOFT-ABI-NOT: "-msoft-float" +// SOFT-ABI: "-target-feature" "+vfp4" +// SOFT-ABI-NOT: "-msoft-float" +// SOFT-ABI: "-mfloat-abi" "soft" +// SOFT-ABI-NOT: "-msoft-float" + +// Floating point features should be disabled only when explicitly requested, +// otherwise we must respect target inferred defaults. +// +// RUN: %clang -target armv8-freebsd-gnueabi %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=DEFAULT-FP %s +// DEAFULT-FP-NOT: error: +// DEFAULT-FP-NOT: warning: +// DEFAULT-FP-NOT: "-target-feature" "-{{[^ ]*fp[^ ]*}}" +// DEFAULT-FP: "-msoft-float" "-mfloat-abi" "soft" +// DEFAULT-FP-NOT: "-target-feature" "-{{[^ ]*fp[^ ]*}}" + +// RUN: %clang -target armv8-linux-gnueabi -mfpu=vfp4 -mfloat-abi=hard %s -### 2>&1 \ +// RUN: | FileCheck --check-prefix=VFP-ABI %s +// VFP-ABI-NOT: error: +// VFP-ABI-NOT: warning: +// VFP-ABI-NOT: "-msoft-float" +// VFP-ABI: "-target-feature" "+vfp4" +// VFP-ABI-NOT: "-msoft-float" +// VFP-ABI: "-mfloat-abi" "hard" +// VFP-ABI-NOT: "-msoft-float"