MC/Mach-O/x86_64: Darwin's special "signed_N" relocation types should only be
used to replace a normal relocation, not a reference to a GOT entry.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103789 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index 3ca6708..00c14ef 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/lib/MC/MachObjectWriter.cpp
@@ -609,10 +609,31 @@
               Type = RIT_X86_64_GOTLoad;
             else
               Type = RIT_X86_64_GOT;
-          } else if (Modifier != MCSymbolRefExpr::VK_None)
+          } else if (Modifier != MCSymbolRefExpr::VK_None) {
             report_fatal_error("unsupported symbol modifier in relocation");
-          else
+          } else {
             Type = RIT_X86_64_Signed;
+
+            // The Darwin x86_64 relocation format has a problem where it cannot
+            // encode an address (L<foo> + <constant>) which is outside the atom
+            // containing L<foo>. Generally, this shouldn't occur but it does
+            // happen when we have a RIPrel instruction with data following the
+            // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel
+            // adjustment Darwin x86_64 uses, the offset is still negative and
+            // the linker has no way to recognize this.
+            //
+            // To work around this, Darwin uses several special relocation types
+            // to indicate the offsets. However, the specification or
+            // implementation of these seems to also be incomplete; they should
+            // adjust the addend as well based on the actual encoded instruction
+            // (the additional bias), but instead appear to just look at the
+            // final offset.
+            switch (-(Target.getConstant() + (1LL << Log2Size))) {
+            case 1: Type = RIT_X86_64_Signed1; break;
+            case 2: Type = RIT_X86_64_Signed2; break;
+            case 4: Type = RIT_X86_64_Signed4; break;
+            }
+          }
         } else {
           if (Modifier != MCSymbolRefExpr::VK_None)
             report_fatal_error("unsupported symbol modifier in branch "
@@ -620,27 +641,6 @@
 
           Type = RIT_X86_64_Branch;
         }
-
-        // The Darwin x86_64 relocation format has a problem where it cannot
-        // encode an address (L<foo> + <constant>) which is outside the atom
-        // containing L<foo>. Generally, this shouldn't occur but it does happen
-        // when we have a RIPrel instruction with data following the relocation
-        // entry (e.g., movb $012, L0(%rip)). Even with the PCrel adjustment
-        // Darwin x86_64 uses, the offset is still negative and the linker has
-        // no way to recognize this.
-        //
-        // To work around this, Darwin uses several special relocation types to
-        // indicate the offsets. However, the specification or implementation of
-        // these seems to also be incomplete; they should adjust the addend as
-        // well based on the actual encoded instruction (the additional bias),
-        // but instead appear to just look at the final offset.
-        if (IsRIPRel) {
-          switch (-(Target.getConstant() + (1LL << Log2Size))) {
-          case 1: Type = RIT_X86_64_Signed1; break;
-          case 2: Type = RIT_X86_64_Signed2; break;
-          case 4: Type = RIT_X86_64_Signed4; break;
-          }
-        }
       } else {
         if (Modifier == MCSymbolRefExpr::VK_GOT) {
           Type = RIT_X86_64_GOT;