r255515 - [Power PC] add soft float support for ppc32
Petar Jovanovic via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 14 09:51:50 PST 2015
Author: petarj
Date: Mon Dec 14 11:51:50 2015
New Revision: 255515
URL: http://llvm.org/viewvc/llvm-project?rev=255515&view=rev
Log:
[Power PC] add soft float support for ppc32
This patch enables soft float support for ppc32 architecture and fixes
the ABI for variadic functions. This is the first in a set of patches
for soft float support in LLVM.
Patch by Strahinja Petrovic.
Differential Revision: http://reviews.llvm.org/D13351
Added:
cfe/trunk/test/CodeGen/ppc-sfvarargs.c
Modified:
cfe/trunk/lib/CodeGen/TargetInfo.cpp
cfe/trunk/lib/Driver/Tools.cpp
cfe/trunk/lib/Driver/Tools.h
cfe/trunk/test/Driver/ppc-features.cpp
Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=255515&r1=255514&r2=255515&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Mon Dec 14 11:51:50 2015
@@ -3413,8 +3413,10 @@ Address WinX86_64ABIInfo::EmitVAArg(Code
namespace {
/// PPC32_SVR4_ABIInfo - The 32-bit PowerPC ELF (SVR4) ABI information.
class PPC32_SVR4_ABIInfo : public DefaultABIInfo {
+bool IsSoftFloatABI;
public:
- PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
+ PPC32_SVR4_ABIInfo(CodeGen::CodeGenTypes &CGT, bool SoftFloatABI)
+ : DefaultABIInfo(CGT), IsSoftFloatABI(SoftFloatABI) {}
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override;
@@ -3422,8 +3424,8 @@ public:
class PPC32TargetCodeGenInfo : public TargetCodeGenInfo {
public:
- PPC32TargetCodeGenInfo(CodeGenTypes &CGT)
- : TargetCodeGenInfo(new PPC32_SVR4_ABIInfo(CGT)) {}
+ PPC32TargetCodeGenInfo(CodeGenTypes &CGT, bool SoftFloatABI)
+ : TargetCodeGenInfo(new PPC32_SVR4_ABIInfo(CGT, SoftFloatABI)) {}
int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
// This is recovered from gcc output.
@@ -3455,6 +3457,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(Co
bool isI64 = Ty->isIntegerType() && getContext().getTypeSize(Ty) == 64;
bool isInt =
Ty->isIntegerType() || Ty->isPointerType() || Ty->isAggregateType();
+ bool isF64 = Ty->isFloatingType() && getContext().getTypeSize(Ty) == 64;
// All aggregates are passed indirectly? That doesn't seem consistent
// with the argument-lowering code.
@@ -3464,7 +3467,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(Co
// The calling convention either uses 1-2 GPRs or 1 FPR.
Address NumRegsAddr = Address::invalid();
- if (isInt) {
+ if (isInt || IsSoftFloatABI) {
NumRegsAddr = Builder.CreateStructGEP(VAList, 0, CharUnits::Zero(), "gpr");
} else {
NumRegsAddr = Builder.CreateStructGEP(VAList, 1, CharUnits::One(), "fpr");
@@ -3473,7 +3476,7 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(Co
llvm::Value *NumRegs = Builder.CreateLoad(NumRegsAddr, "numUsedRegs");
// "Align" the register count when TY is i64.
- if (isI64) {
+ if (isI64 || (isF64 && IsSoftFloatABI)) {
NumRegs = Builder.CreateAdd(NumRegs, Builder.getInt8(1));
NumRegs = Builder.CreateAnd(NumRegs, Builder.getInt8((uint8_t) ~1U));
}
@@ -3502,14 +3505,14 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(Co
assert(RegAddr.getElementType() == CGF.Int8Ty);
// Floating-point registers start after the general-purpose registers.
- if (!isInt) {
+ if (!(isInt || IsSoftFloatABI)) {
RegAddr = Builder.CreateConstInBoundsByteGEP(RegAddr,
CharUnits::fromQuantity(32));
}
// Get the address of the saved value by scaling the number of
// registers we've used by the number of
- CharUnits RegSize = CharUnits::fromQuantity(isInt ? 4 : 8);
+ CharUnits RegSize = CharUnits::fromQuantity((isInt || IsSoftFloatABI) ? 4 : 8);
llvm::Value *RegOffset =
Builder.CreateMul(NumRegs, Builder.getInt8(RegSize.getQuantity()));
RegAddr = Address(Builder.CreateInBoundsGEP(CGF.Int8Ty,
@@ -3518,7 +3521,9 @@ Address PPC32_SVR4_ABIInfo::EmitVAArg(Co
RegAddr = Builder.CreateElementBitCast(RegAddr, DirectTy);
// Increase the used-register count.
- NumRegs = Builder.CreateAdd(NumRegs, Builder.getInt8(isI64 ? 2 : 1));
+ NumRegs =
+ Builder.CreateAdd(NumRegs,
+ Builder.getInt8((isI64 || (isF64 && IsSoftFloatABI)) ? 2 : 1));
Builder.CreateStore(NumRegs, NumRegsAddr);
CGF.EmitBranch(Cont);
@@ -7471,7 +7476,8 @@ const TargetCodeGenInfo &CodeGenModule::
}
case llvm::Triple::ppc:
- return *(TheTargetCodeGenInfo = new PPC32TargetCodeGenInfo(Types));
+ return *(TheTargetCodeGenInfo =
+ new PPC32TargetCodeGenInfo(Types, CodeGenOpts.FloatABI == "soft"));
case llvm::Triple::ppc64:
if (Triple.isOSBinFormatELF()) {
PPC64_SVR4_ABIInfo::ABIKind Kind = PPC64_SVR4_ABIInfo::ELFv1;
Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=255515&r1=255514&r2=255515&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Mon Dec 14 11:51:50 2015
@@ -1407,7 +1407,8 @@ static std::string getPPCTargetCPU(const
return "";
}
-static void getPPCTargetFeatures(const ArgList &Args,
+static void getPPCTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+ const ArgList &Args,
std::vector<const char *> &Features) {
for (const Arg *A : Args.filtered(options::OPT_m_ppc_Features_Group)) {
StringRef Name = A->getOption().getName();
@@ -1431,11 +1432,51 @@ static void getPPCTargetFeatures(const A
Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
}
+ ppc::FloatABI FloatABI = ppc::getPPCFloatABI(D, Args);
+ if (FloatABI == ppc::FloatABI::Soft &&
+ !(Triple.getArch() == llvm::Triple::ppc64 ||
+ Triple.getArch() == llvm::Triple::ppc64le))
+ Features.push_back("+soft-float");
+ else if (FloatABI == ppc::FloatABI::Soft &&
+ (Triple.getArch() == llvm::Triple::ppc64 ||
+ Triple.getArch() == llvm::Triple::ppc64le))
+ D.Diag(diag::err_drv_invalid_mfloat_abi)
+ << "soft float is not supported for ppc64";
+
// Altivec is a bit weird, allow overriding of the Altivec feature here.
AddTargetFeature(Args, Features, options::OPT_faltivec,
options::OPT_fno_altivec, "altivec");
}
+ppc::FloatABI ppc::getPPCFloatABI(const Driver &D, const ArgList &Args) {
+ ppc::FloatABI ABI = ppc::FloatABI::Invalid;
+ if (Arg *A =
+ Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+ options::OPT_mfloat_abi_EQ)) {
+ if (A->getOption().matches(options::OPT_msoft_float))
+ ABI = ppc::FloatABI::Soft;
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ ABI = ppc::FloatABI::Hard;
+ else {
+ ABI = llvm::StringSwitch<ppc::FloatABI>(A->getValue())
+ .Case("soft", ppc::FloatABI::Soft)
+ .Case("hard", ppc::FloatABI::Hard)
+ .Default(ppc::FloatABI::Invalid);
+ if (ABI == ppc::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
+ D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
+ ABI = ppc::FloatABI::Hard;
+ }
+ }
+ }
+
+ // If unspecified, choose the default based on the platform.
+ if (ABI == ppc::FloatABI::Invalid) {
+ ABI = ppc::FloatABI::Hard;
+ }
+
+ return ABI;
+}
+
void Clang::AddPPCTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Select the ABI to use.
@@ -1472,6 +1513,21 @@ void Clang::AddPPCTargetArgs(const ArgLi
if (StringRef(A->getValue()) != "altivec")
ABIName = A->getValue();
+ ppc::FloatABI FloatABI =
+ ppc::getPPCFloatABI(getToolChain().getDriver(), Args);
+
+ if (FloatABI == ppc::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 == ppc::FloatABI::Hard && "Invalid float abi!");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("hard");
+ }
+
if (ABIName) {
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
@@ -2248,7 +2304,7 @@ static void getTargetFeatures(const Tool
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
- getPPCTargetFeatures(Args, Features);
+ getPPCTargetFeatures(D, Triple, Args, Features);
break;
case llvm::Triple::systemz:
getSystemZTargetFeatures(Args, Features);
Modified: cfe/trunk/lib/Driver/Tools.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.h?rev=255515&r1=255514&r2=255515&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.h (original)
+++ cfe/trunk/lib/Driver/Tools.h Mon Dec 14 11:51:50 2015
@@ -742,6 +742,16 @@ enum class FloatABI {
FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args);
} // end namespace arm
+namespace ppc {
+enum class FloatABI {
+ Invalid,
+ Soft,
+ Hard,
+};
+
+FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
+} // end namespace ppc
+
namespace XCore {
// For XCore, we do not need to instantiate tools for PreProcess, PreCompile and
// Compile.
Added: cfe/trunk/test/CodeGen/ppc-sfvarargs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ppc-sfvarargs.c?rev=255515&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/ppc-sfvarargs.c (added)
+++ cfe/trunk/test/CodeGen/ppc-sfvarargs.c Mon Dec 14 11:51:50 2015
@@ -0,0 +1,17 @@
+// RUN: %clang -O0 --target=powerpc-unknown-linux-gnu -EB -msoft-float -S -emit-llvm %s -o - | FileCheck %s
+
+#include <stdarg.h>
+void test(char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ va_arg(ap, double);
+ va_end(ap);
+}
+
+void foo() {
+ double a;
+ test("test",a);
+}
+// CHECK: %{{[0-9]+}} = add i8 %numUsedRegs, 1
+// CHECK: %{{[0-9]+}} = and i8 %{{[0-9]+}}, -2
+// CHECK: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, 4
\ No newline at end of file
Modified: cfe/trunk/test/Driver/ppc-features.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/ppc-features.cpp?rev=255515&r1=255514&r2=255515&view=diff
==============================================================================
--- cfe/trunk/test/Driver/ppc-features.cpp (original)
+++ cfe/trunk/test/Driver/ppc-features.cpp Mon Dec 14 11:51:50 2015
@@ -12,6 +12,50 @@
// RUN: not %clang -target mips64-linux-gnu -faltivec -fsyntax-only %s 2>&1 | FileCheck %s
// RUN: not %clang -target sparc-unknown-solaris -faltivec -fsyntax-only %s 2>&1 | FileCheck %s
+// check -msoft-float option for ppc32
+// RUN: %clang -target powerpc-unknown-linux-gnu %s -msoft-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-SOFTFLOAT %s
+// CHECK-SOFTFLOAT: "-target-feature" "+soft-float"
+
+// check -mfloat-abi=soft option for ppc32
+// RUN: %clang -target powerpc-unknown-linux-gnu %s -mfloat-abi=soft -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-FLOATABISOFT %s
+// CHECK-FLOATABISOFT: "-target-feature" "+soft-float"
+
+// check -mhard-float option for ppc32
+// RUN: %clang -target powerpc-unknown-linux-gnu %s -mhard-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-HARDFLOAT %s
+// CHECK-HARDFLOAT-NOT: "-target-feature" "+soft-float"
+
+// check -mfloat-abi=hard option for ppc32
+// RUN: %clang -target powerpc-unknown-linux-gnu %s -mfloat-abi=hard -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-FLOATABIHARD %s
+// CHECK-FLOATABIHARD-NOT: "-target-feature" "+soft-float"
+
+// check combine -mhard-float -msoft-float option for ppc32
+// RUN: %clang -target powerpc-unknown-linux-gnu %s -mhard-float -msoft-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-HARDSOFT %s
+// CHECK-HARDSOFT: "-target-feature" "+soft-float"
+
+// check combine -msoft-float -mhard-float option for ppc32
+// RUN: %clang -target powerpc-unknown-linux-gnu %s -msoft-float -mhard-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-SOFTHARD %s
+// CHECK-SOFTHARD-NOT: "-target-feature" "+soft-float"
+
+// check -mfloat-abi=x option
+// RUN: %clang -target powerpc-unknown-linux-gnu %s -mfloat-abi=x -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-ERRMSG %s
+// CHECK-ERRMSG: clang: error: invalid float ABI '-mfloat-abi=x'
+
+// check -msoft-float option for ppc64
+// RUN: %clang -target powerpc64-unknown-linux-gnu %s -msoft-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-SOFTFLOAT64 %s
+// CHECK-SOFTFLOAT64: clang: error: invalid float ABI 'soft float is not supported for ppc64'
+
+// check -mfloat-abi=soft option for ppc64
+// RUN: %clang -target powerpc64-unknown-linux-gnu %s -mfloat-abi=soft -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-FLOATABISOFT64 %s
+// CHECK-FLOATABISOFT64: clang: error: invalid float ABI 'soft float is not supported for ppc64'
+
+// check -msoft-float option for ppc64
+// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -msoft-float -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-SOFTFLOAT64le %s
+// CHECK-SOFTFLOAT64le: clang: error: invalid float ABI 'soft float is not supported for ppc64'
+
+// check -mfloat-abi=soft option for ppc64
+// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -mfloat-abi=soft -### -o %t.o 2>&1 | FileCheck --check-prefix=CHECK-FLOATABISOFT64le %s
+// CHECK-FLOATABISOFT64le: clang: error: invalid float ABI 'soft float is not supported for ppc64'
+
// CHECK: invalid argument '-faltivec' only allowed with 'ppc/ppc64/ppc64le'
// Check that -fno-altivec and -mno-altivec correctly disable the altivec
More information about the cfe-commits
mailing list