Skip to content

Commit a03a6e9

Browse files
authored
[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 <[email protected]>
1 parent 22773e5 commit a03a6e9

File tree

8 files changed

+209
-17
lines changed

8 files changed

+209
-17
lines changed

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2424,8 +2424,10 @@ MCSection *TargetLoweringObjectFileXCOFF::SelectSectionForGlobal(
24242424
if (GVar->hasAttribute("toc-data")) {
24252425
SmallString<128> Name;
24262426
getNameWithPrefix(Name, GO, TM);
2427+
XCOFF::SymbolType symType =
2428+
GO->hasCommonLinkage() ? XCOFF::XTY_CM : XCOFF::XTY_SD;
24272429
return getContext().getXCOFFSection(
2428-
Name, Kind, XCOFF::CsectProperties(XCOFF::XMC_TD, XCOFF::XTY_SD),
2430+
Name, Kind, XCOFF::CsectProperties(XCOFF::XMC_TD, symType),
24292431
/* MultiSymbolsAllowed*/ true);
24302432
}
24312433

llvm/lib/MC/MCSectionXCOFF.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ void MCSectionXCOFF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
8282
}
8383

8484
if (isCsect() && getMappingClass() == XCOFF::XMC_TD) {
85+
// Common csect type (uninitialized storage) does not have to print csect
86+
// directive for section switching unless it is local.
87+
if (getKind().isCommon() && !getKind().isBSSLocal())
88+
return;
89+
8590
assert((getKind().isBSSExtern() || getKind().isBSSLocal()) &&
8691
"Unexepected section kind for toc-data");
8792
printCsectDirective(OS);
@@ -135,5 +140,7 @@ bool MCSectionXCOFF::isVirtualSection() const {
135140
return false;
136141
assert(isCsect() &&
137142
"Handling for isVirtualSection not implemented for this section!");
138-
return XCOFF::XTY_CM == CsectProp->Type;
143+
// XTY_CM sections are virtual except for toc-data symbols.
144+
return (XCOFF::XTY_CM == CsectProp->Type) &&
145+
(getMappingClass() != XCOFF::XMC_TD);
139146
}

llvm/lib/MC/XCOFFObjectWriter.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,9 +533,15 @@ CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
533533
return TOCCsects;
534534
case XCOFF::XMC_TC:
535535
case XCOFF::XMC_TE:
536-
case XCOFF::XMC_TD:
537536
assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
538-
"Only an initialized csect can contain TC entry.");
537+
"A TOC symbol must be an initialized csect.");
538+
assert(!TOCCsects.empty() &&
539+
"We should at least have a TOC-base in this CsectGroup.");
540+
return TOCCsects;
541+
case XCOFF::XMC_TD:
542+
assert((XCOFF::XTY_SD == MCSec->getCSectType() ||
543+
XCOFF::XTY_CM == MCSec->getCSectType()) &&
544+
"Symbol type incompatible with toc-data.");
539545
assert(!TOCCsects.empty() &&
540546
"We should at least have a TOC-base in this CsectGroup.");
541547
return TOCCsects;

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,12 +2571,18 @@ void PPCAIXAsmPrinter::emitGlobalVariableHelper(const GlobalVariable *GV) {
25712571
GVSym->setStorageClass(
25722572
TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
25732573

2574-
if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal())
2574+
if (GVKind.isBSSLocal() && Csect->getMappingClass() == XCOFF::XMC_TD) {
2575+
OutStreamer->emitZeros(Size);
2576+
} else if (GVKind.isBSSLocal() || GVKind.isThreadBSSLocal()) {
2577+
assert(Csect->getMappingClass() != XCOFF::XMC_TD &&
2578+
"BSS local toc-data already handled and TLS variables "
2579+
"incompatible with XMC_TD");
25752580
OutStreamer->emitXCOFFLocalCommonSymbol(
25762581
OutContext.getOrCreateSymbol(GVSym->getSymbolTableName()), Size,
25772582
GVSym, Alignment);
2578-
else
2583+
} else {
25792584
OutStreamer->emitCommonSymbol(GVSym, Size, Alignment);
2585+
}
25802586
return;
25812587
}
25822588

@@ -2737,8 +2743,17 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
27372743
TS->emitTCEntry(*I.first.first, I.first.second);
27382744
}
27392745

2740-
for (const auto *GV : TOCDataGlobalVars)
2741-
emitGlobalVariableHelper(GV);
2746+
// Traverse the list of global variables twice, emitting all of the
2747+
// non-common global variables before the common ones, as emitting a
2748+
// .comm directive changes the scope from .toc to the common symbol.
2749+
for (const auto *GV : TOCDataGlobalVars) {
2750+
if (!GV->hasCommonLinkage())
2751+
emitGlobalVariableHelper(GV);
2752+
}
2753+
for (const auto *GV : TOCDataGlobalVars) {
2754+
if (GV->hasCommonLinkage())
2755+
emitGlobalVariableHelper(GV);
2756+
}
27422757
}
27432758

