Index: lib/Driver/ToolChains/Arch/ARM.cpp =================================================================== --- lib/Driver/ToolChains/Arch/ARM.cpp +++ lib/Driver/ToolChains/Arch/ARM.cpp @@ -246,7 +246,7 @@ case llvm::Triple::MuslEABI: case llvm::Triple::EABI: // EABI is always AAPCS, and if it was not marked 'hard', it's softfp - ABI = FloatABI::SoftFP; + ABI = FloatABI::Soft; break; case llvm::Triple::Android: ABI = (SubArch == 7) ? FloatABI::SoftFP : FloatABI::Soft; Index: lib/Driver/ToolChains/Gnu.cpp =================================================================== --- lib/Driver/ToolChains/Gnu.cpp +++ lib/Driver/ToolChains/Gnu.cpp @@ -808,9 +808,22 @@ if (!A) return false; + // ARM GNUEABI allows a "softfp" ABI (compatible with soft-float calling + // conventions, but can still generate FPU instructions inside functions). return A->getOption().matches(options::OPT_msoft_float) || (A->getOption().matches(options::OPT_mfloat_abi_EQ) && - A->getValue() == StringRef("soft")); + (A->getValue() == StringRef("soft") || A->getValue() == StringRef("softfp"))); +} + +static bool isHardFloatABI(const ArgList &Args) { + Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ); + if (!A) + return false; + + return A->getOption().matches(options::OPT_mhard_float) || + (A->getOption().matches(options::OPT_mfloat_abi_EQ) && + A->getValue() == StringRef("hard")); } /// \p Flag must be a flag accepted by the driver with its leading '-' removed, @@ -1425,6 +1438,75 @@ Result.Multilibs = RISCVMultilibs; } +static bool findArmEABIMultilibs(const Driver &D, + const llvm::Triple &TargetTriple, + StringRef Path, const ArgList &Args, + DetectedMultilibs &Result) { + // Find multilibs with subdirectories like hf (for hard-float) or sf (for + // soft-float). gcc also allows for "-mfloat-abi=softfp": ABI-equivalent + // to soft-float, but can still generate FPU instuctions inside functions. + // softfp usually has the same multilib subdirectory as soft-float. + Multilib Default; + bool DefaultHardFloat = TargetTriple.isHardFloatEABI(); + llvm::Triple AltTriple(DefaultHardFloat ? + TargetTriple.getSoftFloatArchVariant() : + TargetTriple.getHardFloatArchVariant()); + // We assume the Debian libdir/includedir arrangement for armel/armhf, + // since Debian and its descendents are apparently the only common Linux + // distros that have anything resembling multilib support for this scenario. + // SuSE and RedHat seem to stick with hard-float only and no libdir suffix. + // TODO: this (and a lot of other code here) could be generalized via the + // output of "gcc --print-multi-os-dir". + Multilib ArmHFMultilib = makeMultilib("/hf") + .osSuffix("/" + TargetTriple.getHardFloatArchVariant().str()) + .includeSuffix("/" + TargetTriple.getHardFloatArchVariant().str()) + .flag("+mhard-float") + .flag("+mfloat-abi=hard") + .flag("-msoft-float") + .flag("-mfloat-abi=soft") + .flag("-mfloat-abi=softfp"); + Multilib ArmSFMultilib = makeMultilib("/sf") + .osSuffix("/" + TargetTriple.getSoftFloatArchVariant().str()) + .includeSuffix("/" + TargetTriple.getSoftFloatArchVariant().str()) + .flag("+msoft-float") + .flag("+mfloat-abi=soft") + .flag("+mfloat-abi=softfp") + .flag("-mhard-float") + .flag("-mfloat-abi=hard"); + + FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS()); + + if (DefaultHardFloat) + Default.flag("+mhard-float") + .flag("+mfloat-abi=hard") + .flag("-msoft-float") + .flag("-mfloat-abi=soft") + .flag("-mfloat-abi=softfp"); + else + Default.flag("+msoft-float") + .flag("+mfloat-abi=soft") + .flag("+mfloat-abi=softfp") + .flag("-mhard-float") + .flag("-mfloat-abi=hard"); + + Result.Multilibs.push_back(Default); + Result.Multilibs.push_back(ArmHFMultilib); + Result.Multilibs.push_back(ArmSFMultilib); + Result.Multilibs.FilterOut(NonExistent); + + Multilib::flags_list Flags; + addMultilibFlag(isSoftFloatABI(Args), "msoft-float", Flags); + addMultilibFlag(isHardFloatABI(Args), "mhard-float", Flags); + + if (!Result.Multilibs.select(Flags, Result.SelectedMultilib)) + return false; + + if (Result.SelectedMultilib == ArmSFMultilib || Result.SelectedMultilib == ArmHFMultilib) + Result.BiarchSibling = Default; + + return true; +} + static bool findBiarchMultilibs(const Driver &D, const llvm::Triple &TargetTriple, StringRef Path, const ArgList &Args, @@ -1637,9 +1719,21 @@ void Generic_GCC::GCCInstallationDetector::init( const llvm::Triple &TargetTriple, const ArgList &Args, ArrayRef ExtraTripleAliases) { - llvm::Triple BiarchVariantTriple = TargetTriple.isArch32Bit() - ? TargetTriple.get64BitArchVariant() - : TargetTriple.get32BitArchVariant(); + llvm::Triple BiarchVariantTriple; + + // Triples with an EABI environment are normally biarch-by-FPU rather + // than biarch-by-wordsize. + if (TargetTriple.isEABI()) { + BiarchVariantTriple = TargetTriple.isHardFloatEABI() + ? TargetTriple.getSoftFloatArchVariant() + : TargetTriple.getHardFloatArchVariant(); + } + else { + BiarchVariantTriple = TargetTriple.isArch32Bit() + ? TargetTriple.get64BitArchVariant() + : TargetTriple.get32BitArchVariant(); + } + // The library directories which may contain GCC installations. SmallVector CandidateLibDirs, CandidateBiarchLibDirs; // The compatible GCC triples for this particular architecture. @@ -2137,6 +2231,9 @@ if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) { // It should also work without multilibs in a simplified toolchain. findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected); + } else if (isArmOrThumbArch(TargetArch) && TargetTriple.isEABI()) { + if (!findArmEABIMultilibs(D, TargetTriple, Path, Args, Detected)) + return false; } else if (TargetTriple.isMIPS()) { if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected)) return false; Index: lib/Driver/ToolChains/Linux.cpp =================================================================== --- lib/Driver/ToolChains/Linux.cpp +++ lib/Driver/ToolChains/Linux.cpp @@ -533,8 +533,9 @@ case llvm::Triple::thumb: case llvm::Triple::armeb: case llvm::Triple::thumbeb: { + // NOTE: If no float-ABI selector flags are in use, getARMFloatABI() + // will fall back on determining ABI by Triple.getEnvironment(). const bool HF = - Triple.getEnvironment() == llvm::Triple::GNUEABIHF || tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard; LibDir = "lib";