From 13a49374048c0d9e1600cda96f181d07ce732042 Mon Sep 17 00:00:00 2001 From: Jacob Baungard Hansen Date: Tue, 24 May 2016 08:30:08 +0000 Subject: [PATCH] [Sparc] Add software float option -msoft-float Summary: Following patch D19265 which enable software floating point support in the Sparc backend, this patch enables the option to be enabled in the front-end using the -msoft-float option. The user should ensure a library (such as the builtins from Compiler-RT) that includes the software floating point routines is provided. Reviewers: jyknight, lero_chris Subscribers: jyknight, cfe-commits Differential Revision: http://reviews.llvm.org/D20419 llvm-svn: 270538 --- clang/lib/Basic/Targets.cpp | 4 +- clang/lib/Driver/Tools.cpp | 74 +++++++++++++++---- clang/lib/Driver/Tools.h | 10 +++ clang/test/CodeGen/function-target-features.c | 2 +- clang/test/Driver/sparc-float.c | 40 +++++++++- 5 files changed, 109 insertions(+), 21 deletions(-) diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index cd9c51adab9e5..4d06ebb724bd3 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -6333,12 +6333,10 @@ class SparcTargetInfo : public TargetInfo { bool handleTargetFeatures(std::vector &Features, DiagnosticsEngine &Diags) override { - // The backend doesn't actually handle soft float yet, but in case someone - // is using the support for the front end continue to support it. + // Check if software floating point is enabled auto Feature = std::find(Features.begin(), Features.end(), "+soft-float"); if (Feature != Features.end()) { SoftFloat = true; - Features.erase(Feature); } return true; } diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index b45a118bc3bc2..67bce6b2bd821 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -1640,28 +1640,67 @@ static std::string getLanaiTargetCPU(const ArgList &Args) { return ""; } -void Clang::AddSparcTargetArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - const Driver &D = getToolChain().getDriver(); - std::string Triple = getToolChain().ComputeEffectiveClangTriple(Args); - - bool SoftFloatABI = false; +sparc::FloatABI sparc::getSparcFloatABI(const Driver &D, + const ArgList &Args) { + sparc::FloatABI ABI = sparc::FloatABI::Invalid; if (Arg *A = - Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float)) { + Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ)) { if (A->getOption().matches(options::OPT_msoft_float)) - SoftFloatABI = true; + ABI = sparc::FloatABI::Soft; + else if (A->getOption().matches(options::OPT_mhard_float)) + ABI = sparc::FloatABI::Hard; + else { + ABI = llvm::StringSwitch(A->getValue()) + .Case("soft", sparc::FloatABI::Soft) + .Case("hard", sparc::FloatABI::Hard) + .Default(sparc::FloatABI::Invalid); + if (ABI == sparc::FloatABI::Invalid && + !StringRef(A->getValue()).empty()) { + D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); + ABI = sparc::FloatABI::Hard; + } + } } + // If unspecified, choose the default based on the platform. // Only the hard-float ABI on Sparc is standardized, and it is the - // default. GCC also supports a nonstandard soft-float ABI mode, and - // perhaps LLVM should implement that, too. However, since llvm - // currently does not support Sparc soft-float, at all, display an - // error if it's requested. - if (SoftFloatABI) { - D.Diag(diag::err_drv_unsupported_opt_for_target) << "-msoft-float" - << Triple; + // default. GCC also supports a nonstandard soft-float ABI mode, also + // implemented in LLVM. However as this is not standard we set the default + // to be hard-float. + if (ABI == sparc::FloatABI::Invalid) { + ABI = sparc::FloatABI::Hard; } + return ABI; +} + +static void getSparcTargetFeatures(const Driver &D, const ArgList &Args, + std::vector &Features) { + sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args); + if (FloatABI == sparc::FloatABI::Soft) + Features.push_back("+soft-float"); +} + +void Clang::AddSparcTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + //const Driver &D = getToolChain().getDriver(); + std::string Triple = getToolChain().ComputeEffectiveClangTriple(Args); + + sparc::FloatABI FloatABI = + sparc::getSparcFloatABI(getToolChain().getDriver(), Args); + + if (FloatABI == sparc::FloatABI::Soft) { + // Floating point operations and argument passing are soft. + CmdArgs.push_back("-msoft-float"); + CmdArgs.push_back("-mfloat-abi"); + CmdArgs.push_back("soft"); + } else { + // Floating point operations and argument passing are hard. + assert(FloatABI == sparc::FloatABI::Hard && "Invalid float abi!"); + CmdArgs.push_back("-mfloat-abi"); + CmdArgs.push_back("hard"); + } } void Clang::AddSystemZTargetArgs(const ArgList &Args, @@ -2478,6 +2517,11 @@ static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, case llvm::Triple::wasm32: case llvm::Triple::wasm64: getWebAssemblyTargetFeatures(Args, Features); + break; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + getSparcTargetFeatures(D, Args, Features); break; case llvm::Triple::r600: case llvm::Triple::amdgcn: diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h index 514abf82f22e1..c2114bcfa8503 100644 --- a/clang/lib/Driver/Tools.h +++ b/clang/lib/Driver/Tools.h @@ -777,6 +777,16 @@ enum class FloatABI { FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args); } // end namespace ppc +namespace sparc { +enum class FloatABI { + Invalid, + Soft, + Hard, +}; + +FloatABI getSparcFloatABI(const Driver &D, const llvm::opt::ArgList &Args); +} // end namespace sparc + namespace XCore { // For XCore, we do not need to instantiate tools for PreProcess, PreCompile and // Compile. diff --git a/clang/test/CodeGen/function-target-features.c b/clang/test/CodeGen/function-target-features.c index 351c7f102b12b..6b32d3ddbcda6 100644 --- a/clang/test/CodeGen/function-target-features.c +++ b/clang/test/CodeGen/function-target-features.c @@ -9,7 +9,7 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -target-cpu corei7 -target-feature +avx | FileCheck %s -check-prefix=CORE-CPU-AND-FEATURES // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -target-cpu x86-64 | FileCheck %s -check-prefix=X86-64-CPU // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -target-cpu corei7-avx -target-feature -avx | FileCheck %s -check-prefix=AVX-MINUS-FEATURE -// RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm -o - %s -target-feature +soft-float | FileCheck %s -check-prefix=NO-SOFT-FLOAT +// RUN: %clang_cc1 -triple sparc-unknown-unknown -emit-llvm -o - %s -target-feature +soft-float | FileCheck %s -check-prefix=SOFT-FLOAT // RUN: %clang_cc1 -triple arm-unknown-unknown -emit-llvm -o - %s -target-feature +soft-float | FileCheck %s -check-prefix=SOFT-FLOAT // RUN: %clang_cc1 -triple mips-unknown-unknown -emit-llvm -o - %s -target-feature +soft-float | FileCheck %s -check-prefix=SOFT-FLOAT diff --git a/clang/test/Driver/sparc-float.c b/clang/test/Driver/sparc-float.c index 6fa47f00cc7a3..c205f5db17ec1 100644 --- a/clang/test/Driver/sparc-float.c +++ b/clang/test/Driver/sparc-float.c @@ -18,7 +18,25 @@ // RUN: %clang -c %s -### -o %t.o 2>&1 \ // RUN: -target sparc-linux-gnu -msoft-float \ // RUN: | FileCheck --check-prefix=CHECK-SOFT %s -// CHECK-SOFT: error: unsupported option '-msoft-float' +// CHECK-SOFT: "-target-feature" "+soft-float" +// +// -mfloat-abi=soft +// RUN: %clang -c %s -### -o %t.o 2>&1 \ +// RUN: -target sparc-linux-gnu -mfloat-abi=soft \ +// RUN: | FileCheck --check-prefix=CHECK-FLOATABISOFT %s +// CHECK-FLOATABISOFT: "-target-feature" "+soft-float" +// +// -mfloat-abi=hard +// RUN: %clang -c %s -### -o %t.o 2>&1 \ +// RUN: -target sparc-linux-gnu -mfloat-abi=hard \ +// RUN: | FileCheck --check-prefix=CHECK-FLOATABIHARD %s +// CHECK-FLOATABIHARD-NOT: "-target-feature" "+soft-float" +// +// check invalid -mfloat-abi +// RUN: %clang -c %s -### -o %t.o 2>&1 \ +// RUN: -target sparc-linux-gnu -mfloat-abi=x \ +// RUN: | FileCheck --check-prefix=CHECK-ERRMSG %s +// CHECK-ERRMSG: error: invalid float ABI '-mfloat-abi=x' // // Default sparc64 // RUN: %clang -c %s -### -o %t.o 2>&1 \ @@ -37,4 +55,22 @@ // RUN: %clang -c %s -### -o %t.o 2>&1 \ // RUN: -target sparc64-linux-gnu -msoft-float \ // RUN: | FileCheck --check-prefix=CHECK-SOFT-SPARC64 %s -// CHECK-SOFT-SPARC64: error: unsupported option '-msoft-float' +// CHECK-SOFT-SPARC64: "-target-feature" "+soft-float" +// +// -mfloat-abi=soft +// RUN: %clang -c %s -### -o %t.o 2>&1 \ +// RUN: -target sparc64-linux-gnu -mfloat-abi=soft \ +// RUN: | FileCheck --check-prefix=CHECK-FLOATABISOFT64 %s +// CHECK-FLOATABISOFT64: "-target-feature" "+soft-float" +// +// -mfloat-abi=hard +// RUN: %clang -c %s -### -o %t.o 2>&1 \ +// RUN: -target sparc64-linux-gnu -mfloat-abi=hard \ +// RUN: | FileCheck --check-prefix=CHECK-FLOATABIHARD64 %s +// CHECK-FLOATABIHARD64-NOT: "-target-feature" "+soft-float" +// +// check invalid -mfloat-abi +// RUN: %clang -c %s -### -o %t.o 2>&1 \ +// RUN: -target sparc64-linux-gnu -mfloat-abi=x \ +// RUN: | FileCheck --check-prefix=CHECK-ERRMSG64 %s +// CHECK-ERRMSG64: error: invalid float ABI '-mfloat-abi=x'