27442759
bool PPCAIXAsmPrinter::doInitialization(Module &M) {

llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -551,13 +551,10 @@ static bool hasTocDataAttr(SDValue Val, unsigned PointerSize) {
551551
"A GlobalVariable with size larger than a TOC entry is not currently "
552552
"supported by the toc data transformation.");
553553

554-
if (GV->hasLocalLinkage() || GV->hasPrivateLinkage())
555-
report_fatal_error("A GlobalVariable with private or local linkage is not "
554+
if (GV->hasPrivateLinkage())
555+
report_fatal_error("A GlobalVariable with private linkage is not "
556556
"currently supported by the toc data transformation.");
557557

558-
assert(!GV->hasCommonLinkage() &&
559-
"Tentative definitions cannot have the mapping class XMC_TD.");
560-
561558
return true;
562559
}
563560

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs \
1+
; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs \
22
; RUN: < %s 2>&1 | FileCheck %s
3-
; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs \
3+
; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs \
44
; RUN: < %s 2>&1 | FileCheck %s
55

66
@ilocal = internal global i32 0, align 4 #0
@@ -11,6 +11,8 @@ define dso_local i32 @read_i32_local_linkage() {
1111
ret i32 %0
1212
}
1313

14-
; CHECK: LLVM ERROR: A GlobalVariable with private or local linkage is not currently supported by the toc data transformation.
15-
1614
attributes #0 = { "toc-data" }
15+
16+
; CHECK: .toc
17+
; CHECK-NEXT: .csect ilocal[TD],2
18+
; CHECK-NEXT: .space 4
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs \
2+
; RUN: < %s 2>&1 | FileCheck %s
3+
; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs \
4+
; RUN: < %s 2>&1 | FileCheck %s
5+
6+
@iprivate = private global i32 55 #0
7+
8+
define nonnull ptr @get() local_unnamed_addr {
9+
entry:
10+
ret ptr @iprivate
11+
}
12+
13+
attributes #0 = { "toc-data" }
14+
15+
; CHECK: LLVM ERROR: A GlobalVariable with private linkage is not currently supported by the toc data transformation.
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s -DINSTR=lwz --check-prefix=CHECK
3+
; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s -DINSTR=ld --check-prefix=CHECK
4+
5+
; RUN: llc -filetype=obj -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s -o %t32.o
6+
; RUN: llvm-objdump -t --symbol-description %t32.o | FileCheck %s --check-prefix=OBJ32
7+
8+
; RUN: llc -filetype=obj -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s -o %t64.o
9+
; RUN: llvm-objdump -t --symbol-description %t64.o | FileCheck %s --check-prefix=OBJ64
10+
11+
@a1 = common global i32 0, align 4 #0
12+
@a2 = global i32 0, align 4 #0
13+
@a3 = common global i32 0, align 4
14+
@a4 = global i32 0, align 4
15+
16+
define void @set(i32 noundef %_a) {
17+
; CHECK-LABEL: set:
18+
; CHECK: # %bb.0: # %entry
19+
; CHECK-NEXT: la 4, a2[TD](2)
20+
; CHECK-NEXT: la 5, a1[TD](2)
21+
; CHECK-NEXT: stw 3, 0(4)
22+
; CHECK-NEXT: [[INSTR]] 4, L..C0(2) # @a4
23+
; CHECK-NEXT: stw 3, 0(5)
24+
; CHECK-NEXT: [[INSTR]] 5, L..C1(2) # @a3
25+
; CHECK-NEXT: stw 3, 0(4)
26+
; CHECK-NEXT: stw 3, 0(5)
27+
; CHECK-NEXT: blr
28+
entry:
29+
store i32 %_a, ptr @a2, align 4
30+
store i32 %_a, ptr @a1, align 4
31+
store i32 %_a, ptr @a4, align 4
32+
store i32 %_a, ptr @a3, align 4
33+
ret void
34+
}
35+
36+
define i32 @get1() {
37+
; CHECK-LABEL: get1:
38+
; CHECK: # %bb.0: # %entry
39+
; CHECK-NEXT: la 3, a2[TD](2)
40+
; CHECK-NEXT: lwz 3, 0(3)
41+
; CHECK-NEXT: blr
42+
entry:
43+
%0 = load i32, ptr @a2, align 4
44+
ret i32 %0
45+
}
46+
47+
define i32 @get2() {
48+
; CHECK-LABEL: get2:
49+
; CHECK: # %bb.0: # %entry
50+
; CHECK-NEXT: la 3, a1[TD](2)
51+
; CHECK-NEXT: lwz 3, 0(3)
52+
; CHECK-NEXT: blr
53+
entry:
54+
%0 = load i32, ptr @a1, align 4
55+
ret i32 %0
56+
}
57+
58+
define i32 @get3() {
59+
; CHECK-LABEL: get3:
60+
; CHECK: # %bb.0: # %entry
61+
; CHECK-NEXT: [[INSTR]] 3, L..C0(2) # @a4
62+
; CHECK-NEXT: lwz 3, 0(3)
63+
; CHECK-NEXT: blr
64+
entry:
65+
%0 = load i32, ptr @a4, align 4
66+
ret i32 %0
67+
}
68+
69+
define i32 @get4() {
70+
; CHECK-LABEL: get4:
71+
; CHECK: # %bb.0: # %entry
72+
; CHECK-NEXT: [[INSTR]] 3, L..C1(2) # @a3
73+
; CHECK-NEXT: lwz 3, 0(3)
74+
; CHECK-NEXT: blr
75+
entry:
76+
%0 = load i32, ptr @a3, align 4
77+
ret i32 %0
78+
}
79+
80+
define nonnull ptr @escape1() {
81+
; CHECK-LABEL: escape1:
82+
; CHECK: # %bb.0: # %entry
83+
; CHECK-NEXT: la 3, a2[TD](2)
84+
; CHECK-NEXT: blr
85+
entry:
86+
ret ptr @a2
87+
}
88+
89+
define nonnull ptr @escape2() {
90+
; CHECK-LABEL: escape2:
91+
; CHECK: # %bb.0: # %entry
92+
; CHECK-NEXT: la 3, a1[TD](2)
93+
; CHECK-NEXT: blr
94+
entry:
95+
ret ptr @a1
96+
}
97+
98+
define nonnull ptr @escape3() {
99+
; CHECK-LABEL: escape3:
100+
; CHECK: # %bb.0: # %entry
101+
; CHECK-NEXT: [[INSTR]] 3, L..C0(2) # @a4
102+
; CHECK-NEXT: blr
103+
entry:
104+
ret ptr @a4
105+
}
106+
107+
define nonnull ptr @escape4() {
108+
; CHECK-LABEL: escape4:
109+
; CHECK: # %bb.0: # %entry
110+
; CHECK-NEXT: [[INSTR]] 3, L..C1(2) # @a3
111+
; CHECK-NEXT: blr
112+
entry:
113+
ret ptr @a3
114+
}
115+
116+
attributes #0 = { "toc-data" }
117+
118+
; CHECK: .comm a3[RW],4,2 # @a3
119+
; CHECK-NEXT: .csect a4[RW],2
120+
; CHECK-NEXT: .globl a4[RW] # @a4
121+
; CHECK-NEXT: .align 2
122+
; CHECK-NEXT: .vbyte 4, 0 # 0x0
123+
; CHECK-NEXT: .toc
124+
; CHECK-LABEL: L..C0:
125+
; CHECK-NEXT: .tc a4[TC],a4[RW]
126+
; CHECK-LABEL: L..C1:
127+
; CHECK-NEXT: .tc a3[TC],a3[RW]
128+
; CHECK-NEXT: .csect a2[TD],2
129+
; CHECK-NEXT: .globl a2[TD] # @a2
130+
; CHECK-NEXT: .align 2
131+
; CHECK-NEXT: .vbyte 4, 0 # 0x0
132+
; CHECK-NEXT: .comm a1[TD],4,2 # @a1
133+
134+
; OBJ32: {{([[:xdigit:]]{8})}} g O .data 00000004 (idx: {{[0-9]+}}) a4[RW]
135+
; OBJ32-LABEL: {{([[:xdigit:]]{8})}} l .data 00000000 (idx: {{[0-9]+}}) TOC[TC0]
136+
; OBJ32-NEXT: {{([[:xdigit:]]{8})}} l O .data 00000004 (idx: {{[0-9]+}}) a4[TC]
137+
; OBJ32-NEXT: {{([[:xdigit:]]{8})}} l O .data 00000004 (idx: {{[0-9]+}}) a3[TC]
138+
; OBJ32-NEXT: {{([[:xdigit:]]{8})}} g O .data 00000004 (idx: {{[0-9]+}}) a2[TD]
139+
; OBJ32-NEXT: {{([[:xdigit:]]{8})}} g O *COM* 00000004 (idx: {{[0-9]+}}) a1[TD]
140+
; OBJ32-NEXT: {{([[:xdigit:]]{8})}} g O *COM* 00000004 (idx: {{[0-9]+}}) a3[RW]
141+
142+
; OBJ64: {{([[:xdigit:]]{16})}} g O .data 0000000000000004 (idx: {{[0-9]+}}) a4[RW]
143+
; OBJ64-LABEL: {{([[:xdigit:]]{16})}} l .data 0000000000000000 (idx: {{[0-9]+}}) TOC[TC0]
144+
; OBJ64-NEXT: {{([[:xdigit:]]{16})}} l O .data 0000000000000008 (idx: {{[0-9]+}}) a4[TC]
145+
; OBJ64-NEXT: {{([[:xdigit:]]{16})}} l O .data 0000000000000008 (idx: {{[0-9]+}}) a3[TC]
146+
; OBJ64-NEXT: {{([[:xdigit:]]{16})}} g O .data 0000000000000004 (idx: {{[0-9]+}}) a2[TD]
147+
; OBJ64-NEXT: {{([[:xdigit:]]{16})}} g O *COM* 0000000000000004 (idx: {{[0-9]+}}) a1[TD]
148+
; OBJ64-NEXT: {{([[:xdigit:]]{16})}} g O *COM* 0000000000000004 (idx: {{[0-9]+}}) a3[RW]

0 commit comments

Comments
 (0)