[llvm] 49dcd08 - [XCOFF] support the ref directive for object generation.
via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 23 02:11:24 PDT 2023
Author: esmeyi
Date: 2023-03-23T05:09:47-04:00
New Revision: 49dcd08c3d963e79d0710faf0e4024eb9b84bc8b
URL: https://github.com/llvm/llvm-project/commit/49dcd08c3d963e79d0710faf0e4024eb9b84bc8b
DIFF: https://github.com/llvm/llvm-project/commit/49dcd08c3d963e79d0710faf0e4024eb9b84bc8b.diff
LOG: [XCOFF] support the ref directive for object generation.
Summary: A R_REF relocation as a non-relocating reference is required to prevent garbage collection (by the binder) of the ref symbol in object generation.
Reviewed By: shchenz
Differential Revision: https://reviews.llvm.org/D144356
Added:
Modified:
llvm/include/llvm/MC/MCStreamer.h
llvm/include/llvm/MC/MCXCOFFStreamer.h
llvm/lib/MC/MCAsmStreamer.cpp
llvm/lib/MC/MCStreamer.cpp
llvm/lib/MC/MCXCOFFStreamer.cpp
llvm/lib/MC/XCOFFObjectWriter.cpp
llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
llvm/test/CodeGen/PowerPC/pgo-ref-directive.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
index aa39954d62868..f5891b24ae4b4 100644
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -645,7 +645,7 @@ class MCStreamer {
/// relocation table for one or more symbols.
///
/// \param Sym - The symbol on the .ref directive.
- virtual void emitXCOFFRefDirective(StringRef Sym);
+ virtual void emitXCOFFRefDirective(const MCSymbol *Symbol);
/// Emit an ELF .size directive.
///
diff --git a/llvm/include/llvm/MC/MCXCOFFStreamer.h b/llvm/include/llvm/MC/MCXCOFFStreamer.h
index a437faeccbff4..aea2a3265d572 100644
--- a/llvm/include/llvm/MC/MCXCOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCXCOFFStreamer.h
@@ -31,10 +31,7 @@ class MCXCOFFStreamer : public MCObjectStreamer {
void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
MCSymbolAttr Linkage,
MCSymbolAttr Visibility) override;
- void emitXCOFFRefDirective(StringRef Name) override {
- report_fatal_error("emitXCOFFRefDirective is not implemented yet on object"
- "generation path");
- }
+ void emitXCOFFRefDirective(const MCSymbol *Symbol) override;
void emitXCOFFRenameDirective(const MCSymbol *Name,
StringRef Rename) override {
report_fatal_error("emitXCOFFRenameDirective is not implemented yet on "
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 006f697b61875..fa1ab2717af2e 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -194,7 +194,7 @@ class MCAsmStreamer final : public MCStreamer {
void emitXCOFFRenameDirective(const MCSymbol *Name,
StringRef Rename) override;
- void emitXCOFFRefDirective(StringRef Name) override;
+ void emitXCOFFRefDirective(const MCSymbol *Symbol) override;
void emitXCOFFExceptDirective(const MCSymbol *Symbol,
const MCSymbol *Trap,
@@ -943,8 +943,9 @@ void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
EmitEOL();
}
-void MCAsmStreamer::emitXCOFFRefDirective(StringRef Name) {
- OS << "\t.ref " << Name;
+void MCAsmStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
+ OS << "\t.ref ";
+ Symbol->print(OS, MAI);
EmitEOL();
}
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index 517e258844156..4dd3163fd399d 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -1190,7 +1190,7 @@ void MCStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
"XCOFF targets");
}
-void MCStreamer::emitXCOFFRefDirective(StringRef Name) {
+void MCStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
llvm_unreachable("emitXCOFFRefDirective is only supported on XCOFF targets");
}
diff --git a/llvm/lib/MC/MCXCOFFStreamer.cpp b/llvm/lib/MC/MCXCOFFStreamer.cpp
index 25a678c68416e..d8ac07bc85b1b 100644
--- a/llvm/lib/MC/MCXCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCXCOFFStreamer.cpp
@@ -81,6 +81,21 @@ void MCXCOFFStreamer::emitXCOFFSymbolLinkageWithVisibility(
emitSymbolAttribute(Symbol, Visibility);
}
+void MCXCOFFStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
+ // Add a Fixup here to later record a relocation of type R_REF to prevent the
+ // ref symbol from being garbage collected (by the binder).
+ MCDataFragment *DF = getOrCreateDataFragment();
+ const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
+ std::optional<MCFixupKind> MaybeKind =
+ getAssembler().getBackend().getFixupKind("R_REF");
+ if (!MaybeKind)
+ report_fatal_error("failed to get fixup kind for R_REF relocation");
+
+ MCFixupKind Kind = *MaybeKind;
+ MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, Kind);
+ DF->getFixups().push_back(Fixup);
+}
+
void MCXCOFFStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,
const MCSymbol *Trap,
unsigned Lang, unsigned Reason,
diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp
index c79bdeb2cac4c..6452050d5941e 100644
--- a/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -663,7 +663,10 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
// instr address plus any constant value.
FixedValue =
SectionMap[SymASec]->Address - BRInstrAddress + Target.getConstant();
- }
+ } else if (Type == XCOFF::RelocationType::R_REF)
+ // The FixedValue should always be 0 since it specifies a nonrelocating
+ // reference.
+ FixedValue = 0;
assert((Fixup.getOffset() <=
MaxRawDataSize - Layout.getFragmentOffset(Fragment)) &&
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
index 227bd59ba3a64..a814bb1b4c07e 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
@@ -238,6 +238,8 @@ class XCOFFPPCAsmBackend : public PPCAsmBackend {
createObjectTargetWriter() const override {
return createPPCXCOFFObjectWriter(TT.isArch64Bit());
}
+
+ std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
};
} // end anonymous namespace
@@ -272,6 +274,13 @@ ELFPPCAsmBackend::getFixupKind(StringRef Name) const {
return std::nullopt;
}
+std::optional<MCFixupKind>
+XCOFFPPCAsmBackend::getFixupKind(StringRef Name) const {
+ return StringSwitch<std::optional<MCFixupKind>>(Name)
+ .Case("R_REF", (MCFixupKind)PPC::fixup_ppc_nofixup)
+ .Default(std::nullopt);
+}
+
MCAsmBackend *llvm::createPPCAsmBackend(const Target &T,
const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
index df0c666f5b113..9e8ee9f23107b 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
@@ -48,7 +48,8 @@ enum Fixups {
/// Not a true fixup, but ties a symbol to a call to __tls_get_addr for the
/// TLS general and local dynamic models, or inserts the thread-pointer
- /// register number.
+ /// register number. It can also be used to tie the ref symbol to prevent it
+ /// from being garbage collected on AIX.
fixup_ppc_nofixup,
/// A 16-bit fixup corresponding to lo16(_foo) with implied 3 zero bits for
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
index 729cb35cbebcf..b6e749b781804 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
@@ -90,6 +90,12 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
return {XCOFF::RelocationType::R_RBR, EncodedSignednessIndicator | 25};
case PPC::fixup_ppc_br24abs:
return {XCOFF::RelocationType::R_RBA, EncodedSignednessIndicator | 25};
+ case PPC::fixup_ppc_nofixup: {
+ if (Modifier == MCSymbolRefExpr::VK_None)
+ return {XCOFF::RelocationType::R_REF, 0};
+ else
+ llvm_unreachable("Unsupported Modifier");
+ } break;
case FK_Data_4:
case FK_Data_8:
const uint8_t SignAndSizeForFKData =
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 1ecaeabacf9f7..7c6fd3b85b1eb 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -2517,16 +2517,22 @@ void PPCAIXAsmPrinter::emitPGORefs() {
OutStreamer->switchSection(CntsSection);
if (OutContext.hasXCOFFSection(
"__llvm_prf_data",
- XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
- OutStreamer->emitXCOFFRefDirective("__llvm_prf_data[RW]");
+ XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {
+ MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_data[RW]");
+ OutStreamer->emitXCOFFRefDirective(S);
+ }
if (OutContext.hasXCOFFSection(
"__llvm_prf_names",
- XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD)))
- OutStreamer->emitXCOFFRefDirective("__llvm_prf_names[RO]");
+ XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD))) {
+ MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_names[RO]");
+ OutStreamer->emitXCOFFRefDirective(S);
+ }
if (OutContext.hasXCOFFSection(
"__llvm_prf_vnds",
- XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD)))
- OutStreamer->emitXCOFFRefDirective("__llvm_prf_vnds[RW]");
+ XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) {
+ MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_vnds[RW]");
+ OutStreamer->emitXCOFFRefDirective(S);
+ }
}
}
diff --git a/llvm/test/CodeGen/PowerPC/pgo-ref-directive.ll b/llvm/test/CodeGen/PowerPC/pgo-ref-directive.ll
index 172affa4a2661..201af2f949618 100644
--- a/llvm/test/CodeGen/PowerPC/pgo-ref-directive.ll
+++ b/llvm/test/CodeGen/PowerPC/pgo-ref-directive.ll
@@ -1,9 +1,22 @@
; RUN: rm -rf %t && split-file %s %t
-; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff -xcoff-traceback-table=false < %t/no-ref.ll | FileCheck %s --check-prefixes=NOREF
-; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff -xcoff-traceback-table=false < %t/no-vnds.ll | FileCheck %s --check-prefixes=NOVNDS
-; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff -xcoff-traceback-table=false < %t/with-vnds.ll | FileCheck %s --check-prefixes=WITHVNDS
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \
+; RUN: -xcoff-traceback-table=false < %t/no-ref.ll | FileCheck %s --check-prefixes=NOREF
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \
+; RUN: -xcoff-traceback-table=false --filetype=obj < %t/no-ref.ll -o %t/no-ref.o
+; RUN: llvm-objdump %t/no-ref.o -r | FileCheck %s --check-prefix=NOREF-OBJ
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \
+; RUN: -xcoff-traceback-table=false < %t/no-vnds.ll | FileCheck %s --check-prefixes=NOVNDS
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \
+; RUN: -xcoff-traceback-table=false --filetype=obj < %t/no-vnds.ll -o %t/no-vnds.o
+; RUN: llvm-objdump %t/no-vnds.o -r | FileCheck %s --check-prefix=NOVNDS-OBJ
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \
+; RUN: -xcoff-traceback-table=false < %t/with-vnds.ll | FileCheck %s --check-prefixes=WITHVNDS
+; RUN: llc -verify-machineinstrs -mcpu=pwr4 -mattr=-altivec -mtriple powerpc-ibm-aix-xcoff \
+; RUN: -xcoff-traceback-table=false --filetype=obj < %t/with-vnds.ll -o %t/with-vnds.o
+; RUN: llvm-objdump %t/with-vnds.o -tr | FileCheck %s --check-prefix=WITHVNDS-OBJ
;--- no-ref.ll
; The absence of a __llvm_prf_cnts section should stop generating the .refs.
@@ -27,6 +40,10 @@ entry:
; NOREF-NOT: .ref __llvm_prf_names
; NOREF-NOT: .ref __llvm_prf_vnds
+; NOREF-OBJ-NOT: R_REF __llvm_prf_data
+; NOREF-OBJ-NOT: R_REF __llvm_prf_names
+; NOREF-OBJ-NOT: R_REF __llvm_prf_vnds
+
;--- no-vnds.ll
; This is the most common case. When -fprofile-generate is used and there exists executable code, we generate the __llvm_prf_cnts, __llvm_prf_data, and __llvm_prf_names sections.
;
@@ -56,6 +73,10 @@ entry:
; NOVNDS-NEXT: .ref __llvm_prf_names[RO]
; NOVNDS-NOT: .ref __llvm_prf_vnds
+; NOVNDS-OBJ: 00000008 R_REF __llvm_prf_data
+; NOVNDS-OBJ: 00000008 R_REF __llvm_prf_names
+; NOVNDS-OBJ-NOT: R_REF __llvm_prf_vnds
+
;--- with-vnds.ll
; When value profiling is needed, the PGO instrumentation generates variables in the __llvm_prf_vnds section, so we generate a .ref for them too.
;
@@ -80,3 +101,22 @@ entry:
; WITHVNDS-NEXT: .ref __llvm_prf_data[RW]
; WITHVNDS-NEXT: .ref __llvm_prf_names[RO]
; WITHVNDS-NEXT: .ref __llvm_prf_vnds[RW]
+
+; WITHVNDS-OBJ: SYMBOL TABLE:
+; WITHVNDS-OBJ-NEXT: 00000000 df *DEBUG* 00000000 <stdin>
+; WITHVNDS-OBJ-NEXT: 00000000 l .text 00000008 .text
+; WITHVNDS-OBJ-NEXT: 00000000 g F .text (csect: .text) 00000000 .main
+; WITHVNDS-OBJ-NEXT: 00000008 l .text 00000006 __llvm_prf_names
+; WITHVNDS-OBJ-NEXT: 00000010 l O .data 00000008 __llvm_prf_cnts
+; WITHVNDS-OBJ-NEXT: 00000018 l O .data 00000008 __llvm_prf_data
+; WITHVNDS-OBJ-NEXT: 00000020 l O .data 000000f0 __llvm_prf_vnds
+; WITHVNDS-OBJ-NEXT: 00000110 g O .data 0000000c main
+; WITHVNDS-OBJ-NEXT: 0000011c l .data 00000000 TOC
+
+; WITHVNDS-OBJ: RELOCATION RECORDS FOR [.data]:
+; WITHVNDS-OBJ-NEXT: OFFSET TYPE VALUE
+; WITHVNDS-OBJ-NEXT: 00000008 R_REF __llvm_prf_data
+; WITHVNDS-OBJ-NEXT: 00000008 R_REF __llvm_prf_names
+; WITHVNDS-OBJ-NEXT: 00000008 R_REF __llvm_prf_vnds
+; WITHVNDS-OBJ-NEXT: 00000100 R_POS .main
+; WITHVNDS-OBJ-NEXT: 00000104 R_POS TOC
More information about the llvm-commits
mailing list