Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -6297,8 +6297,7 @@ 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; Index: lib/Driver/Tools.h =================================================================== --- lib/Driver/Tools.h +++ lib/Driver/Tools.h @@ -777,6 +777,16 @@ 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. Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -1640,26 +1640,65 @@ 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"); } } @@ -2477,6 +2516,11 @@ 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: Index: test/CodeGen/function-target-features.c =================================================================== --- test/CodeGen/function-target-features.c +++ test/CodeGen/function-target-features.c @@ -9,7 +9,6 @@ // 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 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 @@ -23,4 +22,3 @@ // X86-64-CPU: "target-cpu"="x86-64" // AVX-MINUS-FEATURE: "target-features"={{.*}}-avx // SOFT-FLOAT: "target-features"={{.*}}+soft-float -// NO-SOFT-FLOAT-NOT: "target-features"={{.*}}+soft-float Index: test/Driver/sparc-float.c =================================================================== --- test/Driver/sparc-float.c +++ 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'