[llvm] [GOFF] Emit symbols for functions. (PR #144437)

Kai Nacke via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 28 08:50:48 PDT 2025


https://github.com/redstar updated https://github.com/llvm/llvm-project/pull/144437

>From a80ae0f07fbe76b9d169d9a1c695f464bcce2e3e Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Mon, 16 Jun 2025 17:27:16 -0400
Subject: [PATCH 1/2] [GOFF] Emit symbols for functions.

A function entry is mapped to a LD symbol with an offset to the begin of the section.
---
 llvm/include/llvm/MC/MCGOFFStreamer.h      |  7 +--
 llvm/include/llvm/MC/MCSymbolGOFF.h        | 19 ++++++-
 llvm/lib/MC/CMakeLists.txt                 |  1 +
 llvm/lib/MC/GOFFObjectWriter.cpp           |  1 +
 llvm/lib/MC/MCGOFFStreamer.cpp             | 58 ++++++++++++++++++++++
 llvm/lib/MC/MCSymbolGOFF.cpp               | 40 +++++++++++++++
 llvm/test/CodeGen/SystemZ/zos-section-1.ll | 34 ++++++++-----
 7 files changed, 142 insertions(+), 18 deletions(-)
 create mode 100644 llvm/lib/MC/MCSymbolGOFF.cpp

diff --git a/llvm/include/llvm/MC/MCGOFFStreamer.h b/llvm/include/llvm/MC/MCGOFFStreamer.h
index 6d029f6bd4a29..171924f9b3470 100644
--- a/llvm/include/llvm/MC/MCGOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCGOFFStreamer.h
@@ -30,9 +30,10 @@ class MCGOFFStreamer : public MCObjectStreamer {
 
   GOFFObjectWriter &getWriter();
 
-  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
-    return false;
-  }
+  void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
+
+  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
+
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                         Align ByteAlignment) override {}
 };
diff --git a/llvm/include/llvm/MC/MCSymbolGOFF.h b/llvm/include/llvm/MC/MCSymbolGOFF.h
index d8c570d2de240..7612a06e7d738 100644
--- a/llvm/include/llvm/MC/MCSymbolGOFF.h
+++ b/llvm/include/llvm/MC/MCSymbolGOFF.h
@@ -28,7 +28,10 @@ class MCSymbolGOFF : public MCSymbol {
   GOFF::LDAttr LDAttributes;
 
   enum SymbolFlags : uint16_t {
-    SF_LD = 0x01, // LD attributes are set.
+    SF_LD = 0x01,     // LD attributes are set.
+                      // Leave place for EX attributes.
+    SF_Hidden = 0x04, // Symbol is hidden, aka not exported.
+    SF_Weak = 0x08,   // Symbol is weak.
   };
 
 public:
@@ -39,7 +42,8 @@ class MCSymbolGOFF : public MCSymbol {
     modifyFlags(SF_LD, SF_LD);
     LDAttributes = Attr;
   }
-  GOFF::LDAttr getLDAttributes() const { return LDAttributes; }
+  const GOFF::LDAttr &getLDAttributes() const { return LDAttributes; }
+  GOFF::LDAttr &getLDAttributes() { return LDAttributes; }
   bool hasLDAttributes() const { return getFlags() & SF_LD; }
 
   void setADA(MCSectionGOFF *AssociatedDataArea) {
@@ -48,6 +52,17 @@ class MCSymbolGOFF : public MCSymbol {
   }
   MCSectionGOFF *getADA() const { return ADA; }
 
+  void setHidden(bool Value = true) {
+    modifyFlags(Value ? SF_Hidden : 0, SF_Hidden);
+  }
+  bool isHidden() const { return getFlags() & SF_Hidden; }
+  bool isExported() const { return !isHidden(); }
+
+  void setWeak(bool Value = true) { modifyFlags(Value ? SF_Weak : 0, SF_Weak); }
+  bool isWeak() const { return getFlags() & SF_Weak; }
+
+  void initAttributes();
+
   static bool classof(const MCSymbol *S) { return S->isGOFF(); }
 };
 } // end namespace llvm
