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 ) {
+ 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 ,
+ const llvm::Triple ,
+ StringRef Path, const ArgList ,
+ DetectedMultilibs ) {
+ // 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("/" +