[XCOFF][AIX] Support relocation generation for large code model
authorjasonliu <jasonliu.development@gmail.com>
Wed, 26 Aug 2020 16:08:43 +0000 (16:08 +0000)
committerjasonliu <jasonliu.development@gmail.com>
Wed, 26 Aug 2020 17:12:28 +0000 (17:12 +0000)
Summary:
Support TOCU and TOCL relocation type for object file generation.

Reviewed by: DiggerLin

Differential Revision: https://reviews.llvm.org/D84549

llvm/lib/MC/XCOFFObjectWriter.cpp
llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
llvm/test/CodeGen/PowerPC/aix-xcoff-reloc-large.ll [new file with mode: 0644]

index d6565f2..e0dee7e 100644 (file)
@@ -49,6 +49,7 @@ namespace {
 
 constexpr unsigned DefaultSectionAlign = 4;
 constexpr int16_t MaxSectionIndex = INT16_MAX;
+constexpr uint16_t MaxTOCSizeInARegion = UINT16_MAX;
 
 // Packs the csect's alignment and type into a byte.
 uint8_t getEncodedType(const MCSectionXCOFF *);
@@ -309,6 +310,7 @@ CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
            "in this CsectGroup.");
     return TOCCsects;
   case XCOFF::XMC_TC:
