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

Zaara Syeda via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 29 13:02:09 PST 2024


https://github.com/syzaara updated https://github.com/llvm/llvm-project/pull/79530

>From 15471a2bf6c17ce2197ba7ebf20668b6c7b220ad Mon Sep 17 00:00:00 2001
From: Zaara Syeda <syzaara at cpap8104.rtp.raleigh.ibm.com>
Date: Thu, 25 Jan 2024 19:32:41 -0500
Subject: [PATCH 1/2] [AIX] [XCOFF] Add support for common and local common
 symbols in the TOC

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.
---
 llvm/lib/MC/MCSectionXCOFF.cpp                |  9 +++++++-
 llvm/lib/MC/XCOFFObjectWriter.cpp             | 10 ++++++--
 llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp     | 23 +++++++++++++++----
 llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp   |  7 ++----
 .../PowerPC/basic-toc-data-local-linkage.ll   | 10 ++++----
 5 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/MC/MCSectionXCOFF.cpp b/llvm/lib/MC/MCSectionXCOFF.cpp
index 02b1b972f339bf0..95d32e3580e3f55 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 343e2fc877bc3b1..11f8a72edeadafc 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 4f15ba497d84c45..1f4476d3907cdd3 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -2572,12 +2572,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;
   }
 
@@ -2738,8 +2744,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 b57d185bb638b8c..b86c9abeecf35f8 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 0e131672b421e4b..4352852533ffb31 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

>From 11aba623cc1d3f2fc4bc0104a33f5d0e50b85c05 Mon Sep 17 00:00:00 2001
From: Zaara Syeda <syzaara at cpap8104.rtp.raleigh.ibm.com>
Date: Mon, 29 Jan 2024 16:01:13 -0500
Subject: [PATCH 2/2] Add tests

---
 .../CodeGen/TargetLoweringObjectFileImpl.cpp  |   3 +-
 .../PowerPC/basic-toc-data-private-linkage.ll |  15 ++
 llvm/test/CodeGen/PowerPC/toc-data-common.ll  | 204 ++++++++++++++++++
 3 files changed, 221 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/basic-toc-data-private-linkage.ll
 create mode 100644 llvm/test/CodeGen/PowerPC/toc-data-common.ll

diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index f3ba380818901ca..03b1a14db1f55b1 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2421,8 +2421,9 @@ 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/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 000000000000000..a3831d8f0f3c8a2
--- /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 000000000000000..097f787448da772
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/toc-data-common.ll
@@ -0,0 +1,204 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s --check-prefix CHECK
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s --check-prefix CHECK64
+
+; 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: lwz 4, L..C0(2) # @a4
+; CHECK-NEXT: stw 3, 0(5)
+; CHECK-NEXT: lwz 5, L..C1(2) # @a3
+; CHECK-NEXT: stw 3, 0(4)
+; CHECK-NEXT: stw 3, 0(5)
+; CHECK-NEXT: blr
+;
+; CHECK64-LABEL: set:
+; CHECK64: # %bb.0: # %entry
+; CHECK64-NEXT: la 4, a2[TD](2)
+; CHECK64-NEXT: la 5, a1[TD](2)
+; CHECK64-NEXT: stw 3, 0(4)
+; CHECK64-NEXT: ld 4, L..C0(2) # @a4
+; CHECK64-NEXT: stw 3, 0(5)
+; CHECK64-NEXT: ld 5, L..C1(2) # @a3
+; CHECK64-NEXT: stw 3, 0(4)
+; CHECK64-NEXT: stw 3, 0(5)
+; CHECK64-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
+;
+; CHECK64-LABEL: get1:
+; CHECK64: # %bb.0: # %entry
+; CHECK64-NEXT: la 3, a2[TD](2)
+; CHECK64-NEXT: lwz 3, 0(3)
+; CHECK64-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
+;
+; CHECK64-LABEL: get2:
+; CHECK64: # %bb.0: # %entry
+; CHECK64-NEXT: la 3, a1[TD](2)
+; CHECK64-NEXT: lwz 3, 0(3)
+; CHECK64-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: lwz 3, L..C0(2) # @a4
+; CHECK-NEXT: lwz 3, 0(3)
+; CHECK-NEXT: blr
+;
+; CHECK64-LABEL: get3:
+; CHECK64: # %bb.0: # %entry
+; CHECK64-NEXT: ld 3, L..C0(2) # @a4
+; CHECK64-NEXT: lwz 3, 0(3)
+; CHECK64-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: lwz 3, L..C1(2) # @a3
+; CHECK-NEXT: lwz 3, 0(3)
+; CHECK-NEXT: blr
+;
+; CHECK64-LABEL: get4:
+; CHECK64: # %bb.0: # %entry
+; CHECK64-NEXT: ld 3, L..C1(2) # @a3
+; CHECK64-NEXT: lwz 3, 0(3)
+; CHECK64-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
+;
+; CHECK64-LABEL: escape1:
+; CHECK64: # %bb.0: # %entry
+; CHECK64-NEXT: la 3, a2[TD](2)
+; CHECK64-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
+;
+; CHECK64-LABEL: escape2:
+; CHECK64: # %bb.0: # %entry
+; CHECK64-NEXT: la 3, a1[TD](2)
+; CHECK64-NEXT: blr
+entry:
+ret ptr @a1
+}
+
+define nonnull ptr @escape3() {
+; CHECK-LABEL: escape3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lwz 3, L..C0(2) # @a4
+; CHECK-NEXT: blr
+;
+; CHECK64-LABEL: escape3:
+; CHECK64: # %bb.0: # %entry
+; CHECK64-NEXT: ld 3, L..C0(2) # @a4
+; CHECK64-NEXT: blr
+entry:
+ret ptr @a4
+}
+
+define nonnull ptr @escape4() {
+; CHECK-LABEL: escape4:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lwz 3, L..C1(2) # @a3
+; CHECK-NEXT: blr
+;
+; CHECK64-LABEL: escape4:
+; CHECK64: # %bb.0: # %entry
+; CHECK64-NEXT: ld 3, L..C1(2) # @a3
+; CHECK64-NEXT: blr
+entry:
+ret ptr @a3
+}
+
+attributes #0 = { "toc-data" }
+
+; CHECK,CHECK64: .comm a3[RW],4,2 # @a3
+; CHECK-NEXT,CHECK64-NEXT: .csect a4[RW],2
+; CHECK-NEXT,CHECK64-NEXT: .globl a4[RW] # @a4
+; CHECK-NEXT,CHECK64-NEXT: .align 2
+; CHECK-NEXT,CHECK64-NEXT: .vbyte 4, 0 # 0x0
+; CHECK-NEXT,CHECK64-NEXT: .toc
+; CHECK-LABEL,CHECK64-LABEL: L..C0:
+; CHECK-NEXT,CHECK64-NEXT: .tc a4[TC],a4[RW]
+; CHECK-LABEL,CHECK64-LABEL: L..C1:
+; CHECK-NEXT,CHECK64-NEXT: .tc a3[TC],a3[RW]
+; CHECK-NEXT,CHECK64-NEXT: .csect a2[TD],2
+; CHECK-NEXT,CHECK64-NEXT: .globl a2[TD] # @a2
+; CHECK-NEXT,CHECK64-NEXT: .align 2
+; CHECK-NEXT,CHECK64-NEXT: .vbyte 4, 0 # 0x0
+; CHECK-NEXT,CHECK64-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