[llvm] a03a6e9 - [AIX] [XCOFF] Add support for common and local common symbols in the TOC (#79530)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 31 13:34:25 PST 2024


Author: Zaara Syeda
Date: 2024-01-31T16:34:21-05:00
New Revision: a03a6e99647318a86ea398c42e241da43e3c550e

URL: https://github.com/llvm/llvm-project/commit/a03a6e99647318a86ea398c42e241da43e3c550e
DIFF: https://github.com/llvm/llvm-project/commit/a03a6e99647318a86ea398c42e241da43e3c550e.diff

LOG: [AIX] [XCOFF] Add support for common and local common symbols in the TOC (#79530)

This patch adds support for common and local symbols in the TOC for AIX.
Note that we need to update isVirtualSection so as a common symbol in
TOC will have the symbol type XTY_CM and will be initialized when placed
in the TOC so sections with this type are no longer virtual.

---------

Co-authored-by: Zaara Syeda <syzaara at ca.ibm.com>

Added: 
    llvm/test/CodeGen/PowerPC/basic-toc-data-private-linkage.ll
    llvm/test/CodeGen/PowerPC/toc-data-common.ll

Modified: 
    llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    llvm/lib/MC/MCSectionXCOFF.cpp
    llvm/lib/MC/XCOFFObjectWriter.cpp
    llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
    llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
    llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index a69b71451736f..b0cdd6321a5f9 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2424,8 +2424,10 @@ MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal(
     if (GVar->hasAttribute("toc-data")) {
       SmallString<128> Name;
       getNameWithPrefix(Name, GO, TM);
+      XCOFF::SymbolType symType =
+          GO->hasCommonLinkage() ? XCOFF::XTY_CM : XCOFF::XTY_SD;
       return getContext().getXCOFFSection(
-          Name, Kind, XCOFF::CsectProperties(XCOFF::XMC_TD, XCOFF::XTY_SD),
+          Name, Kind, XCOFF::CsectProperties(XCOFF::XMC_TD, symType),
           /* MultiSymbolsAllowed*/ true);
     }
 

diff  --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp
index 02b1b972f339b..95d32e3580e3f 100644
--- a/llvm/lib/MC/MCSectionXCOFF.cpp
+++ b/llvm/lib/MC/MCSectionXCOFF.cpp
@@ -82,6 +82,11 @@ void MCSectionXCOFF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
   }
 
   if (isCsect() && getMappingClass() == XCOFF::XMC_TD) {
+    // Common csect type (uninitialized storage) does not have to print csect
+    // directive for section switching unless it is local.
+    if (getKind().isCommon() && !getKind().isBSSLocal())
+      return;
+
     assert((getKind().isBSSExtern() || getKind().isBSSLocal()) &&
            "Unexepected section kind for toc-data");
     printCsectDirective(OS);
@@ -135,5 +140,7 @@ bool MCSectionXCOFF::isVirtualSection() const {
     return false;
   assert(isCsect() &&
          "Handling for isVirtualSection not implemented for this section!");
-  return XCOFF::XTY_CM == CsectProp->Type;
+  // XTY_CM sections are virtual except for toc-data symbols.
+  return (XCOFF::XTY_CM == CsectProp->Type) &&
+         (getMappingClass() != XCOFF::XMC_TD);
 }

diff  --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index 343e2fc877bc3..11f8a72edeada 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -533,9 +533,15 @@ CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
     return TOCCsects;
   case XCOFF::XMC_TC:
   case XCOFF::XMC_TE:
-  case XCOFF::XMC_TD:
     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
-           "Only an initialized csect can contain TC entry.");
+           "A TOC symbol must be an initialized csect.");
+    assert(!TOCCsects.empty() &&
+           "We should at least have a TOC-base in this CsectGroup.");
+    return TOCCsects;
+  case XCOFF::XMC_TD:
+    assert((XCOFF::XTY_SD == MCSec->getCSectType() ||
+            XCOFF::XTY_CM == MCSec->getCSectType()) &&
+           "Symbol type incompatible with toc-data.");
     assert(!TOCCsects.empty() &&
            "We should at least have a TOC-base in this CsectGroup.");
     return TOCCsects;

diff  --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 528267cb01329..ce600654df72a 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -2571,12 +2571,18 @@ void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
     GVSym->setStorageClass(
         TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
 
-    if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal())
+    if (GVKind.isBSSLocal() && Csect->getMappingClass() == XCOFF::XMC_TD) {
+      OutStreamer->emitZeros(Size);
+    } else if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal()) {
+      assert(Csect->getMappingClass() != XCOFF::XMC_TD &&
+             "BSS local toc-data already handled and TLS variables "
+             "incompatible with XMC_TD");
       OutStreamer->emitXCOFFLocalCommonSymbol(
           OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()), Size,
           GVSym, Alignment);
