[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