[llvm] 5ac411a - [SystemZ][z/OS] Add the PPA1 to SystemZAsmPrinter

Yusra Syeda via llvm-commits llvm-commits at lists.llvm.org
Wed May 18 11:13:28 PDT 2022


Author: Yusra Syeda
Date: 2022-05-18T14:13:17-04:00
New Revision: 5ac411aea802f5983b7979b9198ba7d8fb38f64d

URL: https://github.com/llvm/llvm-project/commit/5ac411aea802f5983b7979b9198ba7d8fb38f64d
DIFF: https://github.com/llvm/llvm-project/commit/5ac411aea802f5983b7979b9198ba7d8fb38f64d.diff

LOG: [SystemZ][z/OS] Add the PPA1 to SystemZAsmPrinter

Differential Revision: https://reviews.llvm.org/D125725

Added: 
    llvm/include/llvm/BinaryFormat/GOFF.h

Modified: 
    llvm/include/llvm/MC/MCContext.h
    llvm/include/llvm/MC/MCObjectFileInfo.h
    llvm/include/llvm/MC/MCSectionGOFF.h
    llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    llvm/lib/MC/MCContext.cpp
    llvm/lib/MC/MCObjectFileInfo.cpp
    llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
    llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
    llvm/test/MC/GOFF/ppa1.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/BinaryFormat/GOFF.h b/llvm/include/llvm/BinaryFormat/GOFF.h
new file mode 100644
index 000000000000..40d323cac99c
--- /dev/null
+++ b/llvm/include/llvm/BinaryFormat/GOFF.h
@@ -0,0 +1,31 @@
+//===-- llvm/BinaryFormat/GOFF.h - GOFF definitions --------------*- C++-*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This header contains common, non-processor-specific data structures and
+// constants for the GOFF file format.
+//
+// GOFF specifics can be found in MVS Program Management: Advanced Facilities
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_BINARYFORMAT_GOFF_H
+#define LLVM_BINARYFORMAT_GOFF_H
+
+namespace llvm {
+
+namespace GOFF {
+
+// \brief Subsections of the primary C_CODE section in the object file.
+enum SubsectionKind : uint8_t {
+  SK_PPA1 = 2,
+};
+
+} // end namespace GOFF
+
+} // end namespace llvm
+
+#endif // LLVM_BINARYFORMAT_GOFF_H

diff  --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h
index b639473b2d8e..5b81ba31b83c 100644
--- a/llvm/include/llvm/MC/MCContext.h
+++ b/llvm/include/llvm/MC/MCContext.h
@@ -613,7 +613,8 @@ class MCContext {
                                               unsigned Flags,
                                               unsigned EntrySize);
 
-  MCSectionGOFF *getGOFFSection(StringRef Section, SectionKind Kind);
+  MCSectionGOFF *getGOFFSection(StringRef Section, SectionKind Kind,
+                                MCSection *Parent, const MCExpr *SubsectionId);
 
   MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
                                 SectionKind Kind, StringRef COMDATSymName,

