Relocations needed for helloworld()

From: Jack Carter <jcarter@mips.com>


---
 lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp    |   10 +++++
 .../Mips/MCTargetDesc/MipsELFObjectWriter.cpp      |   16 ++++++++
 lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h      |   12 ++++++
 lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp |   19 +++++++++-
 test/MC/Mips/elf-N64.ll                            |   34 ++++++++++++++++++
 test/Scripts/elf-dump                              |   38 +++++++++++++++-----
 6 files changed, 117 insertions(+), 12 deletions(-)
 create mode 100644 test/MC/Mips/elf-N64.ll

diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
index 9b4caf6..b2b30e3 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -36,6 +36,10 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
   case FK_GPRel_4:
   case FK_Data_4:
   case Mips::fixup_Mips_LO16:
+  case Mips::fixup_Mips_GPOFF_HI:
+  case Mips::fixup_Mips_GPOFF_LO:
+  case Mips::fixup_Mips_GOT_PAGE:
+  case Mips::fixup_Mips_GOT_OFST:
     break;
   case Mips::fixup_Mips_PC16:
     // So far we are only using this type for branches.
@@ -156,7 +160,11 @@ public:
       { "fixup_Mips_TLSLDM",       0,     16,   0 },
       { "fixup_Mips_DTPREL_HI",    0,     16,   0 },
       { "fixup_Mips_DTPREL_LO",    0,     16,   0 },
-      { "fixup_Mips_Branch_PCRel", 0,     16,  MCFixupKindInfo::FKF_IsPCRel }
+      { "fixup_Mips_Branch_PCRel", 0,     16,  MCFixupKindInfo::FKF_IsPCRel },
+      { "fixup_Mips_GPOFF_HI",     0,     16,   0 },
+      { "fixup_Mips_GPOFF_LO",     0,     16,   0 },
+      { "fixup_Mips_GOT_PAGE",     0,     16,   0 },
+      { "fixup_Mips_GOT_OFST",     0,     16,   0 }
     };
 
     if (Kind < FirstTargetFixupKind)
diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
index 9ccc659..16fb92f 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
@@ -150,6 +150,22 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
   case Mips::fixup_Mips_PC16:
     Type = ELF::R_MIPS_PC16;
     break;
+  case Mips::fixup_Mips_GOT_PAGE:
+    Type = ELF::R_MIPS_GOT_PAGE;
+    break;
+  case Mips::fixup_Mips_GOT_OFST:
+    Type = ELF::R_MIPS_GOT_OFST;
+    break;
+  case Mips::fixup_Mips_GPOFF_HI:
+    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
+    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
+    Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type);
+    break;
+  case Mips::fixup_Mips_GPOFF_LO:
+    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
+    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
+    Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type);
+    break;
   }
   return Type;
 }
diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
index 9b76eda..c5b6c4f 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
@@ -95,6 +95,18 @@ namespace Mips {
     // PC relative branch fixup resulting in - R_MIPS_PC16
     fixup_Mips_Branch_PCRel,
 
+    // resulting in -
+    fixup_Mips_GPOFF_HI,
+
+    // resulting in -
+    fixup_Mips_GPOFF_LO,
+
+    // resulting in - R_MIPS_PAGE
+    fixup_Mips_GOT_PAGE,
+
+    // resulting in - R_MIPS_GOT_OFST
+    fixup_Mips_GOT_OFST,
+
     // Marker
     LastTargetFixupKind,
     NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
index 6353da3..8d37f9c 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -199,6 +199,23 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
   Mips::Fixups FixupKind = Mips::Fixups(0);
 
   switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
+  default: llvm_unreachable("Unknown fixup kind!");
+    break;
+  case MCSymbolRefExpr::VK_Mips_GOT_DISP :
+    llvm_unreachable("fixup kind VK_Mips_GOT_DISP not supported for direct object!");
+    break;
+  case MCSymbolRefExpr::VK_Mips_GPOFF_HI :
+    FixupKind = Mips::fixup_Mips_GPOFF_HI;
+    break;
+  case MCSymbolRefExpr::VK_Mips_GPOFF_LO :
+    FixupKind = Mips::fixup_Mips_GPOFF_LO;
+    break;
+  case MCSymbolRefExpr::VK_Mips_GOT_PAGE :
+    FixupKind = Mips::fixup_Mips_GOT_PAGE;
+    break;
+  case MCSymbolRefExpr::VK_Mips_GOT_OFST :
+    FixupKind = Mips::fixup_Mips_GOT_OFST;
+    break;
   case MCSymbolRefExpr::VK_Mips_GPREL:
     FixupKind = Mips::fixup_Mips_GPREL16;
     break;
@@ -238,8 +255,6 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
   case MCSymbolRefExpr::VK_Mips_TPREL_LO:
     FixupKind = Mips::fixup_Mips_TPREL_LO;
     break;
-  default:
-    break;
   } // switch
 
   Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind)));
