diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 60 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.h | 10 |
3 files changed, 83 insertions, 11 deletions
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 290a0755d63..1e262ccbb9c 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -3413,8 +3413,10 @@ Address WinX86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 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(CodeGenFunction &CGF, Address VAList, 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(CodeGenFunction &CGF, Address VAList, // 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(CodeGenFunction &CGF, Address VAList, 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(CodeGenFunction &CGF, Address VAList, 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(CodeGenFunction &CGF, Address VAList, 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::getTargetCodeGenInfo() { } 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; diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 7a02a115b88..f843ec4a0c7 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -1407,7 +1407,8 @@ static std::string getPPCTargetCPU(const ArgList &Args) { 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 ArgList &Args, 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 ArgList &Args, 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 ToolChain &TC, const llvm::Triple &Triple, 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); diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h index 95c2063695c..7d6e2a11326 100644 --- a/clang/lib/Driver/Tools.h +++ b/clang/lib/Driver/Tools.h @@ -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. |