diff  --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h
index f1e63e0ba7be..e4ae85e91531 100644
--- a/llvm/include/llvm/MC/MCObjectFileInfo.h
+++ b/llvm/include/llvm/MC/MCObjectFileInfo.h
@@ -225,6 +225,9 @@ class MCObjectFileInfo {
   MCSection *GIATsSection = nullptr;
   MCSection *GLJMPSection = nullptr;
 
+  // GOFF specific sections.
+  MCSection *PPA1Section = nullptr;
+
   // XCOFF specific sections
   MCSection *TOCBaseSection = nullptr;
   MCSection *ReadOnly8Section = nullptr;
@@ -423,6 +426,9 @@ class MCObjectFileInfo {
   MCSection *getGIATsSection() const { return GIATsSection; }
   MCSection *getGLJMPSection() const { return GLJMPSection; }
 
+  // GOFF specific sections.
+  MCSection *getPPA1Section() const { return PPA1Section; }
+
   // XCOFF specific sections
   MCSection *getTOCBaseSection() const { return TOCBaseSection; }
 

diff  --git a/llvm/include/llvm/MC/MCSectionGOFF.h b/llvm/include/llvm/MC/MCSectionGOFF.h
index ce36d92ebd56..d866329461ce 100644
--- a/llvm/include/llvm/MC/MCSectionGOFF.h
+++ b/llvm/include/llvm/MC/MCSectionGOFF.h
@@ -15,6 +15,7 @@
 #ifndef LLVM_MC_MCSECTIONGOFF_H
 #define LLVM_MC_MCSECTIONGOFF_H
 
+#include "llvm/BinaryFormat/GOFF.h"
 #include "llvm/MC/MCSection.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -24,9 +25,12 @@ class MCExpr;
 
 class MCSectionGOFF final : public MCSection {
 private:
+  MCSection *Parent;
+  const MCExpr *SubsectionId;
+
   friend class MCContext;
-  MCSectionGOFF(StringRef Name, SectionKind K)
-      : MCSection(SV_GOFF, Name, K, nullptr) {}
+  MCSectionGOFF(StringRef Name, SectionKind K, MCSection *P, const MCExpr *Sub)
+      : MCSection(SV_GOFF, Name, K, nullptr), Parent(P), SubsectionId(Sub) {}
 
 public:
   void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
@@ -39,6 +43,9 @@ class MCSectionGOFF final : public MCSection {
 
   bool isVirtualSection() const override { return false; }
 
+  MCSection *getParent() const { return Parent; }
+  const MCExpr *getSubsectionId() const { return SubsectionId; }
+
   static bool classof(const MCSection *S) { return S->getVariant() == SV_GOFF; }
 };
 } // end namespace llvm

diff  --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index d34ba6fd77d9..7e2dd1546b5b 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2593,8 +2593,8 @@ MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
   auto *Symbol = TM.getSymbol(GO);
   if (Kind.isBSS())
-    return getContext().getGOFFSection(Symbol->getName(),
-                                       SectionKind::getBSS());
+    return getContext().getGOFFSection(Symbol->getName(), SectionKind::getBSS(),
+                                       nullptr, nullptr);
 
   return getContext().getObjectFileInfo()->getTextSection();
 }

diff  --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index 827fe691fc44..887969fcd841 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -634,11 +634,14 @@ Optional<unsigned> MCContext::getELFUniqueIDForEntsize(StringRef SectionName,
   return (I != ELFEntrySizeMap.end()) ? Optional<unsigned>(I->second) : None;
 }
 
-MCSectionGOFF *MCContext::getGOFFSection(StringRef Section, SectionKind Kind) {
+MCSectionGOFF *MCContext::getGOFFSection(StringRef Section, SectionKind Kind,
+                                         MCSection *Parent,
+                                         const MCExpr *SubsectionId) {
   // Do the lookup. If we don't have a hit, return a new section.
   auto &GOFFSection = GOFFUniquingMap[Section.str()];
   if (!GOFFSection)
-    GOFFSection = new (GOFFAllocator.Allocate()) MCSectionGOFF(Section, Kind);
+    GOFFSection = new (GOFFAllocator.Allocate())
+        MCSectionGOFF(Section, Kind, Parent, SubsectionId);
 
   return GOFFSection;
 }

diff  --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 3ee8167c3832..d56f72cfc388 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -523,8 +523,13 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
 }
 
 void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
-  TextSection = Ctx->getGOFFSection(".text", SectionKind::getText());
-  BSSSection = Ctx->getGOFFSection(".bss", SectionKind::getBSS());
+  TextSection =
+      Ctx->getGOFFSection(".text", SectionKind::getText(), nullptr, nullptr);
+  BSSSection =
+      Ctx->getGOFFSection(".bss", SectionKind::getBSS(), nullptr, nullptr);
+  PPA1Section =
+      Ctx->getGOFFSection(".ppa1", SectionKind::getMetadata(), TextSection,
+                          MCConstantExpr::create(GOFF::SK_PPA1, *Ctx));
 }
 
 void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {

diff  --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 75f19e01e9b2..3142abb2b08c 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -819,13 +819,253 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
   emitStackMaps(SM);
 }
 