diff --git a/llvm/lib/MC/CMakeLists.txt b/llvm/lib/MC/CMakeLists.txt
index d662c42c522fc..85e857d3fb406 100644
--- a/llvm/lib/MC/CMakeLists.txt
+++ b/llvm/lib/MC/CMakeLists.txt
@@ -55,6 +55,7 @@ add_llvm_component_library(LLVMMC
   MCSubtargetInfo.cpp
   MCSymbol.cpp
   MCSymbolELF.cpp
+  MCSymbolGOFF.cpp
   MCSymbolXCOFF.cpp
   MCTargetOptions.cpp
   MCTargetOptionsCommandFlags.cpp
diff --git a/llvm/lib/MC/GOFFObjectWriter.cpp b/llvm/lib/MC/GOFFObjectWriter.cpp
index 1871f5fe507e2..1e9d6c72ea0e1 100644
--- a/llvm/lib/MC/GOFFObjectWriter.cpp
+++ b/llvm/lib/MC/GOFFObjectWriter.cpp
@@ -329,6 +329,7 @@ void GOFFWriter::defineLabel(const MCSymbolGOFF &Symbol) {
                 Section.getEDAttributes().NameSpace, Symbol.getLDAttributes());
   if (Symbol.getADA())
     LD.ADAEsdId = Symbol.getADA()->getOrdinal();
+  LD.Offset = Asm.getSymbolOffset(Symbol);
   writeSymbol(LD);
 }
 
diff --git a/llvm/lib/MC/MCGOFFStreamer.cpp b/llvm/lib/MC/MCGOFFStreamer.cpp
index b7021915e7b70..451acf3b5d781 100644
--- a/llvm/lib/MC/MCGOFFStreamer.cpp
+++ b/llvm/lib/MC/MCGOFFStreamer.cpp
@@ -15,8 +15,11 @@
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCCodeEmitter.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCGOFFObjectWriter.h"
+#include "llvm/MC/MCSymbolGOFF.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Casting.h"
 
 using namespace llvm;
 
@@ -41,6 +44,61 @@ void MCGOFFStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
   MCObjectStreamer::changeSection(Section, Subsection);
 }
 
+void MCGOFFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
+  MCObjectStreamer::emitLabel(Symbol, Loc);
+  cast<MCSymbolGOFF>(Symbol)->initAttributes();
+}
+
+bool MCGOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
+                                         MCSymbolAttr Attribute) {
+  auto *Symbol = cast<MCSymbolGOFF>(Sym);
+  switch (Attribute) {
+  case MCSA_Invalid:
+  case MCSA_Cold:
+  case MCSA_ELF_TypeFunction:
+  case MCSA_ELF_TypeIndFunction:
+  case MCSA_ELF_TypeObject:
+  case MCSA_ELF_TypeTLS:
+  case MCSA_ELF_TypeCommon:
+  case MCSA_ELF_TypeNoType:
+  case MCSA_ELF_TypeGnuUniqueObject:
+  case MCSA_LGlobal:
+  case MCSA_Extern:
+  case MCSA_Exported:
+  case MCSA_IndirectSymbol:
+  case MCSA_Internal:
+  case MCSA_LazyReference:
+  case MCSA_NoDeadStrip:
+  case MCSA_SymbolResolver:
+  case MCSA_AltEntry:
+  case MCSA_PrivateExtern:
+  case MCSA_Protected:
+  case MCSA_Reference:
+  case MCSA_WeakDefinition:
+  case MCSA_WeakDefAutoPrivate:
+  case MCSA_WeakAntiDep:
+  case MCSA_Memtag:
+    return false;
+
+  case MCSA_Global:
+    Symbol->setExternal(true);
+    break;
+  case MCSA_Local:
+    Symbol->setExternal(false);
+    break;
+  case MCSA_Weak:
+  case MCSA_WeakReference:
+    Symbol->setExternal(true);
+    Symbol->setWeak();
+    break;
+  case MCSA_Hidden:
+    Symbol->setHidden(true);
+    break;
+  }
+
+  return true;
+}
+
 MCStreamer *llvm::createGOFFStreamer(MCContext &Context,
                                      std::unique_ptr<MCAsmBackend> &&MAB,
                                      std::unique_ptr<MCObjectWriter> &&OW,
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
new file mode 100644
index 0000000000000..b03014ffd8e41
--- /dev/null
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -0,0 +1,40 @@
+//===- MCSymbolGOFF.cpp - GOFF Symbol Representation ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCSymbolGOFF.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+void MCSymbolGOFF::initAttributes() {
+  if (hasLDAttributes())
+    return;
+
+  if (isDefined()) {
+    MCSectionGOFF &Section = cast<MCSectionGOFF>(getSection());
+    GOFF::ESDBindingScope BindingScope =
+        isExternal() ? (isExported() ? GOFF::ESD_BSC_ImportExport
+                                     : GOFF::ESD_BSC_Library)
+                     : GOFF::ESD_BSC_Section;
+    GOFF::ESDBindingStrength BindingStrength =
+        isWeak() ? GOFF::ESDBindingStrength::ESD_BST_Weak
+                 : GOFF::ESDBindingStrength::ESD_BST_Strong;
+    if (Section.isED()) {
+      setLDAttributes(GOFF::LDAttr{false, GOFF::ESD_EXE_CODE, BindingStrength,
+                                   GOFF::ESD_LT_XPLink, GOFF::ESD_AMODE_64,
+                                   BindingScope});
+    } else if (Section.isPR()) {
+      // For data symbols, the attributes are already determind in TLOFI.
+      // TODO Does it make sense to it to here?
+    } else
+      llvm_unreachable("Unexpected section type for label");
+  }
+  // TODO Handle external symbol.
+}
diff --git a/llvm/test/CodeGen/SystemZ/zos-section-1.ll b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
index b98584df54d5a..6caa8f4d607de 100644
--- a/llvm/test/CodeGen/SystemZ/zos-section-1.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-section-1.ll
@@ -104,26 +104,34 @@ entry:
 ; CHECK-NEXT: 000300 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
 ; CHECK-NEXT: 000310 00 01 20 00 00 00 00 06 a3 85 a2 a3 7b c3 00 00
 
