[llvm-commits] [llvm] r111963 - in /llvm/trunk: lib/MC/WinCOFFObjectWriter.cpp test/MC/COFF/basic-coff.ll test/MC/COFF/switch-relocations.ll test/MC/COFF/symbol-fragment-offset.ll

Michael J. Spencer bigcheesegs at gmail.com
Tue Aug 24 14:04:52 PDT 2010


Author: mspencer
Date: Tue Aug 24 16:04:52 2010
New Revision: 111963

URL: http://llvm.org/viewvc/llvm-project?rev=111963&view=rev
Log:
Fix COFF x86-64 relocations. PR7960.

Multiple symbol reloc handling part of the patch by Cameron Esfahani.

Added:
    llvm/trunk/test/MC/COFF/switch-relocations.ll
Modified:
    llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp
    llvm/trunk/test/MC/COFF/basic-coff.ll
    llvm/trunk/test/MC/COFF/symbol-fragment-offset.ll

Modified: llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp?rev=111963&r1=111962&r2=111963&view=diff
==============================================================================
--- llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/WinCOFFObjectWriter.cpp Tue Aug 24 16:04:52 2010
@@ -125,6 +125,7 @@
   typedef DenseMap<MCSectionData const *, COFFSection *> section_map;
 
   // Root level file contents.
+  bool Is64Bit;
   COFF::header Header;
   sections     Sections;
   symbols      Symbols;
@@ -274,10 +275,11 @@
 // WinCOFFObjectWriter class implementation
 
 WinCOFFObjectWriter::WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit)