+  case XCOFF::XMC_TE:
     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
            "Only an initialized csect can contain TC entry.");
     assert(!TOCCsects.empty() &&
@@ -432,9 +434,15 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
     // The FixedValue should be symbol's virtual address in this object file
     // plus any constant value that we might get.
     FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
-  else if (Type == XCOFF::RelocationType::R_TOC)
+  else if (Type == XCOFF::RelocationType::R_TOC ||
+           Type == XCOFF::RelocationType::R_TOCL) {
     // The FixedValue should be the TC entry offset from TOC-base.
     FixedValue = SectionMap[SymASec]->Address - TOCCsects.front().Address;
+    if (FixedValue >= MaxTOCSizeInARegion)
+      report_fatal_error(
+          "handling of TOC entries could not fit in the initial TOC "
+          "entry region is not yet supported");
+  }
 
   assert(
       (TargetObjectWriter->is64Bit() ||
index d672d54..77b0331 100644 (file)
@@ -58,14 +58,19 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
   switch ((unsigned)Fixup.getKind()) {
   default:
     report_fatal_error("Unimplemented fixup kind.");
-  case PPC::fixup_ppc_half16:
+  case PPC::fixup_ppc_half16: {
+    const uint8_t SignAndSizeForHalf16 = EncodedSignednessIndicator | 15;
     switch (Modifier) {
     default:
       report_fatal_error("Unsupported modifier for half16 fixup.");
     case MCSymbolRefExpr::VK_None:
-      return {XCOFF::RelocationType::R_TOC, EncodedSignednessIndicator | 15};
+      return {XCOFF::RelocationType::R_TOC, SignAndSizeForHalf16};
+    case MCSymbolRefExpr::VK_PPC_U:
+      return {XCOFF::RelocationType::R_TOCU, SignAndSizeForHalf16};
+    case MCSymbolRefExpr::VK_PPC_L:
+      return {XCOFF::RelocationType::R_TOCL, SignAndSizeForHalf16};
     }
-    break;
+  } break;
   case PPC::fixup_ppc_br24:
     // Branches are 4 byte aligned, so the 24 bits we encode in
     // the instruction actually represents a 26 bit offset.
diff --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-reloc-large.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-reloc-large.ll
new file mode 100644 (file)
index 0000000..18aea72
--- /dev/null
@@ -0,0 +1,90 @@
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff \
+; RUN:     -filetype=obj -code-model=large -o %t.o < %s
+; RUN: llvm-readobj --relocs --expand-relocs %t.o | FileCheck --check-prefixes=RELOC %s
+; RUN: llvm-objdump -D -r --symbol-description %t.o | FileCheck --check-prefix=DIS %s
+
+@a = global i32 2, align 4
+@b = global i32 10, align 4
+@c = global i32 11, align 4
+
+define i32 @foo() {
+entry:
+  %0 = load i32, i32* @a, align 4
+  %1 = load i32, i32* @b, align 4
+  %add = add nsw i32 %0, %1
+  %2 = load i32, i32* @c, align 4
+  %add1 = add nsw i32 %add, %2
+  ret i32 %add1
+}
+
+; RELOC:        Section (index: {{[0-9]+}}) .text {
+; RELOC-NEXT:   Relocation {
+; RELOC-NEXT:     Virtual Address: 0x2
+; RELOC-NEXT:     Symbol: a ([[#INDX:]])
+; RELOC-NEXT:     IsSigned: No
+; RELOC-NEXT:     FixupBitValue: 0
+; RELOC-NEXT:     Length: 16
+; RELOC-NEXT:     Type: R_TOCU (0x30)
+; RELOC-NEXT:   }
+; RELOC-NEXT:   Relocation {
+; RELOC-NEXT:     Virtual Address: 0x6
+; RELOC-NEXT:     Symbol: a ([[#INDX]])
+; RELOC-NEXT:     IsSigned: No
+; RELOC-NEXT:     FixupBitValue: 0
+; RELOC-NEXT:     Length: 16
+; RELOC-NEXT:     Type: R_TOCL (0x31)
+; RELOC-NEXT:   }
+; RELOC-NEXT:   Relocation {
+; RELOC-NEXT:     Virtual Address: 0xE
+; RELOC-NEXT:     Symbol: b ([[#INDX+2]])
+; RELOC-NEXT:     IsSigned: No
+; RELOC-NEXT:     FixupBitValue: 0
+; RELOC-NEXT:     Length: 16
+; RELOC-NEXT:     Type: R_TOCU (0x30)
+; RELOC-NEXT:   }
+; RELOC-NEXT:   Relocation {
+; RELOC-NEXT:     Virtual Address: 0x12
+; RELOC-NEXT:     Symbol: b ([[#INDX+2]])
+; RELOC-NEXT:     IsSigned: No
+; RELOC-NEXT:     FixupBitValue: 0
+; RELOC-NEXT:     Length: 16
+; RELOC-NEXT:     Type: R_TOCL (0x31)
+; RELOC-NEXT:   }
+; RELOC-NEXT:   Relocation {
+; RELOC-NEXT:     Virtual Address: 0x1A
+; RELOC-NEXT:     Symbol: c ([[#INDX+4]])
+; RELOC-NEXT:     IsSigned: No
+; RELOC-NEXT:     FixupBitValue: 0
+; RELOC-NEXT:     Length: 16
+; RELOC-NEXT:     Type: R_TOCU (0x30)
+; RELOC-NEXT:   }
+; RELOC-NEXT:   Relocation {
+; RELOC-NEXT:     Virtual Address: 0x1E
+; RELOC-NEXT:     Symbol: c ([[#INDX+4]])
+; RELOC-NEXT:     IsSigned: No
+; RELOC-NEXT:     FixupBitValue: 0
+; RELOC-NEXT:     Length: 16
+; RELOC-NEXT:     Type: R_TOCL (0x31)
+; RELOC-NEXT:   }
+
+; DIS:        Disassembly of section .text:
+; DIS-EMPTY:
+; DIS-NEXT:   00000000 (idx: {{[0-9]+}}) .foo:
+; DIS-NEXT:          0: 3c 62 00 00   addis 3, 2, 0
+; DIS-NEXT:                           00000002:  R_TOCU       (idx: [[#INDX:]]) a[TE]
+; DIS-NEXT:          4: 80 63 00 00   lwz 3, 0(3)
+; DIS-NEXT:                           00000006:  R_TOCL       (idx: [[#INDX]]) a[TE]
+; DIS-NEXT:          8: 80 63 00 00   lwz 3, 0(3)
+; DIS-NEXT:          c: 3c 82 00 00   addis 4, 2, 0
+; DIS-NEXT:                           0000000e:  R_TOCU       (idx: [[#INDX+2]]) b[TE]
+; DIS-NEXT:         10: 80 84 00 04   lwz 4, 4(4)
+; DIS-NEXT:                           00000012:  R_TOCL       (idx: [[#INDX+2]]) b[TE]
+; DIS-NEXT:         14: 80 84 00 00   lwz 4, 0(4)
+; DIS-NEXT:         18: 3c a2 00 00   addis 5, 2, 0
+; DIS-NEXT:                           0000001a:  R_TOCU       (idx: [[#INDX+4]]) c[TE]
+; DIS-NEXT:         1c: 80 a5 00 08   lwz 5, 8(5)
+; DIS-NEXT:                           0000001e:  R_TOCL       (idx: [[#INDX+4]]) c[TE]
+; DIS-NEXT:         20: 7c 63 22 14   add 3, 3, 4
+; DIS-NEXT:         24: 80 a5 00 00   lwz 5, 0(5)
+; DIS-NEXT:         28: 7c 63 2a 14   add 3, 3, 5
+; DIS-NEXT:         2c: 4e 80 00 20   blr