+void SystemZAsmPrinter::emitFunctionBodyEnd() {
+  if (TM.getTargetTriple().isOSzOS()) {
+    // Emit symbol for the end of function if the z/OS target streamer
+    // is used. This is needed to calculate the size of the function.
+    MCSymbol *FnEndSym = createTempSymbol("func_end");
+    OutStreamer->emitLabel(FnEndSym);
+
+    OutStreamer->PushSection();
+    OutStreamer->SwitchSection(getObjFileLowering().getPPA1Section());
+    emitPPA1(FnEndSym);
+    OutStreamer->PopSection();
+
+    CurrentFnPPA1Sym = nullptr;
+    CurrentFnEPMarkerSym = nullptr;
+  }
+}
+
+static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
+                          bool StackProtector, bool FPRMask, bool VRMask) {
+  enum class PPA1Flag1 : uint8_t {
+    DSA64Bit = (0x80 >> 0),
+    VarArg = (0x80 >> 7),
+    LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit)
+  };
+  enum class PPA1Flag2 : uint8_t {
+    ExternalProcedure = (0x80 >> 0),
+    STACKPROTECTOR = (0x80 >> 3),
+    LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
+  };
+  enum class PPA1Flag3 : uint8_t {
+    FPRMask = (0x80 >> 2),
+    LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
+  };
+  enum class PPA1Flag4 : uint8_t {
+    EPMOffsetPresent = (0x80 >> 0),
+    VRMask = (0x80 >> 2),
+    ProcedureNamePresent = (0x80 >> 7),
+    LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
+  };
+
+  // Declare optional section flags that can be modified.
+  auto Flags1 = PPA1Flag1(0);
+  auto Flags2 = PPA1Flag2::ExternalProcedure;
+  auto Flags3 = PPA1Flag3(0);
+  auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent;
+
+  Flags1 |= PPA1Flag1::DSA64Bit;
+
+  if (VarArg)
+    Flags1 |= PPA1Flag1::VarArg;
+
+  if (StackProtector)
+    Flags2 |= PPA1Flag2::STACKPROTECTOR;
+
+  // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
+  if (FPRMask)
+    Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
+
+  if (VRMask)
+    Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
+
+  OutStreamer->AddComment("PPA1 Flags 1");
+  if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
+    OutStreamer->AddComment("  Bit 0: 1 = 64-bit DSA");
+  else
+    OutStreamer->AddComment("  Bit 0: 0 = 32-bit DSA");
+  if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
+    OutStreamer->AddComment("  Bit 7: 1 = Vararg function");
+  OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
+
+  OutStreamer->AddComment("PPA1 Flags 2");
+  if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
+    OutStreamer->AddComment("  Bit 0: 1 = External procedure");
+  if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
+    OutStreamer->AddComment("  Bit 3: 1 = STACKPROTECT is enabled");
+  else
+    OutStreamer->AddComment("  Bit 3: 0 = STACKPROTECT is not enabled");
+  OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
+
+  OutStreamer->AddComment("PPA1 Flags 3");
+  if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
+    OutStreamer->AddComment("  Bit 2: 1 = FP Reg Mask is in optional area");
+  OutStreamer->emitInt8(
+      static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
+
+  OutStreamer->AddComment("PPA1 Flags 4");
+  if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
+    OutStreamer->AddComment("  Bit 2: 1 = Vector Reg Mask is in optional area");
+  OutStreamer->emitInt8(static_cast<uint8_t>(
+      Flags4)); // Flags 4 (optional sections, always emit these).
+}
+
+void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
+  const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
+  const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
+  const auto TargetHasVector = Subtarget.hasVector();
+
+  const SystemZMachineFunctionInfo *ZFI =
+      MF->getInfo<SystemZMachineFunctionInfo>();
+  const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
+      Subtarget.getFrameLowering());
+  const MachineFrameInfo &MFFrame = MF->getFrameInfo();
+
+  // Get saved GPR/FPR/VPR masks.
+  const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
+  uint16_t SavedGPRMask = 0;
+  uint16_t SavedFPRMask = 0;
+  uint8_t SavedVRMask = 0;
+  int64_t OffsetFPR = 0;
+  int64_t OffsetVR = 0;
+  const int64_t TopOfStack =
+      MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
+
+  // Loop over the spilled registers. The CalleeSavedInfo can't be used because
+  // it does not contain all spilled registers.
+  for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
+                E = ZFI->getSpillGPRRegs().HighGPR;
+       I && E && I <= E; ++I) {
+    unsigned V = TRI->getEncodingValue((Register)I);
+    assert(V < 16 && "GPR index out of range");
+    SavedGPRMask |= 1 << (15 - V);
+  }
+
+  for (auto &CS : CSI) {
+    unsigned Reg = CS.getReg();
+    unsigned I = TRI->getEncodingValue(Reg);
+
+    if (SystemZ::FP64BitRegClass.contains(Reg)) {
+      assert(I < 16 && "FPR index out of range");
+      SavedFPRMask |= 1 << (15 - I);
+      int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
+      if (Temp < OffsetFPR)
+        OffsetFPR = Temp;
+    } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
+      assert(I >= 16 && I <= 23 && "VPR index out of range");
+      unsigned BitNum = I - 16;
+      SavedVRMask |= 1 << (7 - BitNum);
+      int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
+      if (Temp < OffsetVR)
+        OffsetVR = Temp;
+    }
+  }
+
+  // Adjust the offset.
+  OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
+  OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
+
+  // Get alloca register.
+  uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
+  uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
+  assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
+
+  // Build FPR save area offset.
+  uint32_t FrameAndFPROffset = 0;
+  if (SavedFPRMask) {
+    uint64_t FPRSaveAreaOffset = OffsetFPR;
+    assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
+
+    FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
+    FrameAndFPROffset |= FrameReg << 28;                // Put into top 4 bits.
+  }
+
+  // Build VR save area offset.
+  uint32_t FrameAndVROffset = 0;
+  if (TargetHasVector && SavedVRMask) {
+    uint64_t VRSaveAreaOffset = OffsetVR;
+    assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
+
+    FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
+    FrameAndVROffset |= FrameReg << 28;               // Put into top 4 bits.
+  }
+
+  // Emit PPA1 section.
+  OutStreamer->AddComment("PPA1");
+  OutStreamer->emitLabel(CurrentFnPPA1Sym);
+  OutStreamer->AddComment("Version");
+  OutStreamer->emitInt8(0x02); // Version.
+  OutStreamer->AddComment("LE Signature X'CE'");
+  OutStreamer->emitInt8(0xCE); // CEL signature.
+  OutStreamer->AddComment("Saved GPR Mask");
+  OutStreamer->emitInt16(SavedGPRMask);
+
+  emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
+                MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
+                TargetHasVector && SavedVRMask != 0);
+
+  OutStreamer->AddComment("Length/4 of Parms");
+  OutStreamer->emitInt16(
+      static_cast<uint16_t>(MFFrame.getMaxCallFrameSize() / 4)); // Parms/4.
+  OutStreamer->AddComment("Length of Code");
+  OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
+
+  // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
+  if (SavedFPRMask) {
+    OutStreamer->AddComment("FPR mask");
+    OutStreamer->emitInt16(SavedFPRMask);
+    OutStreamer->AddComment("AR mask");
+    OutStreamer->emitInt16(0); // AR Mask, unused currently.
+    OutStreamer->AddComment("FPR Save Area Locator");
+    OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
+                                .concat(utostr(FrameAndFPROffset >> 28))
+                                .str());
+    OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
+                                .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
+                                .str());
+    OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
+                                               // register to add value to
+                                               // (alloca reg).
+  }
+
+  // Emit saved VR mask to VR save area.
+  if (TargetHasVector && SavedVRMask) {
+    OutStreamer->AddComment("VR mask");
+    OutStreamer->emitInt8(SavedVRMask);
+    OutStreamer->emitInt8(0);  // Reserved.
+    OutStreamer->emitInt16(0); // Also reserved.
+    OutStreamer->AddComment("VR Save Area Locator");
+    OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
+                                .concat(utostr(FrameAndVROffset >> 28))
+                                .str());
+    OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
+                                .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
+                                .str());
+    OutStreamer->emitInt32(FrameAndVROffset);
+  }
+
+  // Emit offset to entry point optional section (0x80 of flags 4).
+  OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
+                                      4);
+}
+
 void SystemZAsmPrinter::emitFunctionEntryLabel() {
   const SystemZSubtarget &Subtarget =
       static_cast<const SystemZSubtarget &>(MF->getSubtarget());
 
   if (Subtarget.getTargetTriple().isOSzOS()) {
     MCContext &OutContext = OutStreamer->getContext();
-    MCSymbol *EPMarkerSym = OutContext.createTempSymbol("CM_", true);
+
+    // Save information for later use.
+    std::string N(MF->getFunction().hasName()
+                      ? Twine(MF->getFunction().getName()).concat("_").str()
+                      : "");
+
+    CurrentFnEPMarkerSym =
+        OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);
+    CurrentFnPPA1Sym =
+        OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);
 
     // EntryPoint Marker
     const MachineFrameInfo &MFFrame = MF->getFrameInfo();
