-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[AIX][XCOFF] rename metadata #159435
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[AIX][XCOFF] rename metadata #159435
Conversation
Adds a metadata node that represents a special case of the XCOFF rename directive. The node must be placed on a variable that has an explict section attribute, and the global with the node will be emitted to a csect with a unique name, which is later renamed to the section attributes name. This is used in pgo when function sections is enabled, becuase otherwise the pgo instrumentation breaks garbage collection which many builds on AIX rely on. Other features which emit data which is meant to be globed together into a contiguous output sections, but may also contain references to other data that pollutes the symbol reference graph inhibiting garbage collection will also find this feature useful.
@llvm/pr-subscribers-llvm-ir Author: Sean Fertile (mandlebug) ChangesAdds a metadata node that represents a special case of the XCOFF rename directive. The node must be placed on a variable that has an explict section attribute, and the global with the node will be emitted to a csect with a unique name, which is later renamed to the section attributes name. This is used in pgo when function sections is enabled, because otherwise the pgo instrumentation breaks garbage collection which many builds on AIX rely on. Other features which emit data which is meant to be globed together into a contiguous output sections, but may also contain references to other data that pollutes the symbol reference graph inhibiting garbage collection will also find this feature useful. Full diff: https://github.com/llvm/llvm-project/pull/159435.diff 9 Files Affected:
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index d61ea07830123..03ba7a1e6b956 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -8441,6 +8441,29 @@ The ``nofree`` metadata indicates the memory pointed by the pointer will not be
freed after the attached instruction.
+'``rename.key``' Metadata
+^^^^^^^^^^^^^^^^^^^^^^^^^
+The rename key may be attached to a global variable definition that has an
+explicit section attribute. It is used as a flag so the associated node
+must be empty. It only takes effect when function sections is enabled, and
+only on XCOFF targets. The metadata will casue the global to be emitted to a
+control section (CSECT) with a name that is an amalgamation of both the section
+attribute and the global variables identifier. After the control section is
+defined it will be renamed to match the name of the section attribute. This
+allows the linker to aggressively garbage collect the symbol if unreferenced,
+while directing the linker to merge any control sections with the same name
+that remain after garbage collecting into the same CSECT in the output binary.
+Commonly used where there is a feature that uses a runtime to walk over a
+section using the linker-defined encapsulation symbols
+``__start_<section_name>`` and ``__stop_<section_name>``.
+
+Example:
+
+.. code-block:: llvm
+
+ @a = global i32 1, section "abc", !rename.key !0
+ !0 = !{}
+
Module Flags Metadata
=====================
diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def
index d09cc15d65ff6..f4b7ebfcf14d5 100644
--- a/llvm/include/llvm/IR/FixedMetadataKinds.def
+++ b/llvm/include/llvm/IR/FixedMetadataKinds.def
@@ -55,3 +55,4 @@ LLVM_FIXED_MD_KIND(MD_mmra, "mmra", 40)
LLVM_FIXED_MD_KIND(MD_noalias_addrspace, "noalias.addrspace", 41)
LLVM_FIXED_MD_KIND(MD_callee_type, "callee_type", 42)
LLVM_FIXED_MD_KIND(MD_nofree, "nofree", 43)
+LLVM_FIXED_MD_KIND(MD_rename_key, "rename.key", 44)
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index ae681b9aebdfb..759b6a8e349cc 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2431,16 +2431,24 @@ MCSection *TargetLoweringObjectFileXCOFF::getExplicitSectionGlobal(
if (!GO->hasSection())
report_fatal_error("#pragma clang section is not yet supported");
- StringRef SectionName = GO->getSection();
+ std::string SectionName(GO->getSection());
- // Handle the XCOFF::TD case first, then deal with the rest.
- if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO))
+ // Have to check for either attributes or metadata that can affect the
+ // section type or section name.
+ if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO)) {
if (GVar->hasAttribute("toc-data"))
return getContext().getXCOFFSection(
SectionName, Kind,
XCOFF::CsectProperties(/*MappingClass*/ XCOFF::XMC_TD, XCOFF::XTY_SD),
/* MultiSymbolsAllowed*/ true);
+ if (TM.getFunctionSections() &&
+ GVar->hasMetadata(LLVMContext::MD_rename_key)) {
+ SectionName += ".";
+ SectionName += GO->getName();
+ }
+ }
+
XCOFF::StorageMappingClass MappingClass;
if (Kind.isText())
MappingClass = XCOFF::XMC_PR;
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index c06b60fd2d9a9..1d11e3f4e3aae 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -766,6 +766,15 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {
DL.getIntPtrType(GO->getType()),
RangeLikeMetadataKind::AbsoluteSymbol);
}
+
+ if (GO->hasMetadata(LLVMContext::MD_rename_key)) {
+ SmallVector<MDNode *, 1> MDs;
+ GO->getMetadata(LLVMContext::MD_rename_key, MDs);
+ Check(MDs.size() == 1,
+ "global value cannot have more then 1 rename metadata", GO);
+ Check(MDs[0]->getNumOperands() == 0,
+ "rename metadata must have no operands", GO);
+ }
}
Check(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 023fd147535ec..962cf518614c8 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -2970,58 +2970,80 @@ void PPCAIXAsmPrinter::emitGCOVRefs() {
}
void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
- // If there are no functions and there are no toc-data definitions in this
- // module, we will never need to reference the TOC base.
- if (M.empty() && TOCDataGlobalVars.empty())
- return;
emitPGORefs(M);
emitGCOVRefs();
- // Switch to section to emit TOC base.
- OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
+ // If there are no functions and there are no toc-data definitions in this
+ // module, we will never need to reference the TOC base.
+ if (!M.empty() || !TOCDataGlobalVars.empty()) {
+ // Switch to section to emit TOC base.
+ OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
- PPCTargetStreamer *TS =
- static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
+ PPCTargetStreamer *TS =
+ static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
+
+ for (auto &I : TOC) {
+ MCSectionXCOFF *TCEntry;
+ // Setup the csect for the current TC entry. If the variant kind is
+ // VK_AIX_TLSGDM the entry represents the region handle, we create a
+ // new symbol to prefix the name with a dot.
+ // If TLS model opt is turned on, create a new symbol to prefix the name
+ // with a dot.
+ if (I.first.second == PPC::S_AIX_TLSGDM ||
+ (Subtarget->hasAIXShLibTLSModelOpt() &&
+ I.first.second == PPC::S_AIX_TLSLD)) {
+ SmallString<128> Name;
+ StringRef Prefix = ".";
+ Name += Prefix;
+ Name += static_cast<const MCSymbolXCOFF *>(I.first.first)
+ ->getSymbolTableName();
+ MCSymbol *S = OutContext.getOrCreateSymbol(Name);
+ TCEntry = static_cast<MCSectionXCOFF *>(
+ getObjFileLowering().getSectionForTOCEntry(S, TM));
+ } else {
+ TCEntry = static_cast<MCSectionXCOFF *>(
+ getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
+ }
+ OutStreamer->switchSection(TCEntry);
- for (auto &I : TOC) {
- MCSectionXCOFF *TCEntry;
- // Setup the csect for the current TC entry. If the variant kind is
- // VK_AIX_TLSGDM the entry represents the region handle, we create a
- // new symbol to prefix the name with a dot.
- // If TLS model opt is turned on, create a new symbol to prefix the name
- // with a dot.
- if (I.first.second == PPC::S_AIX_TLSGDM ||
- (Subtarget->hasAIXShLibTLSModelOpt() &&
- I.first.second == PPC::S_AIX_TLSLD)) {
- SmallString<128> Name;
- StringRef Prefix = ".";
- Name += Prefix;
- Name += static_cast<const MCSymbolXCOFF *>(I.first.first)
- ->getSymbolTableName();
- MCSymbol *S = OutContext.getOrCreateSymbol(Name);
- TCEntry = static_cast<MCSectionXCOFF *>(
- getObjFileLowering().getSectionForTOCEntry(S, TM));
- } else {
- TCEntry = static_cast<MCSectionXCOFF *>(
- getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
+ OutStreamer->emitLabel(I.second);
+ TS->emitTCEntry(*I.first.first, I.first.second);
}
- OutStreamer->switchSection(TCEntry);
- OutStreamer->emitLabel(I.second);
- TS->emitTCEntry(*I.first.first, I.first.second);
+ // 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);
+ }
}
- // 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);
+ // Renames only take effect when function sections is enabled.
+ if (!TM.getFunctionSections())
+ return;
+
+ for (const GlobalVariable &GV : M.globals()) {
+ if (GV.hasMetadata(LLVMContext::MD_rename_key)) {
+ // Get orginal csect.
+ SectionKind GVKind = getObjFileLowering().getKindForGlobal(&GV, TM);
+ auto *CSect = static_cast<MCSectionXCOFF *>(
+ getObjFileLowering().SectionForGlobal(&GV, GVKind, TM));
+
+ // Get the section to rename to.
+ if (!GV.hasSection())
+ reportFatalInternalError(
+ "rename.key metadata used without a section attribute");
+
+ StringRef SectionName = GV.getSection();
+ OutStreamer->emitXCOFFRenameDirective(CSect->getQualNameSymbol(),
+ SectionName);
+ }
}
}
diff --git a/llvm/test/CodeGen/PowerPC/aix-rename.ll b/llvm/test/CodeGen/PowerPC/aix-rename.ll
new file mode 100644
index 0000000000000..3fe379b8cd33b
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-rename.ll
@@ -0,0 +1,38 @@
+; RUN: llc --function-sections -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck --check-prefix=NOFUNCSECT %s
+
+@a = global i32 1, section "abcd", !rename.key !0
+@b = global i32 2, section "abcd", !rename.key !0
+@c = global i32 3, section "abcd", !rename.key !0
+@d = global i32 4, section "abcd", !rename.key !0
+
+!0 = !{}
+
+;CHECK: .csect abcd.a[RW]
+;CHECK: .globl a
+
+;CHECK: .csect abcd.b[RW]
+;CHECK: .globl b
+
+;CHECK: .csect abcd.c[RW]
+;CHECK: .globl c
+
+;CHECK: .csect abcd.d[RW]
+;CHECK: .globl d
+
+;CHECK: .rename abcd.a[RW],"abcd"
+;CHECK: .rename abcd.b[RW],"abcd"
+;CHECK: .rename abcd.c[RW],"abcd"
+;CHECK: .rename abcd.d[RW],"abcd"
+
+;NOFUNCSECT: .csect abcd[RW],2
+;NOFUNCSECT-NOT: .csect
+;NOFUNCSECT: .globl a
+;NOFUNCSECT-NOT: .csect
+;NOFUNCSECT: .globl b
+;NOFUNCSECT-NOT: .csect
+;NOFUNCSECT: .globl c
+;NOFUNCSECT-NOT: .csect
+;NOFUNCSECT: .globl d
+
+;NOFUNCSECT-NOT: .rename
diff --git a/llvm/test/Verifier/PowerPC/lit.local.cfg b/llvm/test/Verifier/PowerPC/lit.local.cfg
new file mode 100644
index 0000000000000..bb982488eb15e
--- /dev/null
+++ b/llvm/test/Verifier/PowerPC/lit.local.cfg
@@ -0,0 +1,2 @@
+if not "PowerPC" in config.root.targets:
+ config.unsupported = True
diff --git a/llvm/test/Verifier/PowerPC/multiple_rename.ll b/llvm/test/Verifier/PowerPC/multiple_rename.ll
new file mode 100644
index 0000000000000..16b03dc34be7e
--- /dev/null
+++ b/llvm/test/Verifier/PowerPC/multiple_rename.ll
@@ -0,0 +1,8 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+@a = global i32 1, section "abc", !rename.key !0, !rename.key !1
+
+!0 = !{}
+!1 = !{}
+
+; CHECK: global value cannot have more then 1 rename metadata
diff --git a/llvm/test/Verifier/PowerPC/rename_operands.ll b/llvm/test/Verifier/PowerPC/rename_operands.ll
new file mode 100644
index 0000000000000..a76575bc5293e
--- /dev/null
+++ b/llvm/test/Verifier/PowerPC/rename_operands.ll
@@ -0,0 +1,6 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+@a = global i32 1, section "abc", !rename.key !0
+
+!0 = !{!"Hello World!"}
+; CHECK: rename metadata must have no operands
|
@llvm/pr-subscribers-backend-powerpc Author: Sean Fertile (mandlebug) ChangesAdds a metadata node that represents a special case of the XCOFF rename directive. The node must be placed on a variable that has an explict section attribute, and the global with the node will be emitted to a csect with a unique name, which is later renamed to the section attributes name. This is used in pgo when function sections is enabled, because otherwise the pgo instrumentation breaks garbage collection which many builds on AIX rely on. Other features which emit data which is meant to be globed together into a contiguous output sections, but may also contain references to other data that pollutes the symbol reference graph inhibiting garbage collection will also find this feature useful. Full diff: https://github.com/llvm/llvm-project/pull/159435.diff 9 Files Affected:
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index d61ea07830123..03ba7a1e6b956 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -8441,6 +8441,29 @@ The ``nofree`` metadata indicates the memory pointed by the pointer will not be
freed after the attached instruction.
+'``rename.key``' Metadata
+^^^^^^^^^^^^^^^^^^^^^^^^^
+The rename key may be attached to a global variable definition that has an
+explicit section attribute. It is used as a flag so the associated node
+must be empty. It only takes effect when function sections is enabled, and
+only on XCOFF targets. The metadata will casue the global to be emitted to a
+control section (CSECT) with a name that is an amalgamation of both the section
+attribute and the global variables identifier. After the control section is
+defined it will be renamed to match the name of the section attribute. This
+allows the linker to aggressively garbage collect the symbol if unreferenced,
+while directing the linker to merge any control sections with the same name
+that remain after garbage collecting into the same CSECT in the output binary.
+Commonly used where there is a feature that uses a runtime to walk over a
+section using the linker-defined encapsulation symbols
+``__start_<section_name>`` and ``__stop_<section_name>``.
+
+Example:
+
+.. code-block:: llvm
+
+ @a = global i32 1, section "abc", !rename.key !0
+ !0 = !{}
+
Module Flags Metadata
=====================
diff --git a/llvm/include/llvm/IR/FixedMetadataKinds.def b/llvm/include/llvm/IR/FixedMetadataKinds.def
index d09cc15d65ff6..f4b7ebfcf14d5 100644
--- a/llvm/include/llvm/IR/FixedMetadataKinds.def
+++ b/llvm/include/llvm/IR/FixedMetadataKinds.def
@@ -55,3 +55,4 @@ LLVM_FIXED_MD_KIND(MD_mmra, "mmra", 40)
LLVM_FIXED_MD_KIND(MD_noalias_addrspace, "noalias.addrspace", 41)
LLVM_FIXED_MD_KIND(MD_callee_type, "callee_type", 42)
LLVM_FIXED_MD_KIND(MD_nofree, "nofree", 43)
+LLVM_FIXED_MD_KIND(MD_rename_key, "rename.key", 44)
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index ae681b9aebdfb..759b6a8e349cc 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2431,16 +2431,24 @@ MCSection *TargetLoweringObjectFileXCOFF::getExplicitSectionGlobal(
if (!GO->hasSection())
report_fatal_error("#pragma clang section is not yet supported");
- StringRef SectionName = GO->getSection();
+ std::string SectionName(GO->getSection());
- // Handle the XCOFF::TD case first, then deal with the rest.
- if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO))
+ // Have to check for either attributes or metadata that can affect the
+ // section type or section name.
+ if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GO)) {
if (GVar->hasAttribute("toc-data"))
return getContext().getXCOFFSection(
SectionName, Kind,
XCOFF::CsectProperties(/*MappingClass*/ XCOFF::XMC_TD, XCOFF::XTY_SD),
/* MultiSymbolsAllowed*/ true);
+ if (TM.getFunctionSections() &&
+ GVar->hasMetadata(LLVMContext::MD_rename_key)) {
+ SectionName += ".";
+ SectionName += GO->getName();
+ }
+ }
+
XCOFF::StorageMappingClass MappingClass;
if (Kind.isText())
MappingClass = XCOFF::XMC_PR;
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index c06b60fd2d9a9..1d11e3f4e3aae 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -766,6 +766,15 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {
DL.getIntPtrType(GO->getType()),
RangeLikeMetadataKind::AbsoluteSymbol);
}
+
+ if (GO->hasMetadata(LLVMContext::MD_rename_key)) {
+ SmallVector<MDNode *, 1> MDs;
+ GO->getMetadata(LLVMContext::MD_rename_key, MDs);
+ Check(MDs.size() == 1,
+ "global value cannot have more then 1 rename metadata", GO);
+ Check(MDs[0]->getNumOperands() == 0,
+ "rename metadata must have no operands", GO);
+ }
}
Check(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 023fd147535ec..962cf518614c8 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -2970,58 +2970,80 @@ void PPCAIXAsmPrinter::emitGCOVRefs() {
}
void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
- // If there are no functions and there are no toc-data definitions in this
- // module, we will never need to reference the TOC base.
- if (M.empty() && TOCDataGlobalVars.empty())
- return;
emitPGORefs(M);
emitGCOVRefs();
- // Switch to section to emit TOC base.
- OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
+ // If there are no functions and there are no toc-data definitions in this
+ // module, we will never need to reference the TOC base.
+ if (!M.empty() || !TOCDataGlobalVars.empty()) {
+ // Switch to section to emit TOC base.
+ OutStreamer->switchSection(getObjFileLowering().getTOCBaseSection());
- PPCTargetStreamer *TS =
- static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
+ PPCTargetStreamer *TS =
+ static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer());
+
+ for (auto &I : TOC) {
+ MCSectionXCOFF *TCEntry;
+ // Setup the csect for the current TC entry. If the variant kind is
+ // VK_AIX_TLSGDM the entry represents the region handle, we create a
+ // new symbol to prefix the name with a dot.
+ // If TLS model opt is turned on, create a new symbol to prefix the name
+ // with a dot.
+ if (I.first.second == PPC::S_AIX_TLSGDM ||
+ (Subtarget->hasAIXShLibTLSModelOpt() &&
+ I.first.second == PPC::S_AIX_TLSLD)) {
+ SmallString<128> Name;
+ StringRef Prefix = ".";
+ Name += Prefix;
+ Name += static_cast<const MCSymbolXCOFF *>(I.first.first)
+ ->getSymbolTableName();
+ MCSymbol *S = OutContext.getOrCreateSymbol(Name);
+ TCEntry = static_cast<MCSectionXCOFF *>(
+ getObjFileLowering().getSectionForTOCEntry(S, TM));
+ } else {
+ TCEntry = static_cast<MCSectionXCOFF *>(
+ getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
+ }
+ OutStreamer->switchSection(TCEntry);
- for (auto &I : TOC) {
- MCSectionXCOFF *TCEntry;
- // Setup the csect for the current TC entry. If the variant kind is
- // VK_AIX_TLSGDM the entry represents the region handle, we create a
- // new symbol to prefix the name with a dot.
- // If TLS model opt is turned on, create a new symbol to prefix the name
- // with a dot.
- if (I.first.second == PPC::S_AIX_TLSGDM ||
- (Subtarget->hasAIXShLibTLSModelOpt() &&
- I.first.second == PPC::S_AIX_TLSLD)) {
- SmallString<128> Name;
- StringRef Prefix = ".";
- Name += Prefix;
- Name += static_cast<const MCSymbolXCOFF *>(I.first.first)
- ->getSymbolTableName();
- MCSymbol *S = OutContext.getOrCreateSymbol(Name);
- TCEntry = static_cast<MCSectionXCOFF *>(
- getObjFileLowering().getSectionForTOCEntry(S, TM));
- } else {
- TCEntry = static_cast<MCSectionXCOFF *>(
- getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
+ OutStreamer->emitLabel(I.second);
+ TS->emitTCEntry(*I.first.first, I.first.second);
}
- OutStreamer->switchSection(TCEntry);
- OutStreamer->emitLabel(I.second);
- TS->emitTCEntry(*I.first.first, I.first.second);
+ // 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);
+ }
}
- // 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);
+ // Renames only take effect when function sections is enabled.
+ if (!TM.getFunctionSections())
+ return;
+
+ for (const GlobalVariable &GV : M.globals()) {
+ if (GV.hasMetadata(LLVMContext::MD_rename_key)) {
+ // Get orginal csect.
+ SectionKind GVKind = getObjFileLowering().getKindForGlobal(&GV, TM);
+ auto *CSect = static_cast<MCSectionXCOFF *>(
+ getObjFileLowering().SectionForGlobal(&GV, GVKind, TM));
+
+ // Get the section to rename to.
+ if (!GV.hasSection())
+ reportFatalInternalError(
+ "rename.key metadata used without a section attribute");
+
+ StringRef SectionName = GV.getSection();
+ OutStreamer->emitXCOFFRenameDirective(CSect->getQualNameSymbol(),
+ SectionName);
+ }
}
}
diff --git a/llvm/test/CodeGen/PowerPC/aix-rename.ll b/llvm/test/CodeGen/PowerPC/aix-rename.ll
new file mode 100644
index 0000000000000..3fe379b8cd33b
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-rename.ll
@@ -0,0 +1,38 @@
+; RUN: llc --function-sections -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck --check-prefix=NOFUNCSECT %s
+
+@a = global i32 1, section "abcd", !rename.key !0
+@b = global i32 2, section "abcd", !rename.key !0
+@c = global i32 3, section "abcd", !rename.key !0
+@d = global i32 4, section "abcd", !rename.key !0
+
+!0 = !{}
+
+;CHECK: .csect abcd.a[RW]
+;CHECK: .globl a
+
+;CHECK: .csect abcd.b[RW]
+;CHECK: .globl b
+
+;CHECK: .csect abcd.c[RW]
+;CHECK: .globl c
+
+;CHECK: .csect abcd.d[RW]
+;CHECK: .globl d
+
+;CHECK: .rename abcd.a[RW],"abcd"
+;CHECK: .rename abcd.b[RW],"abcd"
+;CHECK: .rename abcd.c[RW],"abcd"
+;CHECK: .rename abcd.d[RW],"abcd"
+
+;NOFUNCSECT: .csect abcd[RW],2
+;NOFUNCSECT-NOT: .csect
+;NOFUNCSECT: .globl a
+;NOFUNCSECT-NOT: .csect
+;NOFUNCSECT: .globl b
+;NOFUNCSECT-NOT: .csect
+;NOFUNCSECT: .globl c
+;NOFUNCSECT-NOT: .csect
+;NOFUNCSECT: .globl d
+
+;NOFUNCSECT-NOT: .rename
diff --git a/llvm/test/Verifier/PowerPC/lit.local.cfg b/llvm/test/Verifier/PowerPC/lit.local.cfg
new file mode 100644
index 0000000000000..bb982488eb15e
--- /dev/null
+++ b/llvm/test/Verifier/PowerPC/lit.local.cfg
@@ -0,0 +1,2 @@
+if not "PowerPC" in config.root.targets:
+ config.unsupported = True
diff --git a/llvm/test/Verifier/PowerPC/multiple_rename.ll b/llvm/test/Verifier/PowerPC/multiple_rename.ll
new file mode 100644
index 0000000000000..16b03dc34be7e
--- /dev/null
+++ b/llvm/test/Verifier/PowerPC/multiple_rename.ll
@@ -0,0 +1,8 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+@a = global i32 1, section "abc", !rename.key !0, !rename.key !1
+
+!0 = !{}
+!1 = !{}
+
+; CHECK: global value cannot have more then 1 rename metadata
diff --git a/llvm/test/Verifier/PowerPC/rename_operands.ll b/llvm/test/Verifier/PowerPC/rename_operands.ll
new file mode 100644
index 0000000000000..a76575bc5293e
--- /dev/null
+++ b/llvm/test/Verifier/PowerPC/rename_operands.ll
@@ -0,0 +1,6 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+@a = global i32 1, section "abc", !rename.key !0
+
+!0 = !{!"Hello World!"}
+; CHECK: rename metadata must have no operands
|
llvm/docs/LangRef.rst
Outdated
The rename key may be attached to a global variable definition that has an | ||
explicit section attribute. It is used as a flag so the associated node | ||
must be empty. It only takes effect when function sections is enabled, and | ||
only on XCOFF targets. The metadata will casue the global to be emitted to a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: cause
✅ With the latest revision this PR passed the C/C++ code formatter. |
I was reading about COMDAT in llvm, and it mentions an example of mixing comdat with explicit sections:
and says
So that led me to wonder: |
Adds a metadata node that represents a special case of the XCOFF rename directive. The node must be placed on a variable that has an explict section attribute, and the global with the node will be emitted to a csect with a unique name, which is later renamed to the section attributes name. This is used in pgo when function sections is enabled, because otherwise the pgo instrumentation breaks garbage collection which many builds on AIX rely on. Other features which emit data which is meant to be globed together into a contiguous output sections, but may also contain references to other data that pollutes the symbol reference graph inhibiting garbage collection will also find this feature useful.