[llvm][patch] Adjust behavior of FDE cross-section relocs for targets that don't support abs-differences.

David Fang fang at csl.cornell.edu
Wed Dec 4 13:24:24 PST 2013


Thanks, Iain, for working on this.  We've been doing a bunch of our own 
testing on this.  (#llvm-powerpc-darwin)

I've re-attached the patch, which includes additional PPC relocs patch you 
sent to me earlier, that is needed.
The attached patch was regenerated relative to the powerpc-darwin8 branch 
(relative to trunk @r195934).

With this patch, I am now able to produce working binaries using C++ 
exceptions: try-throw-catch.  Furthermore, this dramatically improves the 
status of libcxxabi tests on powerpc-darwin8: all but 2 tests pass now 
(where all crashed before)!  [http://llvm.org/bugs/show_bug.cgi?id=17505]

While I can't really comment on technical merits of the patch, I can 
testify that this is working rather well.

Of course, we will need to include some dwarfdump tests to go along with 
any patch aimed at trunk.

David

> Hi,
> (I hope I have directed this to the correct reviewers)
>
> At the dev. conf. David reported to me that EH was not working on 
> ppc-darwin8.  Once we checked a few more platforms, it turns out it's 
> not working with any ld64 < 97.17 (so OSX < 10.6 on both x86/ppc).
>
> The reason is that the older ld/ld64 versions require proper scattered 
> relocs for expressions in CIE/FDE symbol refs that cross section 
> boundaries.
>
> Later versions of the ld64 allow that these may be replaced by an 
> absolute difference***
>
> AFAIK, this behaviour is specific to Darwin/OSX (and ld64 >= 97.17), I suspect that any other target that elected to use a non-trivial FDE symbol encoding would likely be surprised by the abs values.  However, these are hardwired in MCDwarf.cpp, as of now.
>
> NOTE1: in general, this would not cause a linkage error for the target - 'just' a failure to unwind at runtime.
> NOTE2: it also seems that the abs-ification is not done even for x86-64-darwin12 for compact unwind.
>
> The solution I am proposing is to introduce a "DwarfFDESymbolsUseAbsDiff" boolean value in MCAsmInfo and to use that to control this behaviour.  In the patch, this is only switched on for X86 Darwin/OSX & for OSX >= 10.6.  It should really be contingent on -target-linker-version >= 97.17, but this information is not yet passed to the target.
>
> With the patch EH works on *-darwin9 with the native linker (and still emits the same set of relocs on darwin12).
>
> Is this a reasonable solution?
> Iain
>
> *** P.S.
> I assume that these extra hoops and inconsistencies (and presumably matching ones in ld64) are really worthwhile?
> I.E. that there is some measurable performance gain?
> (if not, we could just elect to emit the relocs and drop this special casing).
>
>

-- 
David Fang
http://www.csl.cornell.edu/~fang/
-------------- next part --------------
diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h
index 6dfb42c..0189736 100644
--- a/include/llvm/MC/MCAsmInfo.h
+++ b/include/llvm/MC/MCAsmInfo.h
@@ -303,6 +303,10 @@ namespace llvm {
     /// uses relocations for references to other .debug_* sections.
     bool DwarfUsesRelocationsAcrossSections;
 
+    /// DwarfFDESymbolsUseAbsDiff - true if DWARF FDE symbol reference
+    /// relocations should be replaced by an absolute difference.
+    bool DwarfFDESymbolsUseAbsDiff;
+
     /// DwarfRegNumForCFI - True if dwarf register numbers are printed
     /// instead of symbolic register names in .cfi_* directives.
     bool DwarfRegNumForCFI;  // Defaults to false;
@@ -528,6 +532,9 @@ namespace llvm {
     bool doesDwarfUseRelocationsAcrossSections() const {
       return DwarfUsesRelocationsAcrossSections;
     }
+    bool doDwarfFDESymbolsUseAbsDiff() const {
+      return DwarfFDESymbolsUseAbsDiff;
+    }
     bool useDwarfRegNumForCFI() const {
       return DwarfRegNumForCFI;
     }
diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp
index a2ff92f..76c3ce5 100644
--- a/lib/MC/MCAsmInfo.cpp
+++ b/lib/MC/MCAsmInfo.cpp
@@ -85,6 +85,7 @@ MCAsmInfo::MCAsmInfo() {
   SupportsDebugInformation = false;
   ExceptionsType = ExceptionHandling::None;
   DwarfUsesRelocationsAcrossSections = true;
+  DwarfFDESymbolsUseAbsDiff = false;
   DwarfRegNumForCFI = false;
   HasMicrosoftFastStdCallMangling = false;
   NeedsDwarfSectionOffsetDirective = false;
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index 1e5c2e3..9fd13ab 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -836,8 +836,9 @@ static unsigned getSizeForEncoding(MCStreamer &streamer,
   }
 }
 
-static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol,
-                       unsigned symbolEncoding, const char *comment = 0) {
+static void EmitFDESymbol(MCStreamer &streamer, const MCSymbol &symbol,
+                       unsigned symbolEncoding, bool isEH,
+                       const char *comment = 0) {
   MCContext &context = streamer.getContext();
   const MCAsmInfo *asmInfo = context.getAsmInfo();
   const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol,
@@ -845,7 +846,10 @@ static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol,
                                                  streamer);
   unsigned size = getSizeForEncoding(streamer, symbolEncoding);
   if (streamer.isVerboseAsm() && comment) streamer.AddComment(comment);
-  streamer.EmitAbsValue(v, size);
+  if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH)
+    streamer.EmitAbsValue(v, size);
+  else
+    streamer.EmitValue(v, size);
 }
 
 static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
@@ -1344,7 +1348,7 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer,
   unsigned PCEncoding = IsEH ? MOFI->getFDEEncoding(UsingCFI)
                              : (unsigned)dwarf::DW_EH_PE_absptr;
   unsigned PCSize = getSizeForEncoding(streamer, PCEncoding);
-  EmitSymbol(streamer, *frame.Begin, PCEncoding, "FDE initial location");
+  EmitFDESymbol(streamer, *frame.Begin, PCEncoding, IsEH, "FDE initial location");
 
   // PC Range
   const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin,
@@ -1364,8 +1368,8 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer,
 
     // Augmentation Data
     if (frame.Lsda)
-      EmitSymbol(streamer, *frame.Lsda, frame.LsdaEncoding,
-                 "Language Specific Data Area");
+      EmitFDESymbol(streamer, *frame.Lsda, frame.LsdaEncoding, true,
+                    "Language Specific Data Area");
   }
 
   // Call Frame Instructions
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp
index bbafe2e..78a3df4 100644
--- a/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp
@@ -88,8 +88,9 @@ static unsigned getRelocType(const MCValue &Target,
   const MCSymbolRefExpr::VariantKind Modifier =
       Target.isAbsolute() ? MCSymbolRefExpr::VK_None
                           : Target.getSymA()->getKind();
-  // determine the type of the relocation
-  unsigned Type = MachO::GENERIC_RELOC_VANILLA;
+  // Determine the type of the relocation.
+  // Default to vanilla.
+  unsigned Type = MachO::PPC_RELOC_VANILLA ;
   if (IsPCRel) { // relative to PC
     switch ((unsigned)FixupKind) {
     default:
@@ -197,7 +198,7 @@ bool PPCMachObjectWriter::RecordScatteredRelocation(
   const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
   const MCFixupKind FK = Fixup.getKind();
   const unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
-  const unsigned Type = getRelocType(Target, FK, IsPCRel);
+  unsigned Type = getRelocType(Target, FK, IsPCRel);
 
   // Is this a local or SECTDIFF relocation entry?
   // SECTDIFF relocation entries have symbol subtractions,
@@ -225,7 +226,17 @@ bool PPCMachObjectWriter::RecordScatteredRelocation(
       report_fatal_error("symbol '" + B->getSymbol().getName() +
                          "' can not be undefined in a subtraction expression");
 
-    // FIXME: is Type correct? see include/llvm/Support/MachO.h
+    // Select the appropriate difference relocation type.
+    //
+    // Note that there is no longer any semantic difference between these two
+    // relocation types from the linkers point of view, this is done solely for
+    // pedantic compatibility with 'as'.
+
+    // FIXME: Determine if there's ever a time when this override is not
+    // appropriate.
+    if (FK == FK_Data_4 && Type == MachO::PPC_RELOC_VANILLA)
+      Type = A_SD->isExternal() ? (unsigned)MachO::PPC_RELOC_SECTDIFF
+                                : (unsigned)MachO::PPC_RELOC_LOCAL_SECTDIFF;
     Value2 = Writer->getSymbolAddress(B_SD, Layout);
     FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
   }
@@ -233,15 +244,15 @@ bool PPCMachObjectWriter::RecordScatteredRelocation(
 
   // Relocations are written out in reverse order, so the PAIR comes first.
   if (Type == MachO::PPC_RELOC_SECTDIFF ||
+      Type == MachO::PPC_RELOC_LOCAL_SECTDIFF ||
       Type == MachO::PPC_RELOC_HI16_SECTDIFF ||
       Type == MachO::PPC_RELOC_LO16_SECTDIFF ||
       Type == MachO::PPC_RELOC_HA16_SECTDIFF ||
-      Type == MachO::PPC_RELOC_LO14_SECTDIFF ||
-      Type == MachO::PPC_RELOC_LOCAL_SECTDIFF) {
-    // X86 had this piece, but ARM does not
+      Type == MachO::PPC_RELOC_LO14_SECTDIFF) {
+
     // If the offset is too large to fit in a scattered relocation,
     // we're hosed. It's an unfortunate limitation of the MachO format.
-    if (FixupOffset > 0xffffff) {
+    if (FixupOffset > 0x00ffffff) {
       char Buffer[32];
       format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
       Asm.getContext().FatalError(Fixup.getLoc(),
@@ -256,6 +267,9 @@ bool PPCMachObjectWriter::RecordScatteredRelocation(
     // see PPCMCExpr::EvaluateAsRelocatableImpl()
     uint32_t other_half = 0;
     switch (Type) {
+    case MachO::PPC_RELOC_SECTDIFF:
+    case MachO::PPC_RELOC_LOCAL_SECTDIFF:
+      break;
     case MachO::PPC_RELOC_LO16_SECTDIFF:
       other_half = (FixedValue >> 16) & 0xffff;
       // applyFixupOffset longer extracts the high part because it now assumes
@@ -280,7 +294,7 @@ bool PPCMachObjectWriter::RecordScatteredRelocation(
     }
 
     MachO::any_relocation_info MRE;
-    makeScatteredRelocationInfo(MRE, other_half, MachO::GENERIC_RELOC_PAIR,
+    makeScatteredRelocationInfo(MRE, other_half, MachO::PPC_RELOC_PAIR,
                                 Log2Size, IsPCRel, Value2);
     Writer->addRelocation(Fragment->getParent(), MRE);
   } else {
diff --git a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
index 45f22a1..2ac1536 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
@@ -65,6 +65,11 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &T) {
 
   // Exceptions handling
   ExceptionsType = ExceptionHandling::DwarfCFI;
+
+  // FIXME: this should not depend on the target OS version, but on the ld64
+  // version in use.  From at least >= ld64-97.17 (Xcode 3.2.6) the abs-ified
+  // FDE relocs may be used.
+  DwarfFDESymbolsUseAbsDiff = T.isMacOSX() && !T.isMacOSXVersionLT(10, 6);
 }
 
 X86_64MCAsmInfoDarwin::X86_64MCAsmInfoDarwin(const Triple &Triple)
diff --git a/test/CodeGen/X86/pr10420.ll b/test/CodeGen/X86/pr10420.ll
index 3993f24..62951892 100644
--- a/test/CodeGen/X86/pr10420.ll
+++ b/test/CodeGen/X86/pr10420.ll
@@ -1,4 +1,9 @@
-; RUN: llc < %s -mtriple=x86_64-apple-macosx -disable-cfi | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-apple-macosx10.7 -disable-cfi | FileCheck --check-prefix=CHECK-64-D11 %s
+; RUN: llc < %s -mtriple=x86_64-apple-macosx10.6 -disable-cfi | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-apple-macosx10.5 -disable-cfi | FileCheck --check-prefix=CHECK-64-D89 %s
+; RUN: llc < %s -mtriple=i686-apple-macosx10.6 -disable-cfi | FileCheck --check-prefix=CHECK-I686-D10 %s
+; RUN: llc < %s -mtriple=i686-apple-macosx10.5 -disable-cfi | FileCheck --check-prefix=CHECK-I686-D89 %s
+; RUN: llc < %s -mtriple=i686-apple-macosx10.4 -disable-cfi | FileCheck --check-prefix=CHECK-I686-D89 %s
 
 define private void @foo() {
        ret void
@@ -19,3 +24,44 @@ define void @bar() {
 ; CHECK: Ltmp19:
 ; CHECK-NEXT: Ltmp20 = Ltmp2-Ltmp19                   ## FDE initial location
 ; CHECK-NEXT:         .quad   Ltmp20
+
+
+; CHECK-64-D11: Ltmp13:
+; CHECK-64-D11-NEXT: Ltmp14 = L_foo-Ltmp13                   ## FDE initial location
+; CHECK-64-D11-NEXT:         .quad   Ltmp14
+
+; CHECK-64-D11: Ltmp20:
+; CHECK-64-D11-NEXT: Ltmp21 = Ltmp2-Ltmp20                   ## FDE initial location
+; CHECK-64-D11-NEXT:         .quad   Ltmp21
+
+
+; CHECK-64-D89: Ltmp12:
+; CHECK-64-D89-NEXT: .quad	L_foo-Ltmp12                   ## FDE initial location
+; CHECK-64-D89-NEXT: Ltmp13 = (Ltmp0-L_foo)-0                   ## FDE address range
+; CHECK-64-D89-NEXT:         .quad   Ltmp13
+
+; CHECK-64-D89: Ltmp18:
+; CHECK-64-D89-NEXT: .quad	Ltmp2-Ltmp18                   ## FDE initial location
+; CHECK-64-D89-NEXT: Ltmp19 = (Ltmp4-Ltmp2)-0                   ## FDE address range
+; CHECK-64-D89-NEXT:         .quad   Ltmp19
+
+
+; CHECK-I686-D10: Ltmp12:
+; CHECK-I686-D10-NEXT: Ltmp13 = L_foo-Ltmp12                   ## FDE initial location
+; CHECK-I686-D10-NEXT:         .long   Ltmp13
+
+; CHECK-I686-D10: Ltmp19:
+; CHECK-I686-D10-NEXT: Ltmp20 = Ltmp2-Ltmp19                   ## FDE initial location
+; CHECK-I686-D10-NEXT:         .long   Ltmp20
+
+
+; CHECK-I686-D89: Ltmp12:
+; CHECK-I686-D89-NEXT: .long	L_foo-Ltmp12                   ## FDE initial location
+; CHECK-I686-D89-NEXT: Ltmp13 = (Ltmp0-L_foo)-0                   ## FDE address range
+; CHECK-I686-D89-NEXT:         .long   Ltmp13
+
+; CHECK-I686-D89: Ltmp18:
+; CHECK-I686-D89-NEXT: .long	Ltmp2-Ltmp18                   ## FDE initial location
+; CHECK-I686-D89-NEXT: Ltmp19 = (Ltmp4-Ltmp2)-0                   ## FDE address range
+; CHECK-I686-D89-NEXT:         .long   Ltmp19
+


More information about the llvm-commits mailing list