-                                : MCObjectWriter(OS, true) {
+  : MCObjectWriter(OS, true)
+  , Is64Bit(is64Bit) {
   memset(&Header, 0, sizeof(Header));
 
-  is64Bit ? Header.Machine = COFF::IMAGE_FILE_MACHINE_AMD64
+  Is64Bit ? Header.Machine = COFF::IMAGE_FILE_MACHINE_AMD64
           : Header.Machine = COFF::IMAGE_FILE_MACHINE_I386;
 }
 
@@ -565,22 +567,34 @@
                                            MCValue Target,
                                            uint64_t &FixedValue) {
   assert(Target.getSymA() != NULL && "Relocation must reference a symbol!");
-  assert(Target.getSymB() == NULL &&
-         "Relocation must reference only one symbol!");
+
+  const MCSymbol *A = &Target.getSymA()->getSymbol();
+  MCSymbolData &A_SD = Asm.getSymbolData(*A);
 
   MCSectionData const *SectionData = Fragment->getParent();
-  MCSymbolData const *SymbolData =
-                              &Asm.getSymbolData(Target.getSymA()->getSymbol());
 
+  // Mark this symbol as requiring an entry in the symbol table.
   assert(SectionMap.find(SectionData) != SectionMap.end() &&
          "Section must already have been defined in ExecutePostLayoutBinding!");
-  assert(SymbolMap.find(SymbolData) != SymbolMap.end() &&
+  assert(SymbolMap.find(&A_SD) != SymbolMap.end() &&
          "Symbol must already have been defined in ExecutePostLayoutBinding!");
 
   COFFSection *coff_section = SectionMap[SectionData];
-  COFFSymbol *coff_symbol = SymbolMap[SymbolData];
+  COFFSymbol *coff_symbol = SymbolMap[&A_SD];
 
-  FixedValue = Target.getConstant();
+  if (Target.getSymB()) {
+    const MCSymbol *B = &Target.getSymB()->getSymbol();
+    MCSymbolData &B_SD = Asm.getSymbolData(*B);
+
+    FixedValue = Layout.getSymbolAddress(&A_SD) - Layout.getSymbolAddress(&B_SD);
+
+    // In the case where we have SymbA and SymB, we just need to store the delta
+    // between the two symbols.  Update FixedValue to account for the delta, and
+    // skip recording the relocation.
+    return;
+  } else {
+    FixedValue = Target.getConstant();
+  }
 
   COFFRelocation Reloc;
 
@@ -590,40 +604,29 @@
 
   Reloc.Data.VirtualAddress += Fixup.getOffset();
 
-  COFF::RelocationTypeX86 Type;
-
-  if (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386) {
-    switch (Fixup.getKind()) {
-    case X86::reloc_pcrel_4byte:
-      Type = COFF::IMAGE_REL_I386_REL32;
-      FixedValue += 4;
-      break;
-    case FK_Data_4:
-      Type = COFF::IMAGE_REL_I386_DIR32;
-      break;
-    default:
+  switch (Fixup.getKind()) {
+  case X86::reloc_pcrel_4byte:
+  case X86::reloc_riprel_4byte:
+  case X86::reloc_riprel_4byte_movq_load:
+    Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_REL32
+                              : COFF::IMAGE_REL_I386_REL32;
+    // FIXME: Can anyone explain what this does other than adjust for the size
+    // of the offset?
+    FixedValue += 4;
+    break;
+  case FK_Data_4:
+    Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_ADDR32
+                              : COFF::IMAGE_REL_I386_DIR32;
+    break;
+  case FK_Data_8:
+    if (Is64Bit)
+      Reloc.Data.Type = COFF::IMAGE_REL_AMD64_ADDR64;
+    else
       llvm_unreachable("unsupported relocation type");
-    }
-  } else if (Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64) {
-    switch (Fixup.getKind()) {
-    case FK_Data_8:
-      Type = COFF::IMAGE_REL_AMD64_ADDR64;
-      break;
-    case X86::reloc_pcrel_4byte:
-    case X86::reloc_riprel_4byte:
-      Type = COFF::IMAGE_REL_AMD64_REL32;
-      FixedValue += 4;
-      break;
-    case FK_Data_4:
-      Type = COFF::IMAGE_REL_AMD64_ADDR32;
-      break;
-    default:
-      llvm_unreachable("unsupported relocation type");
-    }
-  } else
-    llvm_unreachable("unknown target architecture");
-
-  Reloc.Data.Type = Type;
+    break;
+  default:
+    llvm_unreachable("unsupported relocation type");
+  }
 
   coff_section->Relocations.push_back(Reloc);
 }

Modified: llvm/trunk/test/MC/COFF/basic-coff.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/basic-coff.ll?rev=111963&r1=111962&r2=111963&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/basic-coff.ll (original)
+++ llvm/trunk/test/MC/COFF/basic-coff.ll Tue Aug 24 16:04:52 2010
@@ -1,9 +1,9 @@
-; RUN: llc -filetype=obj %s -o %t
-; RUN: coff-dump.py %abs_tmp | FileCheck %s
+; This test checks that the COFF object emitter works for the most basic
+; programs.
 
-; ModuleID = '-'
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
-target triple = "i686-pc-win32"
+; RUN: llc -filetype=obj -mtriple i686-pc-win32 %s -o %t
+; RUN: coff-dump.py %abs_tmp | FileCheck %s
+; RUN: llc -filetype=obj -mtriple x86_64-pc-win32 %s -o %t
 
 @.str = private constant [12 x i8] c"Hello World\00" ; <[12 x i8]*> [#uses=1]
 

Added: llvm/trunk/test/MC/COFF/switch-relocations.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/switch-relocations.ll?rev=111963&view=auto
==============================================================================
--- llvm/trunk/test/MC/COFF/switch-relocations.ll (added)
+++ llvm/trunk/test/MC/COFF/switch-relocations.ll Tue Aug 24 16:04:52 2010
@@ -0,0 +1,34 @@
+; The purpose of this test is to see if the COFF object writer can properly
+; relax the fixups that are created for jump tables on x86-64. See PR7960.
+
+; This test case was reduced from Lua/lapi.c.
+
+; RUN: llc -filetype=obj -mtriple i686-pc-win32 %s -o %t
+; RUN: llc -filetype=obj -mtriple x86_64-pc-win32 %s -o %t
+
+define void @lua_gc(i32 %what) nounwind {
+entry:
+  switch i32 %what, label %sw.epilog [
+    i32 0, label %sw.bb
+    i32 1, label %sw.bb
+    i32 2, label %sw.bb
+    i32 3, label %sw.bb14
+    i32 4, label %sw.bb18
+    i32 6, label %sw.bb57
+  ]
+
+sw.bb:                                            ; preds = %entry, %entry, %entry
+  ret void
+
+sw.bb14:                                          ; preds = %entry
+  ret void
+
+sw.bb18:                                          ; preds = %entry
+  ret void
+
+sw.bb57:                                          ; preds = %entry
+  ret void
+
+sw.epilog:                                        ; preds = %entry
+  ret void
+}

Modified: llvm/trunk/test/MC/COFF/symbol-fragment-offset.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/COFF/symbol-fragment-offset.ll?rev=111963&r1=111962&r2=111963&view=diff
==============================================================================
--- llvm/trunk/test/MC/COFF/symbol-fragment-offset.ll (original)
+++ llvm/trunk/test/MC/COFF/symbol-fragment-offset.ll Tue Aug 24 16:04:52 2010
@@ -1,9 +1,9 @@
-; RUN: llc -filetype=obj %s -o %t
-; RUN: coff-dump.py %abs_tmp | FileCheck %s
+; The purpose of this test is to see if the COFF object writer is emitting the
+; proper relocations for multiple pieces of data in a single data fragment.
 
-; ModuleID = 'coff-fragment-test.c'
-target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
-target triple = "i686-pc-win32"
+; RUN: llc -filetype=obj -mtriple i686-pc-win32 %s -o %t
+; RUN: coff-dump.py %abs_tmp | FileCheck %s
+; RUN: llc -filetype=obj -mtriple x86_64-pc-win32 %s -o %t
 
 @.str = private constant [7 x i8] c"Hello \00"    ; <[7 x i8]*> [#uses=1]
 @str = internal constant [7 x i8] c"World!\00"    ; <[7 x i8]*> [#uses=1]





More information about the llvm-commits mailing list