@@ -844,11 +1084,14 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
 
     // Emit entry point marker section.
     OutStreamer->AddComment("XPLINK Routine Layout Entry");
-    OutStreamer->emitLabel(EPMarkerSym);
+    OutStreamer->emitLabel(CurrentFnEPMarkerSym);
     OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
     OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
     OutStreamer->AddComment("Mark Type C'1'");
     OutStreamer->emitInt8(0xF1); // Mark Type.
+    OutStreamer->AddComment("Offset to PPA1");
+    OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,
+                                        4);
     if (OutStreamer->isVerboseAsm()) {
       OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
       OutStreamer->AddComment("Entry Flags");

diff  --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
index 7839938f5ae5..f14b4a184f62 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
@@ -26,6 +26,8 @@ class raw_ostream;
 class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
 private:
   StackMaps SM;
+  MCSymbol *CurrentFnPPA1Sym;     // PPA1 Symbol.
+  MCSymbol *CurrentFnEPMarkerSym; // Entry Point Marker.
 
   SystemZTargetStreamer *getTargetStreamer() {
     MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
@@ -45,9 +47,12 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
     BASR33 = 7,   // b'x111' == BASR  r3,r3
   };
 
+  void emitPPA1(MCSymbol *FnEndSym);
+
 public:
   SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
-      : AsmPrinter(TM, std::move(Streamer)), SM(*this) {}
+      : AsmPrinter(TM, std::move(Streamer)), SM(*this),
+        CurrentFnPPA1Sym(nullptr), CurrentFnEPMarkerSym(nullptr) {}
 
   // Override AsmPrinter.
   StringRef getPassName() const override { return "SystemZ Assembly Printer"; }
@@ -64,6 +69,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
     return AsmPrinter::doInitialization(M);
   }
   void emitFunctionEntryLabel() override;
