Hi,

We're trying to make using the OS X equivalent of an "arm-none-eabi" compiler 
simpler for users, and this patch should teach clang how to automatically link 
against the embedded libclang_rt builds I created recently.

The patch here is an interim solution, based on the fact that the triples 
involved are "*-*-darwin-eabi" at the moment. Longer term, this is an incorrect 
characterisation (they're not Darwin) and I'm planning to separate out the 
MachO specific toolchain pieces from the Darwin ones along more sensible lines, 
and start using "*-*-none-macho" as the triple.

But I think that the refactoring needed to support this patch will actually 
leave the interfaces cleaner even after the embedded part is stripped out (IOS, 
IOSSim and MacOSX are mutually exclusive and will cover the 
configuration-space, making an inconsistent check like "isIOSSim && isMacOSX" 
impossible).

Does this look good?

Cheers.

Tim.

http://llvm-reviews.chandlerc.com/D2380

Files:
  lib/Driver/ToolChains.cpp
  lib/Driver/ToolChains.h
  lib/Driver/Tools.cpp
Index: lib/Driver/ToolChains.cpp
===================================================================
--- lib/Driver/ToolChains.cpp
+++ lib/Driver/ToolChains.cpp
@@ -83,19 +83,23 @@
 
 /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
 ObjCRuntime Darwin::getDefaultObjCRuntime(bool isNonFragile) const {
-  if (isTargetIPhoneOS())
+  if (isTargetIOSBased())
     return ObjCRuntime(ObjCRuntime::iOS, TargetVersion);
   if (isNonFragile)
     return ObjCRuntime(ObjCRuntime::MacOSX, TargetVersion);
   return ObjCRuntime(ObjCRuntime::FragileMacOSX, TargetVersion);
 }
 
 /// Darwin provides a blocks runtime starting in MacOS X 10.6 and iOS 3.2.
 bool Darwin::hasBlocksRuntime() const {
-  if (isTargetIPhoneOS())
+  if (isTargetIOSBased())
     return !isIPhoneOSVersionLT(3, 2);
-  else
+  else if (isTargetMacOS())
     return !isMacosxVersionLT(10, 6);
+  else {
+    assert(isTargetEmbedded() && "unexpected target platform");
+    return false;
+  }
 }
 
 static const char *GetArmArchForMArch(StringRef Value) {
@@ -134,6 +138,17 @@
     .Default(0);
 }
 
+static bool isSoftFloatABI(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_msoft_float) ||
+         (A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
+          A->getValue() == StringRef("soft"));
+}
+
 StringRef Darwin::getDarwinArchName(const ArgList &Args) const {
   switch (getTriple().getArch()) {
   default:
@@ -174,7 +189,7 @@
     Triple.setEnvironment(llvm::Triple::EABI);
   } else {
     SmallString<16> Str;
-    Str += isTargetIPhoneOS() ? "ios" : "macosx";
+    Str += isTargetIOSBased() ? "ios" : "macosx";
     Str += getTargetVersion().getAsString();
     Triple.setOSName(Str);
   }
@@ -247,10 +262,12 @@
 
 void DarwinClang::AddLinkRuntimeLib(const ArgList &Args,
                                     ArgStringList &CmdArgs,
-                                    const char *DarwinStaticLib,
-                                    bool AlwaysLink) const {
+                                    StringRef DarwinStaticLib,
+                                    bool AlwaysLink,
+                                    bool IsEmbedded) const {
   SmallString<128> P(getDriver().ResourceDir);
-  llvm::sys::path::append(P, "lib", "darwin", DarwinStaticLib);
+  llvm::sys::path::append(P, "lib", IsEmbedded ? "darwin_embedded" : "darwin",
+                          DarwinStaticLib);
 
   // For now, allow missing resource libraries to support developers who may
   // not have compiler-rt checked out or integrated into their build (unless
@@ -271,6 +288,18 @@
     return;
   }
 
+  if (isTargetEmbedded()) {
+    // Embedded targets are simple at the moment, not supporting sanitizers and
+    // with different libraries for each member of the product { static, PIC } x
+    // { hard-float, soft-float }
+    llvm::SmallString<32> CompilerRT = StringRef("libclang_rt.");
+    CompilerRT += isSoftFloatABI(Args) ? "soft_" : "hard_";
+    CompilerRT += Args.hasArg(options::OPT_fPIC) ? "pic.a" : "static.a";
+
+    AddLinkRuntimeLib(Args, CmdArgs, CompilerRT, false, true);
+    return;
+  }
+
   // Darwin doesn't support real static executables, don't link any runtime
   // libraries with -static.
   if (Args.hasArg(options::OPT_static) ||
@@ -293,7 +322,7 @@
       Args.hasArg(options::OPT_fcreate_profile) ||
       Args.hasArg(options::OPT_coverage)) {
     // Select the appropriate runtime library for the target.
-    if (isTargetIPhoneOS()) {
+    if (isTargetIOSBased()) {
       AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a");
     } else {
       AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_osx.a");
@@ -305,10 +334,11 @@
   // Add Ubsan runtime library, if required.
   if (Sanitize.needsUbsanRt()) {
     // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
-    if (isTargetIPhoneOS()) {
+    if (isTargetIOSBased()) {
       getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
         << "-fsanitize=undefined";
     } else {
+      assert(isTargetMacOS() && "unexpected non OS X target");
       AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ubsan_osx.a", true);
 
       // The Ubsan runtime library requires C++.
@@ -320,7 +350,7 @@
   // should not be linked with the runtime library.
   if (Sanitize.needsAsanRt()) {
     // FIXME: Move this check to SanitizerArgs::filterUnsupportedKinds.
-    if (isTargetIPhoneOS() && !isTargetIOSSimulator()) {
+    if (isTargetIPhoneOS()) {
       getDriver().Diag(diag::err_drv_clang_unsupported_per_platform)
         << "-fsanitize=address";
     } else {
@@ -348,7 +378,7 @@
   CmdArgs.push_back("-lSystem");
 
   // Select the dynamic runtime library and the target specific static library.
-  if (isTargetIPhoneOS()) {
+  if (isTargetIOSBased()) {
     // If we are compiling as iOS / simulator, don't attempt to link libgcc_s.1,
     // it never went into the SDK.
     // Linking against libgcc_s.1 isn't needed for iOS 5.0+
@@ -358,6 +388,7 @@
     // We currently always need a static runtime library for iOS.
     AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.ios.a");
   } else {
+    assert(isTargetMacOS() && "unexpected non MacOS platform");
     // The dynamic runtime library was merged with libSystem for 10.6 and
     // beyond; only 10.4 and 10.5 need an additional runtime library.
     if (isMacosxVersionLT(10, 5))
@@ -448,9 +479,9 @@
 
     // If no OSX or iOS target has been specified and we're compiling for armv7,
     // go ahead as assume we're targeting iOS.
+    StringRef DarwinArchName = getDarwinArchName(Args);
     if (OSXTarget.empty() && iOSTarget.empty() &&
-        (getDarwinArchName(Args) == "armv7" ||
-         getDarwinArchName(Args) == "armv7s"))
+        (DarwinArchName == "armv7" || DarwinArchName == "armv7s"))
         iOSTarget = iOSVersionMin;
 
     // Handle conflicting deployment targets
@@ -488,14 +519,25 @@
         options::OPT_mios_simulator_version_min_EQ);
       iOSSimVersion = Args.MakeJoinedArg(0, O, iOSSimTarget);
       Args.append(iOSSimVersion);
-    } else {
+    } else if (DarwinArchName != "armv6m" && DarwinArchName != "armv7m" &&
+               DarwinArchName != "armv7em") {
       // Otherwise, assume we are targeting OS X.
       const Option O = Opts.getOption(options::OPT_mmacosx_version_min_EQ);
       OSXVersion = Args.MakeJoinedArg(0, O, MacosxVersionMin);
       Args.append(OSXVersion);
     }
   }
 
+  DarwinPlatformKind Platform;
+  if (OSXVersion)
+    Platform = MacOS;
+  else if (iOSVersion)
+    Platform = IPhoneOS;
+  else if (iOSSimVersion)
+    Platform = IPhoneOSSimulator;
+  else
+    Platform = Embedded;
+
   // Reject invalid architecture combinations.
   if (iOSSimVersion && (getTriple().getArch() != llvm::Triple::x86 &&
                         getTriple().getArch() != llvm::Triple::x86_64)) {
@@ -506,34 +548,35 @@
   // Set the tool chain target information.
   unsigned Major, Minor, Micro;
   bool HadExtra;
-  if (OSXVersion) {
+  if (Platform == MacOS) {
     assert((!iOSVersion && !iOSSimVersion) && "Unknown target platform!");
     if (!Driver::GetReleaseVersion(OSXVersion->getValue(), Major, Minor,
                                    Micro, HadExtra) || HadExtra ||
         Major != 10 || Minor >= 100 || Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
         << OSXVersion->getAsString(Args);
-  } else {
+  } else if (Platform == IPhoneOS || Platform == IPhoneOSSimulator) {
     const Arg *Version = iOSVersion ? iOSVersion : iOSSimVersion;
     assert(Version && "Unknown target platform!");
     if (!Driver::GetReleaseVersion(Version->getValue(), Major, Minor,
                                    Micro, HadExtra) || HadExtra ||
         Major >= 10 || Minor >= 100 || Micro >= 100)
       getDriver().Diag(diag::err_drv_invalid_version_number)
         << Version->getAsString(Args);
+  } else {
+    assert(Platform == Embedded && "unexpected platform");
+    Major = Minor = Micro = 0;
   }
 
-  bool IsIOSSim = bool(iOSSimVersion);
-
   // In GCC, the simulator historically was treated as being OS X in some
   // contexts, like determining the link logic, despite generally being called
   // with an iOS deployment target. For compatibility, we detect the
   // simulator as iOS + x86, and treat it differently in a few contexts.
   if (iOSVersion && (getTriple().getArch() == llvm::Triple::x86 ||
                      getTriple().getArch() == llvm::Triple::x86_64))
-    IsIOSSim = true;
+    Platform = IPhoneOSSimulator;
 
-  setTarget(/*IsIPhoneOS=*/ !OSXVersion, Major, Minor, Micro, IsIOSSim);
+  setTarget(Platform, Major, Minor, Micro);
 }
 
 void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args,
@@ -837,7 +880,7 @@
   // FIXME: It would be far better to avoid inserting those -static arguments,
   // but we can't check the deployment target in the translation code until
   // it is set here.
-  if (isTargetIPhoneOS() && !isIPhoneOSVersionLT(6, 0)) {
+  if (isTargetIOSBased() && !isIPhoneOSVersionLT(6, 0)) {
     for (ArgList::iterator it = DAL->begin(), ie = DAL->end(); it != ie; ) {
       Arg *A = *it;
       ++it;
@@ -854,7 +897,7 @@
 
   // Default to use libc++ on OS X 10.9+ and iOS 7+.
   if (((isTargetMacOS() && !isMacosxVersionLT(10, 9)) ||
-       (isTargetIPhoneOS() && !isIPhoneOSVersionLT(7, 0))) &&
+       (isTargetIOSBased() && !isIPhoneOSVersionLT(7, 0))) &&
       !Args.getLastArg(options::OPT_stdlib_EQ))
     DAL->AddJoinedArg(0, Opts.getOption(options::OPT_stdlib_EQ), "libc++");
 
@@ -865,7 +908,7 @@
     StringRef where;
 
     // Complain about targeting iOS < 5.0 in any way.
-    if (isTargetIPhoneOS() && isIPhoneOSVersionLT(5, 0))
+    if (isTargetIOSBased() && isIPhoneOSVersionLT(5, 0))
       where = "iOS 5.0";
 
     if (where != StringRef()) {
@@ -911,12 +954,11 @@
 }
 
 bool Darwin::SupportsObjCGC() const {
-  // Garbage collection is supported everywhere except on iPhone OS.
-  return !isTargetIPhoneOS();
+  return isTargetMacOS();
 }
 
 void Darwin::CheckObjCARC() const {
-  if (isTargetIPhoneOS() || !isMacosxVersionLT(10, 6))
+  if (isTargetIOSBased()|| (isTargetMacOS() && !isMacosxVersionLT(10, 6)))
     return;
   getDriver().Diag(diag::err_arc_unsupported_on_toolchain);
 }
@@ -1299,17 +1341,6 @@
     BiarchTripleAliases.push_back(BiarchTriple.str());
 }
 
-static bool isSoftFloatABI(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_msoft_float) ||
-         (A->getOption().matches(options::OPT_mfloat_abi_EQ) &&
-          A->getValue() == StringRef("soft"));
-}
-
 static bool isMipsArch(llvm::Triple::ArchType Arch) {
   return Arch == llvm::Triple::mips ||
          Arch == llvm::Triple::mipsel ||
Index: lib/Driver/ToolChains.h
===================================================================
--- lib/Driver/ToolChains.h
+++ lib/Driver/ToolChains.h
@@ -210,11 +210,14 @@
   // the argument translation business.
   mutable bool TargetInitialized;
 
-  /// Whether we are targeting iPhoneOS target.
-  mutable bool TargetIsIPhoneOS;
+  enum DarwinPlatformKind {
+    MacOS,
+    IPhoneOS,
+    IPhoneOSSimulator,
+    Embedded // FIXME: embedded isn't really a Darwin platform.
+  };
 
-  /// Whether we are targeting the iPhoneOS simulator target.
-  mutable bool TargetIsIPhoneOSSimulator;
+  mutable DarwinPlatformKind TargetPlatform;
 
   /// The OS version we are targeting.
   mutable VersionTuple TargetVersion;
@@ -244,36 +247,42 @@
 
   // FIXME: Eliminate these ...Target functions and derive separate tool chains
   // for these targets and put version in constructor.
-  void setTarget(bool IsIPhoneOS, unsigned Major, unsigned Minor,
-                 unsigned Micro, bool IsIOSSim) const {
-    assert((!IsIOSSim || IsIPhoneOS) && "Unexpected deployment target!");
-
+  void setTarget(DarwinPlatformKind Platform, unsigned Major, unsigned Minor,
+                 unsigned Micro) const {
     // FIXME: For now, allow reinitialization as long as values don't
     // change. This will go away when we move away from argument translation.
-    if (TargetInitialized && TargetIsIPhoneOS == IsIPhoneOS &&
-        TargetIsIPhoneOSSimulator == IsIOSSim &&
+    if (TargetInitialized && TargetPlatform == Platform &&
         TargetVersion == VersionTuple(Major, Minor, Micro))
       return;
 
     assert(!TargetInitialized && "Target already initialized!");
     TargetInitialized = true;
-    TargetIsIPhoneOS = IsIPhoneOS;
-    TargetIsIPhoneOSSimulator = IsIOSSim;
+    TargetPlatform = Platform;
     TargetVersion = VersionTuple(Major, Minor, Micro);
   }
 
   bool isTargetIPhoneOS() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetIsIPhoneOS;
+    return TargetPlatform == IPhoneOS;
   }
 
   bool isTargetIOSSimulator() const {
     assert(TargetInitialized && "Target not initialized!");
-    return TargetIsIPhoneOSSimulator;
+    return TargetPlatform == IPhoneOSSimulator;
+  }
+
+  bool isTargetIOSBased() const {
+    assert(TargetInitialized && "Target not initialized!");
+    return isTargetIPhoneOS() || isTargetIOSSimulator();
   }
 
   bool isTargetMacOS() const {
-    return !isTargetIOSSimulator() && !isTargetIPhoneOS();
+    return TargetPlatform == MacOS;
+  }
+
+  bool isTargetEmbedded() const {
+    assert(TargetInitialized && "Target not initialized!");
+    return TargetPlatform == Embedded;
   }
 
   bool isTargetInitialized() const { return TargetInitialized; }
@@ -289,12 +298,12 @@
   StringRef getDarwinArchName(const llvm::opt::ArgList &Args) const;
 
   bool isIPhoneOSVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
-    assert(isTargetIPhoneOS() && "Unexpected call for OS X target!");
+    assert(isTargetIOSBased() && "Unexpected call for non iOS target!");
     return TargetVersion < VersionTuple(V0, V1, V2);
   }
 
   bool isMacosxVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const {
-    assert(!isTargetIPhoneOS() && "Unexpected call for iPhoneOS target!");
+    assert(isTargetMacOS() && "Unexpected call for non OS X target!");
     return TargetVersion < VersionTuple(V0, V1, V2);
   }
 
@@ -350,15 +359,20 @@
     // This is only used with the non-fragile ABI and non-legacy dispatch.
 
     // Mixed dispatch is used everywhere except OS X before 10.6.
-    return !(!isTargetIPhoneOS() && isMacosxVersionLT(10, 6));
+    return !(isTargetMacOS() && isMacosxVersionLT(10, 6));
   }
   virtual bool IsUnwindTablesDefault() const;
   virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const {
     // Stack protectors default to on for user code on 10.5,
     // and for everything in 10.6 and beyond
-    return isTargetIPhoneOS() ||
-      (!isMacosxVersionLT(10, 6) ||
-         (!isMacosxVersionLT(10, 5) && !KernelOrKext));
+    if (isTargetIOSBased())
+      return 1;
+    else if (isTargetMacOS() && !isMacosxVersionLT(10, 6))
+      return 1;
+    else if (isTargetMacOS() && !isMacosxVersionLT(10, 5) && !KernelOrKext)
+      return 1;
+
+    return 0;
   }
   virtual RuntimeLibType GetDefaultRuntimeLibType() const {
     return ToolChain::RLT_CompilerRT;
@@ -393,8 +407,9 @@
                                      llvm::opt::ArgStringList &CmdArgs) const;
   void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
                          llvm::opt::ArgStringList &CmdArgs,
-                         const char *DarwinStaticLib,
-                         bool AlwaysLink = false) const;
+                         StringRef DarwinStaticLib,
+                         bool AlwaysLink = false,
+                         bool IsEmbedded = false) const;
 
   virtual void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
                                    llvm::opt::ArgStringList &CmdArgs) const;
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -4847,13 +4847,16 @@
   //
   // FIXME: We may be able to remove this, once we can verify no one depends on
   // it.
-  if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ))
+  if (Args.hasArg(options::OPT_mios_simulator_version_min_EQ)) {
     CmdArgs.push_back("-ios_simulator_version_min");
-  else if (DarwinTC.isTargetIPhoneOS())
+    CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+  } else if (DarwinTC.isTargetIPhoneOS()) {
     CmdArgs.push_back("-iphoneos_version_min");
-  else
+    CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+  } else if (DarwinTC.isTargetMacOS()) {
     CmdArgs.push_back("-macosx_version_min");
-  CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+    CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString()));
+  }
 
   Args.AddLastArg(CmdArgs, options::OPT_nomultidefs);
   Args.AddLastArg(CmdArgs, options::OPT_multi__module);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to