+; ESD record, type LD.
+; The name is me.
+; CHECK-NEXT: 000320 03 00 00 02 [[ME:00 00 00 09]] [[C_CODE64]] 00 00 00 00
+; CHECK-NEXT: 000330 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000340 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
+; CHECK-NEXT: 000350 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 02
+; CHECK-NEXT: 000360 00 04 20 00 00 00 00 02 94 85 00 00 00 00 00 00
+
 ; Text record for the code section C_CODE64.
 ; The regular expression matches the lower byte of the length.
-; CHECK-NEXT: 000320 03 11 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000330 00 00 00 00 00 00 00 {{..}} 00 c3 00 c5 00 c5 00 f1
+; CHECK-NEXT: 000370 03 11 00 00 [[C_CODE64]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000380 00 00 00 00 00 00 00 {{..}} 00 c3 00 c5 00 c5 00 f1
 
 ; Text record for the section .&ppa2.
-; CHECK:      0003c0 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0003d0 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      000410 03 10 00 00 [[PPA2]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000420 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; Text record for the ADA section test#S.
-; CHECK:      000410 03 10 00 00 [[TESTS]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000420 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      000460 03 10 00 00 [[TESTS]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000470 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; Text record for the section B_IDRL.
-; CHECK:      000460 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 000470 00 00 00 00 00 00 00 {{..}} {{.*}}
+; CHECK:      0004b0 03 10 00 01 [[BIDRL]] 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 0004c0 00 00 00 00 00 00 00 {{..}} {{.*}}
 
 ; End record.
-; CHECK:      0004b0 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0004c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0004d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0004e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-; CHECK-NEXT: 0004f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK:      000500 03 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000520 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+; CHECK-NEXT: 000540 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

>From 7763a9f22aad27e65813b399378d5624e3a16519 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Mon, 20 Oct 2025 14:13:06 -0400
Subject: [PATCH 2/2] Update

---
 llvm/include/llvm/MC/MCDirectives.h           |  4 +
 llvm/lib/MC/MCSymbolGOFF.cpp                  |  5 ++
 .../MCTargetDesc/SystemZHLASMAsmStreamer.cpp  | 81 +++++++++++++++++--
 .../MCTargetDesc/SystemZHLASMAsmStreamer.h    |  2 +
 .../MCTargetDesc/SystemZTargetStreamer.cpp    |  6 +-
 .../MCTargetDesc/SystemZTargetStreamer.h      |  5 +-
 llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 13 +++
 7 files changed, 105 insertions(+), 11 deletions(-)

diff --git a/llvm/include/llvm/MC/MCDirectives.h b/llvm/include/llvm/MC/MCDirectives.h
index f8b7e05b3719b..f69144367c8e7 100644
--- a/llvm/include/llvm/MC/MCDirectives.h
+++ b/llvm/include/llvm/MC/MCDirectives.h
@@ -48,6 +48,10 @@ enum MCSymbolAttr {
   MCSA_WeakDefAutoPrivate,      ///< .weak_def_can_be_hidden (MachO)
   MCSA_WeakAntiDep,             ///< .weak_anti_dep (COFF)
   MCSA_Memtag,                  ///< .memtag (ELF)
+
+  // Attributes specific for HLASM.
+  MCSA_Code,                    ///< symbol is code (GOFF)
+  MCSA_Data,                    ///< symbol is data (GOFF)
 };
 
 enum MCDataRegionType {
diff --git a/llvm/lib/MC/MCSymbolGOFF.cpp b/llvm/lib/MC/MCSymbolGOFF.cpp
index b03014ffd8e41..8b1521d03dd74 100644
--- a/llvm/lib/MC/MCSymbolGOFF.cpp
+++ b/llvm/lib/MC/MCSymbolGOFF.cpp
@@ -14,6 +14,11 @@
 using namespace llvm;
 
 void MCSymbolGOFF::initAttributes() {
+  // Temporary labels are not emitted into the object file.
+  if (isTemporary())
+    return;
+
+  // Do not initialize the attributes multiple times.
   if (hasLDAttributes())
     return;
 
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
index 3ef6030ba5183..7e27f0fa00396 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.cpp
@@ -8,6 +8,9 @@
 
 #include "SystemZHLASMAsmStreamer.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/MC/MCGOFFAttributes.h"
+#include "llvm/MC/MCSymbolGOFF.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Signals.h"
 #include <sstream>
@@ -183,17 +186,74 @@ void SystemZHLASMAsmStreamer::emitInstruction(const MCInst &Inst,
   EmitEOL();
 }
 
+static void emitXATTR(raw_ostream &OS, StringRef Name,
+                      GOFF::ESDLinkageType Linkage,
+                      GOFF::ESDExecutable Executable,
+                      GOFF::ESDBindingScope BindingScope) {
+  OS << Name << " XATTR ";
+  OS << "LINKAGE(" << (Linkage == GOFF::ESD_LT_OS ? "OS" : "XPLINK") << "),";
+  if (Executable != GOFF::ESD_EXE_Unspecified)
+    OS << "REFERENCE(" << (Executable == GOFF::ESD_EXE_CODE ? "CODE" : "DATA")
+       << "),";
+  if (BindingScope != GOFF::ESD_BSC_Unspecified) {
+    OS << "SCOPE(";
+    switch (BindingScope) {
+    case GOFF::ESD_BSC_Section:
+      OS << "SECTION";
+      break;
+    case GOFF::ESD_BSC_Module:
+      OS << "MODULE";
+      break;
+    case GOFF::ESD_BSC_Library:
+      OS << "LIBRARY";
+      break;
+    case GOFF::ESD_BSC_ImportExport:
+      OS << "EXPORT";
+      break;
+    default:
+      break;
+    }
+    OS << ')';
+  }
+  OS << '\n';
+}
+
+static bool sameNameAsCSECT(MCSymbolGOFF *Sym) {
+  if (Sym->hasLDAttributes() && Sym->isInSection()) {
+    MCSectionGOFF &ED = cast<MCSectionGOFF>(Sym->getSection());
+    return Sym->getName() == ED.getParent()->getName();
+  }
+  return false;
+}
+
 void SystemZHLASMAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
+  MCSymbolGOFF *Sym = cast<MCSymbolGOFF>(Symbol);
+
+  MCStreamer::emitLabel(Sym, Loc);
+  Sym->initAttributes();
+
+  // Emit ENTRY statement only if not implied by CSECT.
+  bool EmitEntry = !sameNameAsCSECT(Sym);
 
-  MCStreamer::emitLabel(Symbol, Loc);
+  if (!Sym->isTemporary() && Sym->hasLDAttributes()) {
+    GOFF::LDAttr &LD = Sym->getLDAttributes();
+    if (EmitEntry) {
+      OS << " ENTRY " << Sym->getName();
+      EmitEOL();
+    }
+
+    emitXATTR(OS, Sym->getName(), LD.Linkage, LD.Executable, LD.BindingScope);
+    EmitEOL();
+  }
 
-  Symbol->print(OS, MAI);
   // TODO Need to adjust this based on Label type
-  OS << " DS 0H";
-  // TODO Update LabelSuffix in SystemZMCAsmInfoGOFF once tests have been
-  // moved to HLASM syntax.
-  // OS << MAI->getLabelSuffix();
-  EmitEOL();
+  if (EmitEntry) {
+    OS << Sym->getName() << " DS 0H";
+    // TODO Update LabelSuffix in SystemZMCAsmInfoGOFF once tests have been
+    // moved to HLASM syntax.
+    // OS << MAI->getLabelSuffix();
+    EmitEOL();
+  }
 }
 
 void SystemZHLASMAsmStreamer::emitRawTextImpl(StringRef String) {
@@ -285,3 +345,10 @@ void SystemZHLASMAsmStreamer::emitEnd() {
   OS << " END";
   EmitEOL();
 }
+
+void SystemZHLASMAsmStreamer::emitExtern(MCSymbolGOFF &Sym) {
+  Sym.initAttributes();
+  OS << " EXTRN " << Sym.getName();
+  EmitEOL();
+  // TODO Emit XATTR.
+}
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h
index 93b1ac4d901aa..95e12a5abacc9 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZHLASMAsmStreamer.h
@@ -28,6 +28,7 @@
 #include "llvm/Support/FormattedStream.h"
 
 namespace llvm {
+class MCSymbolGOFF;
 
 class SystemZHLASMAsmStreamer final : public MCStreamer {
   constexpr static size_t InstLimit = 80;
@@ -123,6 +124,7 @@ class SystemZHLASMAsmStreamer final : public MCStreamer {
   /// @}
 
   void emitEnd();
+  void emitExtern(MCSymbolGOFF &Sym);
 };
 } // namespace llvm
 
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
index 1a3e373f25374..551df605d53b6 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
@@ -16,6 +16,8 @@
 #include "SystemZHLASMAsmStreamer.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCSymbolGOFF.h"
+#include "llvm/Support/Casting.h"
 
 using namespace llvm;
 
@@ -38,8 +40,8 @@ SystemZHLASMAsmStreamer &SystemZTargetHLASMStreamer::getHLASMStreamer() {
   return static_cast<SystemZHLASMAsmStreamer &>(getStreamer());
 }
 
-void SystemZTargetHLASMStreamer::emitExtern(StringRef Sym) {
-  getStreamer().emitRawText(Twine(" EXTRN ") + Twine(Sym));
+void SystemZTargetHLASMStreamer::emitExtern(MCSymbol *Symbol) {
+  getHLASMStreamer().emitExtern(*cast<MCSymbolGOFF>(Symbol));
 }
 
 void SystemZTargetHLASMStreamer::emitEnd() { getHLASMStreamer().emitEnd(); }
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
index 3fc09bc8c683a..994052efdcc41 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
@@ -57,7 +57,7 @@ class SystemZTargetStreamer : public MCTargetStreamer {
 
   virtual void emitMachine(StringRef CPUOrCommand) {};
 
-  virtual void emitExtern(StringRef Str) {};
+  virtual void emitExtern(MCSymbol *Symbol) {};
   virtual void emitEnd() {};
 
   virtual const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
@@ -69,6 +69,7 @@ class SystemZTargetStreamer : public MCTargetStreamer {
 class SystemZTargetGOFFStreamer : public SystemZTargetStreamer {
 public:
   SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {}
+  //void emitExtern(MCSymbol *Symbol) override;
   const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                    const MCSymbol *Lo) override;
 };
@@ -80,7 +81,7 @@ class SystemZTargetHLASMStreamer : public SystemZTargetStreamer {
   SystemZTargetHLASMStreamer(MCStreamer &S, formatted_raw_ostream &OS)
       : SystemZTargetStreamer(S), OS(OS) {}
   SystemZHLASMAsmStreamer &getHLASMStreamer();
-  void emitExtern(StringRef Sym) override;
+  void emitExtern(MCSymbol *Symbol) override;
   void emitEnd() override;
   const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
                                    const MCSymbol *Lo) override;
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index e31d7c6a86476..8e46bcfdad297 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -26,6 +26,7 @@
 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
 #include "llvm/IR/Mangler.h"
 #include "llvm/IR/Module.h"
+#include "llvm/MC/MCDirectives.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInstBuilder.h"
 #include "llvm/MC/MCSectionELF.h"
@@ -1112,6 +1113,17 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
   if (TT.isOSzOS()) {
     emitADASection();
     emitIDRLSection(M);
+    // Emit EXTRN declarations.
+    for (auto &GO : M.global_objects()) {
+      if (GO.isDeclaration()) {
+        MCSymbol *Sym = TM.getSymbol(&GO);
+        OutStreamer->emitSymbolAttribute(
+            Sym, GO.hasWeakLinkage() ? MCSA_WeakReference : MCSA_Global);
+        OutStreamer->emitSymbolAttribute(Sym, isa<Function>(GO) ? MCSA_Code
+                                                                : MCSA_Data);
+        getTargetStreamer()->emitExtern(Sym);
+      }
+    }
   }
   emitAttributes(M);
   // Emit the END instruction in case of HLASM output. This must be the last
@@ -1570,6 +1582,7 @@ void SystemZAsmPrinter::emitPPA2(Module &M) {
   // Make CELQSTRT symbol.
   const char *StartSymbolName = "CELQSTRT";
   MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
+  getTargetStreamer()->emitExtern(CELQSTRT);
 
   // Create symbol and assign to class field for use in PPA1.
   PPA2Sym = OutContext.createTempSymbol("PPA2", false);



More information about the llvm-commits mailing list