Compute A-B when A or B is weak.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 17 Apr 2015 21:15:17 +0000 (21:15 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 17 Apr 2015 21:15:17 +0000 (21:15 +0000)
Similar to r235222, but for the weak symbol case.

In an "ideal" assembler/object format an expression would always refer to the
final value and A-B would only be computed from a section in the same
comdat as A and B with A and B strong.

Unfortunately that is not the case with debug info on ELF, so we need an
heuristic.  Since we need an heuristic, we may as well use the same one as
gas:

* call weak_sym : produces a relocation, even if in the same section.
* A - weak_sym and weak_sym -A: don't produce a relocation if we can
  compute it.

This fixes pr23272 and changes the fix of pr22815 to match what gas does.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235227 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCMachObjectWriter.h
include/llvm/MC/MCObjectWriter.h
lib/MC/ELFObjectWriter.cpp
lib/MC/MCAssembler.cpp
lib/MC/MCObjectWriter.cpp
lib/MC/MachObjectWriter.cpp
lib/MC/WinCOFFObjectWriter.cpp
test/MC/ELF/weak-diff.s
test/MC/ELF/weak-diff2.s [deleted file]

index a06f44a15f1f23194b951e9742fdbcbd5035bbdb..7feeec3bc8fb750fc85f2e5c655121ce14ad7e50 100644 (file)
@@ -264,7 +264,6 @@ public:
 
   bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
                                               const MCSymbolData &DataA,
-                                              const MCSymbolData *DataB,
                                               const MCFragment &FB,
                                               bool InSet,
                                               bool IsPCRel) const override;
index f8e2821c4dc47133b2ba74befef79199eceb4d0a..b490e92c5218ff3d4daec986b20abed1fe015b6b 100644 (file)
@@ -94,7 +94,6 @@ public:
 
   virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
                                                       const MCSymbolData &DataA,
-                                                      const MCSymbolData *DataB,
                                                       const MCFragment &FB,
                                                       bool InSet,
                                                       bool IsPCRel) const;
index 32ec969c369f72de4f7e9ada2bdbad103600a855..1646fe59ce413b311802872d28ca2802cb421f30 100644 (file)
@@ -275,7 +275,6 @@ class ELFObjectWriter : public MCObjectWriter {
     bool
     IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
                                            const MCSymbolData &DataA,
-                                           const MCSymbolData *DataB,
                                            const MCFragment &FB,
                                            bool InSet,
                                            bool IsPCRel) const override;
@@ -1669,13 +1668,15 @@ void ELFObjectWriter::WriteObject(MCAssembler &Asm,
 }
 
 bool ELFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
-    const MCAssembler &Asm, const MCSymbolData &DataA,
-    const MCSymbolData *DataB, const MCFragment &FB, bool InSet,
-    bool IsPCRel) const {
-  if (!InSet && (::isWeak(DataA) || (DataB && ::isWeak(*DataB))))
-    return false;
-  return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
-      Asm, DataA, DataB, FB, InSet, IsPCRel);
+    const MCAssembler &Asm, const MCSymbolData &DataA, const MCFragment &FB,
+    bool InSet, bool IsPCRel) const {
+  if (IsPCRel) {
+    assert(!InSet);
+    if (::isWeak(DataA))
+      return false;
+  }
+  return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(Asm, DataA, FB,
+                                                                InSet, IsPCRel);
 }
 
 bool ELFObjectWriter::isWeak(const MCSymbolData &SD) const {
index d09e383f73ff7468100abbf8632753c0136c0c7f..a7df95a384f7cded94e0e84fbf47ce95718d7e20 100644 (file)
@@ -504,7 +504,7 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
       } else {
         const MCSymbolData &DataA = getSymbolData(SA);
         IsResolved = getWriter().IsSymbolRefDifferenceFullyResolvedImpl(
-            *this, DataA, nullptr, *DF, false, true);
+            *this, DataA, *DF, false, true);
       }
     }
   } else {
index e40c07d5527f2bc7186bed23744694c272b863da..e90dea814796af8a6c3a62e604346e93740f0778 100644 (file)
@@ -36,13 +36,12 @@ bool MCObjectWriter::IsSymbolRefDifferenceFullyResolved(
     return false;
 
   return IsSymbolRefDifferenceFullyResolvedImpl(
-      Asm, DataA, &DataB, *DataB.getFragment(), InSet, false);
+      Asm, DataA, *DataB.getFragment(), InSet, false);
 }
 
 bool MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
-    const MCAssembler &Asm, const MCSymbolData &DataA,
-    const MCSymbolData *DataB, const MCFragment &FB, bool InSet,
-    bool IsPCRel) const {
+    const MCAssembler &Asm, const MCSymbolData &DataA, const MCFragment &FB,
+    bool InSet, bool IsPCRel) const {
   const MCSection &SecA = DataA.getSymbol().getSection();
   const MCSection &SecB = FB.getParent()->getSection();
   // On ELF and COFF  A - B is absolute if A and B are in the same section.
index 97143a94fb1a675c329746f2724f674a54e19046..dc68a89e6ea9eca17e4b306c30842b527a5415b5 100644 (file)
@@ -669,13 +669,9 @@ void MachObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
   BindIndirectSymbols(Asm);
 }
 
-bool MachObjectWriter::
-IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
-                                       const MCSymbolData &DataA,
-                                       const MCSymbolData *DataB,
-                                       const MCFragment &FB,
-                                       bool InSet,
-                                       bool IsPCRel) const {
+bool MachObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
+    const MCAssembler &Asm, const MCSymbolData &DataA, const MCFragment &FB,
+    bool InSet, bool IsPCRel) const {
   if (InSet)
     return true;
 
index a4b6bf9b08fc8b9ab05e0eddf948feb02c144474..58546307255ee2d60b3d1d2783ec590e0c2e4c2d 100644 (file)
@@ -172,7 +172,6 @@ public:
 
   bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
                                               const MCSymbolData &DataA,
-                                              const MCSymbolData *DataB,
                                               const MCFragment &FB, bool InSet,
                                               bool IsPCRel) const override;
 
@@ -649,17 +648,16 @@ void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
 }
 
 bool WinCOFFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
-    const MCAssembler &Asm, const MCSymbolData &DataA,
-    const MCSymbolData *DataB, const MCFragment &FB, bool InSet,
-    bool IsPCRel) const {
+    const MCAssembler &Asm, const MCSymbolData &DataA, const MCFragment &FB,
+    bool InSet, bool IsPCRel) const {
   // MS LINK expects to be able to replace all references to a function with a
   // thunk to implement their /INCREMENTAL feature.  Make sure we don't optimize
   // away any relocations to functions.
   if ((((DataA.getFlags() & COFF::SF_TypeMask) >> COFF::SF_TypeShift) >>
        COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
     return false;
-  return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(
-      Asm, DataA, DataB, FB, InSet, IsPCRel);
+  return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(Asm, DataA, FB,
+                                                                InSet, IsPCRel);
 }
 
 bool WinCOFFObjectWriter::isWeak(const MCSymbolData &SD) const {
index d270bbb73344d0307a54541ee7550d853e8ec686..ded89b8f8338c042de9640d4749fee51466fcfc9 100644 (file)
@@ -1,6 +1,10 @@
-// RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t 2>&1 | FileCheck %s
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu < %s | llvm-readobj -r | FileCheck %s
 
-// CHECK: error: Cannot represent a subtraction with a weak symbol
+// CHECK:      Relocations [
+// CHECK-NEXT:   Section ({{.*}}) .rela.text {
+// CHECK-NEXT:     0x1D R_X86_64_PC32 f2 0xFFFFFFFFFFFFFFFC
+// CHECK-NEXT:   }
+// CHECK-NEXT: ]
 
 .weak f
 .weak g
@@ -10,3 +14,13 @@ g:
     nop
 
 .quad g - f
+
+
+.weak f2
+f2:
+    nop
+g2:
+    nop
+.quad g2 - f2
+.quad f2 - g2
+call f2
diff --git a/test/MC/ELF/weak-diff2.s b/test/MC/ELF/weak-diff2.s
deleted file mode 100644 (file)
index daf64a4..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t 2>&1 | FileCheck %s
-
-// CHECK: error: Cannot represent a subtraction with a weak symbol
-
-.weak f
-f:
-    nop
-g:
-    nop
-.quad g - f