diff --git a/test/MC/Mips/elf-N64.ll b/test/MC/Mips/elf-N64.ll
new file mode 100644
index 0000000..aa10e64
--- /dev/null
+++ b/test/MC/Mips/elf-N64.ll
@@ -0,0 +1,34 @@
+; RUN: llc -filetype=obj -march=mips64el -mcpu=mips64 %s -o - | elf-dump --dump-section-data  | FileCheck %s
+
+; Check for N64 relocation production.
+;
+; ModuleID = '../hello.c'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v64:64:64-n32"
+target triple = "mips64el-unknown-linux"
+
+@str = private unnamed_addr constant [12 x i8] c"hello world\00"
+
+define i32 @main() nounwind {
+entry:
+; Check that the appropriate relocations were created.
+
+; R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16
+; CHECK:     ('r_type3', 0x05)
+; CHECK-NEXT:     ('r_type2', 0x18)
+; CHECK-NEXT:     ('r_type', 0x07)
+
+; R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16
+; CHECK:     ('r_type3', 0x06)
+; CHECK-NEXT:     ('r_type2', 0x18)
+; CHECK-NEXT:     ('r_type', 0x07)
+
+; R_MIPS_GOT_OFST/R_MIPS_NONE/R_MIPS_NONE
+; CHECK:     ('r_type3', 0x00)
+; CHECK-NEXT:     ('r_type2', 0x00)
+; CHECK-NEXT:     ('r_type', 0x15)
+
+  %puts = tail call i32 @puts(i8* getelementptr inbounds ([12 x i8]* @str, i64 0, i64 0))
+  ret i32 0
+
+}
+declare i32 @puts(i8* nocapture) nounwind
diff --git a/test/Scripts/elf-dump b/test/Scripts/elf-dump
index 58ca177..69cdacd 100755
--- a/test/Scripts/elf-dump
+++ b/test/Scripts/elf-dump
@@ -15,6 +15,7 @@ class Reader:
             self.file = open(path, "rb")
         self.isLSB = None
         self.is64Bit = None
+        self.isN64 = False
 
     def seek(self, pos):
         self.file.seek(pos)
@@ -122,15 +123,28 @@ def dumpRel(f, section, dumprela = False):
         f.seek(section.sh_offset[0] + index * section.sh_entsize[0])
         print "    # Relocation %s" % index
         print "    (('r_offset', %s)" % common_dump.HexDump(f.readWord())
-        r_info = f.readWord()[0]
-        if f.is64Bit:
-            r_sym = (r_info >> 32, 32)
-            r_type = (r_info & 0xffffffff, 32)
+
+        if f.isN64:
+            r_sym =   f.read32()
+            r_ssym =  f.read8()
+            r_type3 = f.read8()
+            r_type2 = f.read8()
+            r_type =  f.read8()
+            print "     ('r_sym', %s)" % common_dump.HexDump(r_sym)
+            print "     ('r_ssym', %s)" % common_dump.HexDump(r_ssym)
+            print "     ('r_type3', %s)" % common_dump.HexDump(r_type3)
+            print "     ('r_type2', %s)" % common_dump.HexDump(r_type2)
+            print "     ('r_type', %s)" % common_dump.HexDump(r_type)
         else:
-            r_sym = (r_info >> 8, 24)
-            r_type = (r_info & 0xff, 8)
-        print "     ('r_sym', %s)" % common_dump.HexDump(r_sym)
-        print "     ('r_type', %s)" % common_dump.HexDump(r_type)
+            r_info = f.readWord()[0]
+            if f.is64Bit:
+                r_sym = (r_info >> 32, 32)
+                r_type = (r_info & 0xffffffff, 32)
+            else:
+                r_sym = (r_info >> 8, 24)
+                r_type = (r_info & 0xff, 8)
+            print "     ('r_sym', %s)" % common_dump.HexDump(r_sym)
+            print "     ('r_type', %s)" % common_dump.HexDump(r_type)
         if dumprela:
             print "     ('r_addend', %s)" % common_dump.HexDump(f.readWord())
         print "    ),"
@@ -166,7 +180,13 @@ def dumpELF(path, opts):
     f.seek(16) # Seek to end of e_ident.
 
     print "('e_type', %s)" % common_dump.HexDump(f.read16())
-    print "('e_machine', %s)" % common_dump.HexDump(f.read16())
+
+    # Does any other architecture use N64?
+    e_machine = f.read16()
+    if e_machine[0] == 0x0008 and f.is64Bit: # EM_MIPS && 64 bit
+        f.isN64 = True 
+    
+    print "('e_machine', %s)" % common_dump.HexDump(e_machine)
     print "('e_version', %s)" % common_dump.HexDump(f.read32())
     print "('e_entry', %s)" % common_dump.HexDump(f.readWord())
     print "('e_phoff', %s)" % common_dump.HexDump(f.readWord())
