kelledin created this revision.
Herald added a reviewer: javed.absar.
Herald added subscribers: cfe-commits, chrib, kristof.beyls.

  This is my first crack at implementing working ARM EABI multilib support
  (where multilib support is between hard/soft float ONLY, not between 32-bit
  and 64-bit).  This is currently NOT suitable for merging; I'm only posting
  it for guidance as to what exactly I'm missing.  Specifically, for the
  default-hardfloat target (arm-linux-gnueabihf), clang selects the correct
  GCC suffix (/sf vs /hf) but consistently selects /usr/lib/arm-linux-gnueabihf
  as the library directory, even if soft-float flags are passed.  This leaves
  binutils trying to mix hard-float/soft-float objects, which of course fails
  miserably.  AIUI the multilib driver *should* trigger the selection of
  /usr/lib/arm-linux-gnueabi instead.
  
  I can produce verbose output from clang's behavior upon request.  Be aware
  that this changeset depends on https://reviews.llvm.org/D52149 for 
compiler-rt.


Repository:
  rC Clang

https://reviews.llvm.org/D52705

Files:
  lib/Driver/ToolChains/Arch/ARM.cpp
  lib/Driver/ToolChains/Gnu.cpp
  lib/Driver/ToolChains/Linux.cpp

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";
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 <flags> --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<std::string> 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<StringRef, 4> 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/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;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to