spetrovic created this revision.
spetrovic added a reviewer: hfinkel.
spetrovic added a subscriber: cfe-commits.
This patch enables soft float support for ppc32 architecture and fixes the ABI
for variadic functions. This is first in set of patches for soft float support
in LLVM.
http://reviews.llvm.org/D13351
Files:
include/clang/Basic/TargetInfo.h
lib/Basic/Targets.cpp
lib/CodeGen/TargetInfo.cpp
lib/Driver/Tools.cpp
lib/Driver/Tools.h
test/CodeGen/ppc-sfvarargs.c
test/Driver/ppc-features.cpp
Index: test/Driver/ppc-features.cpp
===================================================================
--- test/Driver/ppc-features.cpp
+++ test/Driver/ppc-features.cpp
@@ -12,6 +12,10 @@
// 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 soft float option only 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: invalid argument '-faltivec' only allowed with 'ppc/ppc64/ppc64le'
// Check that -fno-altivec and -mno-altivec correctly disable the altivec
Index: test/CodeGen/ppc-sfvarargs.c
===================================================================
--- test/CodeGen/ppc-sfvarargs.c
+++ test/CodeGen/ppc-sfvarargs.c
@@ -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
Index: lib/Driver/Tools.h
===================================================================
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -728,6 +728,10 @@
FloatABI getARMFloatABI(const ToolChain &TC, const llvm::opt::ArgList &Args);
}
+
+namespace ppc {
+ StringRef getPPCFloatABI(const llvm::opt::ArgList &Args);
+}
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
@@ -1344,15 +1344,44 @@
// TODO: Change the LLVM backend option maybe?
if (Name == "mfcrf")
Name = "mfocrf";
-
+
Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
}
+ StringRef FloatABI = ppc::getPPCFloatABI(Args);
+ if (FloatABI == "soft")
+ Features.push_back("+soft-float");
+
// Altivec is a bit weird, allow overriding of the Altivec feature here.
AddTargetFeature(Args, Features, options::OPT_faltivec,
options::OPT_fno_altivec, "altivec");
}
+StringRef ppc::getPPCFloatABI(const ArgList &Args) {
+ StringRef FloatABI;
+ 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))
+ FloatABI = "soft";
+ else if (A->getOption().matches(options::OPT_mhard_float))
+ FloatABI = "hard";
+ else {
+ FloatABI = A->getValue();
+ if (FloatABI != "soft" && FloatABI != "hard") {
+ FloatABI = "hard";
+ }
+ }
+ }
+
+ // If unspecified, choose the default based on the platform.
+ if (FloatABI.empty()) {
+ FloatABI = "hard";
+ }
+
+ return FloatABI;
+}
+
void Clang::AddPPCTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
// Select the ABI to use.
@@ -1389,10 +1418,26 @@
if (StringRef(A->getValue()) != "altivec")
ABIName = A->getValue();
+ StringRef FloatABI = ppc::getPPCFloatABI(Args);
+
+ if (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 == "hard" && "Invalid float abi!");
+ CmdArgs.push_back("-mfloat-abi");
+ CmdArgs.push_back("hard");
+ }
+
if (ABIName) {
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName);
}
+
}
bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) {
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -3422,6 +3422,8 @@
bool isI64 = Ty->isIntegerType() && getContext().getTypeSize(Ty) == 64;
bool isInt =
Ty->isIntegerType() || Ty->isPointerType() || Ty->isAggregateType();
+ bool isF64 = Ty->isFloatingType() && getContext().getTypeSize(Ty) == 64;
+ bool isSF = getTarget().isSoftFloatABI();
// All aggregates are passed indirectly? That doesn't seem consistent
// with the argument-lowering code.
@@ -3431,16 +3433,16 @@
// The calling convention either uses 1-2 GPRs or 1 FPR.
Address NumRegsAddr = Address::invalid();
- if (isInt) {
+ if (isInt || isSF) {
NumRegsAddr = Builder.CreateStructGEP(VAList, 0, CharUnits::Zero(), "gpr");
} else {
NumRegsAddr = Builder.CreateStructGEP(VAList, 1, CharUnits::One(), "fpr");
}
llvm::Value *NumRegs = Builder.CreateLoad(NumRegsAddr, "numUsedRegs");
// "Align" the register count when TY is i64.
- if (isI64) {
+ if (isI64 || (isF64 && isSF)) {
NumRegs = Builder.CreateAdd(NumRegs, Builder.getInt8(1));
NumRegs = Builder.CreateAnd(NumRegs, Builder.getInt8((uint8_t) ~1U));
}
@@ -3469,23 +3471,23 @@
assert(RegAddr.getElementType() == CGF.Int8Ty);
// Floating-point registers start after the general-purpose registers.
- if (!isInt) {
+ if (!(isInt || isSF)) {
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 || isSF) ? 4 : 8);
llvm::Value *RegOffset =
Builder.CreateMul(NumRegs, Builder.getInt8(RegSize.getQuantity()));
RegAddr = Address(Builder.CreateInBoundsGEP(CGF.Int8Ty,
RegAddr.getPointer(), RegOffset),
RegAddr.getAlignment().alignmentOfArrayElement(RegSize));
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 && isSF)) ? 2 : 1));
Builder.CreateStore(NumRegs, NumRegsAddr);
CGF.EmitBranch(Cont);
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp
+++ lib/Basic/Targets.cpp
@@ -770,6 +770,7 @@
std::string CPU;
// Target cpu features.
+ bool isSoftFloat;
bool HasVSX;
bool HasP8Vector;
bool HasP8Crypto;
@@ -784,7 +785,7 @@
public:
PPCTargetInfo(const llvm::Triple &Triple)
- : TargetInfo(Triple), HasVSX(false), HasP8Vector(false),
+ : TargetInfo(Triple), isSoftFloat(false), HasVSX(false), HasP8Vector(false),
HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false),
HasBPERMD(false), HasExtDiv(false) {
BigEndian = (Triple.getArch() != llvm::Triple::ppc64le);
@@ -873,7 +874,7 @@
return CPUKnown;
}
-
+ bool isSoftFloatABI() const override {return isSoftFloat;}
StringRef getABI() const override { return ABI; }
void getTargetBuiltins(const Builtin::Info *&Records,
@@ -1068,6 +1069,11 @@
// all.
}
+ auto Feature = std::find(Features.begin(), Features.end(), "+soft-float");
+ if (Feature != Features.end()) {
+ isSoftFloat = true;
+ }
+
return true;
}
Index: include/clang/Basic/TargetInfo.h
===================================================================
--- include/clang/Basic/TargetInfo.h
+++ include/clang/Basic/TargetInfo.h
@@ -685,6 +685,10 @@
return std::string(1, *Constraint);
}
+ virtual bool isSoftFloatABI() const {
+ return false;
+ }
+
/// \brief Returns a string of target-specific clobbers, in LLVM format.
virtual const char *getClobbers() const = 0;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits