MC/Mach-O/x86_64: Temporary labels in cstring sections require symbols (and external relocations, but we don't have x86_64 relocations yet).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98583 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/X86/X86AsmBackend.cpp b/lib/Target/X86/X86AsmBackend.cpp
index 88cc2c7..a44afc6 100644
--- a/lib/Target/X86/X86AsmBackend.cpp
+++ b/lib/Target/X86/X86AsmBackend.cpp
@@ -9,6 +9,7 @@
 
 #include "llvm/Target/TargetAsmBackend.h"
 #include "X86.h"
+#include "llvm/MC/MCSectionMachO.h"
 #include "llvm/Target/TargetRegistry.h"
 #include "llvm/Target/TargetAsmBackend.h"
 using namespace llvm;
@@ -31,13 +32,38 @@
   virtual bool hasScatteredSymbols() const { return true; }
 };
 
+class DarwinX86_32AsmBackend : public DarwinX86AsmBackend {
+public:
+  DarwinX86_32AsmBackend(const Target &T)
+    : DarwinX86AsmBackend(T) {}
+};
+
+class DarwinX86_64AsmBackend : public DarwinX86AsmBackend {
+public:
+  DarwinX86_64AsmBackend(const Target &T)
+    : DarwinX86AsmBackend(T) {}
+
+  virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
+    // Temporary labels in the string literals sections require symbols. The
+    // issue is that the x86_64 relocation format does not allow symbol +
+    // offset, and so the linker does not have enough information to resolve the
+    // access to the appropriate atom unless an external relocation is used. For
+    // non-cstring sections, we expect the compiler to use a non-temporary label
+    // for anything that could have an addend pointing outside the symbol.
+    //
+    // See <rdar://problem/4765733>.
+    const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
+    return SMO.getType() == MCSectionMachO::S_CSTRING_LITERALS;
+  }
+};
+
 }
 
 TargetAsmBackend *llvm::createX86_32AsmBackend(const Target &T,
                                                const std::string &TT) {
   switch (Triple(TT).getOS()) {
   case Triple::Darwin:
-    return new DarwinX86AsmBackend(T);
+    return new DarwinX86_32AsmBackend(T);
   default:
     return new X86AsmBackend(T);
   }
@@ -47,7 +73,7 @@
                                                const std::string &TT) {
   switch (Triple(TT).getOS()) {
   case Triple::Darwin:
-    return new DarwinX86AsmBackend(T);
+    return new DarwinX86_64AsmBackend(T);
   default:
     return new X86AsmBackend(T);
   }