+  void emitFunctionBodyEnd() override;
 
 private:
   void emitCallInformation(CallType CT);

diff  --git a/llvm/test/MC/GOFF/ppa1.ll b/llvm/test/MC/GOFF/ppa1.ll
index c494b1a70988..85231fb77434 100644
--- a/llvm/test/MC/GOFF/ppa1.ll
+++ b/llvm/test/MC/GOFF/ppa1.ll
@@ -1,7 +1,7 @@
 ; RUN: llc -mtriple s390x-ibm-zos < %s | FileCheck %s
 ; REQUIRES: systemz-registered-target
 
-; CHECK: @@CM_0: * @void_test
+; CHECK: @@EPM_void_test_0: * @void_test
 ; CHECK: * XPLINK Routine Layout Entry
 ; CHECK: .long   12779717 * Eyecatcher 0x00C300C500C500
 ; CHECK: .short  197
@@ -10,6 +10,24 @@
 ; CHECK: .long   128 * DSA Size 0x80
 ; CHECK: * Entry Flags
 ; CHECK: *   Bit 2: 0 = Does not use alloca
+; CHECK: @@func_end0:
+; CHECK: .section        ".ppa1"
+; CHECK: @@PPA1_void_test_0:                     * PPA1
+; CHECK:        .byte   2                               * Version
+; CHECK:        .byte   206                             * LE Signature X'CE'
+; CHECK:        .short  768                             * Saved GPR Mask
+; CHECK:        .byte   128                             * PPA1 Flags 1
+; CHECK:                                        *   Bit 0: 1 = 64-bit DSA
+; CHECK:        .byte   128                             * PPA1 Flags 2
+; CHECK:                                        *   Bit 0: 1 = External procedure
+; CHECK:                                        *   Bit 3: 0 = STACKPROTECT is not enabled
+; CHECK:         .byte   0                               * PPA1 Flags 3
+; CHECK:        .byte   129                             * PPA1 Flags 4
+; CHECK:        .short  0                               * Length/4 of Parms
+; CHECK:        .long   @@func_end0-@@EPM_void_test_0   * Length of Code
+; CHECK:        .long   @@EPM_void_test_0-@@PPA1_void_test_0
+; CHECK:        .section        ".text"
+; CHECK:                                        * -- End function
 define void @void_test() {
 entry:
   ret void


        


More information about the llvm-commits mailing list