-    else
+    } else {
       OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);
+    }
     return;
   }
 
@@ -2737,8 +2743,17 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
     TS->emitTCEntry(*I.first.first, I.first.second);
   }
 
-  for (const auto *GV : TOCDataGlobalVars)
-    emitGlobalVariableHelper(GV);
+  // Traverse the list of global variables twice, emitting all of the
+  // non-common global variables before the common ones, as emitting a
+  // .comm directive changes the scope from .toc to the common symbol.
+  for (const auto *GV : TOCDataGlobalVars) {
+    if (!GV->hasCommonLinkage())
+      emitGlobalVariableHelper(GV);
+  }
+  for (const auto *GV : TOCDataGlobalVars) {
+    if (GV->hasCommonLinkage())
+      emitGlobalVariableHelper(GV);
+  }
 }
 
 bool PPCAIXAsmPrinter::doInitialization(Module &M) {

diff  --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 24e067f2ebfba..9fad96340737c 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -551,13 +551,10 @@ static bool hasTocDataAttr(SDValue Val, unsigned PointerSize) {
          "A GlobalVariable with size larger than a TOC entry is not currently "
          "supported by the toc data transformation.");
 
-  if (GV->hasLocalLinkage() || GV->hasPrivateLinkage())
-    report_fatal_error("A GlobalVariable with private or local linkage is not "
+  if (GV->hasPrivateLinkage())
+    report_fatal_error("A GlobalVariable with private linkage is not "
                        "currently supported by the toc data transformation.");
 
-  assert(!GV->hasCommonLinkage() &&
-         "Tentative definitions cannot have the mapping class XMC_TD.");
-
   return true;
 }
 

diff  --git a/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll b/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
index 0e131672b421e..4352852533ffb 100644
--- a/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
+++ b/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
@@ -1,6 +1,6 @@
-; RUN: not --crash llc  -mtriple powerpc-ibm-aix-xcoff  -verify-machineinstrs \
+; RUN: llc  -mtriple powerpc-ibm-aix-xcoff  -verify-machineinstrs \
 ; RUN:     < %s 2>&1 | FileCheck %s
-; RUN: not --crash llc  -mtriple powerpc64-ibm-aix-xcoff  -verify-machineinstrs \
+; RUN: llc  -mtriple powerpc64-ibm-aix-xcoff  -verify-machineinstrs \
 ; RUN:     < %s 2>&1 | FileCheck %s
 
 @ilocal = internal global i32 0, align 4 #0
@@ -11,6 +11,8 @@ define dso_local i32 @read_i32_local_linkage() {
     ret i32 %0
 }
 
-; CHECK: LLVM ERROR: A GlobalVariable with private or local linkage is not currently supported by the toc data transformation.
-
 attributes #0 = { "toc-data" }
+
+; CHECK:      .toc
+; CHECK-NEXT: .csect ilocal[TD],2
+; CHECK-NEXT: .space  4

diff  --git a/llvm/test/CodeGen/PowerPC/basic-toc-data-private-linkage.ll b/llvm/test/CodeGen/PowerPC/basic-toc-data-private-linkage.ll
new file mode 100644
index 0000000000000..a3831d8f0f3c8
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/basic-toc-data-private-linkage.ll
@@ -0,0 +1,15 @@
+; RUN: not --crash llc  -mtriple powerpc-ibm-aix-xcoff  -verify-machineinstrs \
+; RUN:     < %s 2>&1 | FileCheck %s
+; RUN: not --crash llc  -mtriple powerpc64-ibm-aix-xcoff  -verify-machineinstrs \
+; RUN:     < %s 2>&1 | FileCheck %s
+
+ at iprivate = private global i32 55 #0
+
+define nonnull ptr @get() local_unnamed_addr {
+entry:
+  ret ptr @iprivate
+}
+
+attributes #0 = { "toc-data" }
+
+; CHECK: LLVM ERROR: A GlobalVariable with private linkage is not currently supported by the toc data transformation.

diff  --git a/llvm/test/CodeGen/PowerPC/toc-data-common.ll b/llvm/test/CodeGen/PowerPC/toc-data-common.ll
new file mode 100644
index 0000000000000..7747f2eecc935
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/toc-data-common.ll
@@ -0,0 +1,148 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s -DINSTR=lwz --check-prefix=CHECK
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s -DINSTR=ld --check-prefix=CHECK
+
+; RUN: llc -filetype=obj -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s -o %t32.o
+; RUN: llvm-objdump -t --symbol-description %t32.o | FileCheck %s --check-prefix=OBJ32
+
+; RUN: llc -filetype=obj -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s -o %t64.o
+; RUN: llvm-objdump -t --symbol-description %t64.o | FileCheck %s --check-prefix=OBJ64
+
+ at a1 = common global i32 0, align 4 #0
+ at a2 = global i32 0, align 4 #0
+ at a3 = common global i32 0, align 4
+ at a4 = global i32 0, align 4
+
+define void @set(i32 noundef %_a) {
+; CHECK-LABEL: set:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: la 4, a2[TD](2)
+; CHECK-NEXT: la 5, a1[TD](2)
+; CHECK-NEXT: stw 3, 0(4)
+; CHECK-NEXT: [[INSTR]] 4, L..C0(2) # @a4
+; CHECK-NEXT: stw 3, 0(5)
+; CHECK-NEXT: [[INSTR]] 5, L..C1(2) # @a3
+; CHECK-NEXT: stw 3, 0(4)
+; CHECK-NEXT: stw 3, 0(5)
+; CHECK-NEXT: blr
+entry:
+store i32 %_a, ptr @a2, align 4
+store i32 %_a, ptr @a1, align 4
+store i32 %_a, ptr @a4, align 4
+store i32 %_a, ptr @a3, align 4
+ret void
+}
+
+define i32 @get1() {
+; CHECK-LABEL: get1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: la 3, a2[TD](2)
+; CHECK-NEXT: lwz 3, 0(3)
+; CHECK-NEXT: blr
+entry:
+%0 = load i32, ptr @a2, align 4
+ret i32 %0
+}
+
+define i32 @get2() {
+; CHECK-LABEL: get2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: la 3, a1[TD](2)
+; CHECK-NEXT: lwz 3, 0(3)
+; CHECK-NEXT: blr
+entry:
+%0 = load i32, ptr @a1, align 4
+ret i32 %0
+}
+
+define i32 @get3() {
+; CHECK-LABEL: get3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: [[INSTR]] 3, L..C0(2) # @a4
+; CHECK-NEXT: lwz 3, 0(3)
+; CHECK-NEXT: blr
+entry:
+%0 = load i32, ptr @a4, align 4
+ret i32 %0
+}
+
+define i32 @get4() {
+; CHECK-LABEL: get4:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: [[INSTR]] 3, L..C1(2) # @a3
+; CHECK-NEXT: lwz 3, 0(3)
+; CHECK-NEXT: blr
+entry:
+%0 = load i32, ptr @a3, align 4
+ret i32 %0
+}
+
+define nonnull ptr @escape1() {
+; CHECK-LABEL: escape1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: la 3, a2[TD](2)
+; CHECK-NEXT: blr
+entry:
+ret ptr @a2
+}
+
+define nonnull ptr @escape2() {
+; CHECK-LABEL: escape2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: la 3, a1[TD](2)
+; CHECK-NEXT: blr
+entry:
+ret ptr @a1
+}
+
+define nonnull ptr @escape3() {
+; CHECK-LABEL: escape3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: [[INSTR]] 3, L..C0(2) # @a4
+; CHECK-NEXT: blr
+entry:
+ret ptr @a4
+}
+
+define nonnull ptr @escape4() {
+; CHECK-LABEL: escape4:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: [[INSTR]] 3, L..C1(2) # @a3
+; CHECK-NEXT: blr
+entry:
+ret ptr @a3
+}
+
+attributes #0 = { "toc-data" }
+
+; CHECK: .comm a3[RW],4,2 # @a3
+; CHECK-NEXT: .csect a4[RW],2
+; CHECK-NEXT: .globl a4[RW] # @a4
+; CHECK-NEXT: .align 2
+; CHECK-NEXT: .vbyte 4, 0 # 0x0
+; CHECK-NEXT: .toc
+; CHECK-LABEL: L..C0:
+; CHECK-NEXT: .tc a4[TC],a4[RW]
+; CHECK-LABEL: L..C1:
+; CHECK-NEXT: .tc a3[TC],a3[RW]
+; CHECK-NEXT: .csect a2[TD],2
+; CHECK-NEXT: .globl a2[TD] # @a2
+; CHECK-NEXT: .align 2
+; CHECK-NEXT: .vbyte 4, 0 # 0x0
+; CHECK-NEXT: .comm a1[TD],4,2 # @a1
+
+; OBJ32:       {{([[:xdigit:]]{8})}} g     O .data  00000004 (idx: {{[0-9]+}}) a4[RW]
+; OBJ32-LABEL: {{([[:xdigit:]]{8})}} l       .data  00000000 (idx: {{[0-9]+}}) TOC[TC0]
+; OBJ32-NEXT:  {{([[:xdigit:]]{8})}} l     O .data  00000004 (idx: {{[0-9]+}}) a4[TC]
+; OBJ32-NEXT:  {{([[:xdigit:]]{8})}} l     O .data  00000004 (idx: {{[0-9]+}}) a3[TC]
+; OBJ32-NEXT:  {{([[:xdigit:]]{8})}} g     O .data  00000004 (idx: {{[0-9]+}}) a2[TD]
+; OBJ32-NEXT:  {{([[:xdigit:]]{8})}} g     O *COM*  00000004 (idx: {{[0-9]+}}) a1[TD]
+; OBJ32-NEXT:  {{([[:xdigit:]]{8})}} g     O *COM*  00000004 (idx: {{[0-9]+}}) a3[RW]
+
+; OBJ64:       {{([[:xdigit:]]{16})}} g     O .data  0000000000000004 (idx: {{[0-9]+}}) a4[RW]
+; OBJ64-LABEL: {{([[:xdigit:]]{16})}} l       .data  0000000000000000 (idx: {{[0-9]+}}) TOC[TC0]
+; OBJ64-NEXT:  {{([[:xdigit:]]{16})}} l     O .data  0000000000000008 (idx: {{[0-9]+}}) a4[TC]
+; OBJ64-NEXT:  {{([[:xdigit:]]{16})}} l     O .data  0000000000000008 (idx: {{[0-9]+}}) a3[TC]
+; OBJ64-NEXT:  {{([[:xdigit:]]{16})}} g     O .data  0000000000000004 (idx: {{[0-9]+}}) a2[TD]
+; OBJ64-NEXT:  {{([[:xdigit:]]{16})}} g     O *COM*  0000000000000004 (idx: {{[0-9]+}}) a1[TD]
+; OBJ64-NEXT:  {{([[:xdigit:]]{16})}} g     O *COM*  0000000000000004 (idx: {{[0-9]+}}) a3[RW]


        


More information about the llvm-commits mailing list