[llvm] [SystemZ][z/OS] Move emission of PPA1 (PR #208543)
Kai Nacke via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 13 07:03:19 PDT 2026
https://github.com/redstar updated https://github.com/llvm/llvm-project/pull/208543
>From f2c6536e440ec35156ba6c24b904f5ce32c7590b Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Thu, 9 Jul 2026 15:51:29 -0400
Subject: [PATCH 1/3] [SystemZ][z/OS] Move emission of PPA1
There is an interesting restriction during emission: emitting debug information closes the text section. As result, emitting the delayed PPA1 data does not work in the current place together with emitting debug information.
Since the PPA1 information is constant data, the solution is to emit the data in the target strreamer, in `emitConstantPools()`.
---
.../MCTargetDesc/SystemZTargetStreamer.cpp | 257 +++++++++++++++++
.../MCTargetDesc/SystemZTargetStreamer.h | 64 +++--
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 271 ++----------------
llvm/lib/Target/SystemZ/SystemZAsmPrinter.h | 32 +--
llvm/test/CodeGen/SystemZ/zos-landingpad.ll | 4 +-
5 files changed, 328 insertions(+), 300 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
index 10f3e729f84f3..95f43a6bc76e4 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
@@ -14,9 +14,13 @@
#include "SystemZTargetStreamer.h"
#include "SystemZHLASMAsmStreamer.h"
+#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCGOFFStreamer.h"
#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/Support/ConvertEBCDIC.h"
using namespace llvm;
@@ -35,6 +39,259 @@ void SystemZTargetStreamer::emitConstantPools() {
EXRLTargets2Sym.clear();
}
+static void emitPPA1Flags(MCStreamer &OutStreamer, bool VarArg,
+ bool StackProtector, bool FPRMask, bool VRMask,
+ bool EHBlock, bool HasArgAreaLength, bool HasName) {
+ 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 {
+ HasArgAreaLength = (0x80 >> 1),
+ FPRMask = (0x80 >> 2),
+ LLVM_MARK_AS_BITMASK_ENUM(HasArgAreaLength)
+ };
+ enum class PPA1Flag4 : uint8_t {
+ EPMOffsetPresent = (0x80 >> 0),
+ VRMask = (0x80 >> 2),
+ EHBlock = (0x80 >> 3),
+ 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;
+
+ Flags1 |= PPA1Flag1::DSA64Bit;
+
+ if (VarArg)
+ Flags1 |= PPA1Flag1::VarArg;
+
+ if (StackProtector)
+ Flags2 |= PPA1Flag2::STACKPROTECTOR;
+
+ if (HasArgAreaLength)
+ Flags3 |= PPA1Flag3::HasArgAreaLength; // Add emit ArgAreaLength flag.
+
+ // 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.
+
+ if (EHBlock)
+ Flags4 |= PPA1Flag4::EHBlock; // Add optional EH block.
+
+ if (HasName)
+ Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block.
+
+ OutStreamer.AddComment("PPA1 Flags 1");
+ OutStreamer.AddComment(" Bit 0: 1 = 64-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::HasArgAreaLength) == PPA1Flag3::HasArgAreaLength)
+ OutStreamer.AddComment(
+ " Bit 1: 1 = Argument Area Length is in optional area");
+ 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");
+ if ((Flags4 & PPA1Flag4::EHBlock) == PPA1Flag4::EHBlock)
+ OutStreamer.AddComment(" Bit 3: 1 = C++ EH block");
+ if ((Flags4 & PPA1Flag4::ProcedureNamePresent) ==
+ PPA1Flag4::ProcedureNamePresent)
+ OutStreamer.AddComment(" Bit 7: 1 = Name Length and Name");
+ OutStreamer.emitInt8(static_cast<uint8_t>(
+ Flags4)); // Flags 4 (optional sections, always emit these).
+}
+
+static void emitPPA1Name(MCStreamer &OutStreamer, StringRef OutName) {
+ size_t NameSize = OutName.size();
+ uint16_t OutSize;
+ if (NameSize < UINT16_MAX) {
+ OutSize = static_cast<uint16_t>(NameSize);
+ } else {
+ OutName = OutName.substr(0, UINT16_MAX);
+ OutSize = UINT16_MAX;
+ }
+ // Emit padding to ensure that the next optional field word-aligned.
+ uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4);
+
+ SmallString<512> OutnameConv;
+ ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv);
+ OutName = OutnameConv.str();
+
+ OutStreamer.AddComment("Length of Name");
+ OutStreamer.emitInt16(OutSize);
+ OutStreamer.AddComment("Name of Function");
+ OutStreamer.emitBytes(OutName);
+ OutStreamer.emitZeros(ExtraZeros);
+}
+
+void SystemZzOSStreamer::emitPPA1(PPA1Info &Info) {
+ assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
+ MCStreamer &OutStreamer = getStreamer();
+ MCContext &OutContext = OutStreamer.getContext();
+
+ // Optional Argument Area Length.
+ // Note: This represents the length of the argument area that we reserve
+ // in our stack for setting up arguments for calls to other
+ // routines. If this optional field is not set, LE will reserve
+ // 128 bytes for the argument area. This optional field is
+ // created if greater than 128 bytes is required - to guarantee
+ // the required space is reserved on stack extension in the new
+ // extension. This optional field is also created if the
+ // routine has alloca(). This may reduce stack space
+ // if alloca() call causes a stack extension.
+ bool HasArgAreaLength = (Info.AllocaReg != 0) || (Info.CallFrameSize > 128);
+
+ // Emit PPA1 section.
+ OutStreamer.AddComment("PPA1");
+ OutStreamer.emitLabel(Info.PPA1);
+ 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(Info.SavedGPRMask);
+ OutStreamer.AddComment("Offset to PPA2");
+ OutStreamer.emitAbsoluteSymbolDiff(PPA2Sym, Info.PPA1, 4);
+
+ emitPPA1Flags(OutStreamer, Info.IsVarArg, Info.HasStackProtector,
+ Info.SavedFPRMask != 0, Info.SavedVRMask != 0,
+ Info.PersonalityRoutine != nullptr, HasArgAreaLength,
+ Info.Name.size() > 0);
+
+ OutStreamer.AddComment("Length/4 of Parms");
+ OutStreamer.emitInt16(
+ static_cast<uint16_t>(Info.SizeOfFnParams / 4)); // Parms/4.
+
+ OutStreamer.AddComment("Length/2 of Prolog ");
+ if (Info.EndOfProlog)
+ OutStreamer.emitValue(
+ createWordDiffExpr(OutContext, Info.EndOfProlog, Info.Fn), 1);
+ else
+ OutStreamer.emitInt8(0);
+
+ OutStreamer.AddComment("Alloca Reg + Offset/2 to SP Update");
+ OutStreamer.AddComment(
+ Twine(" Bit 0-3: Register R").concat(utostr(Info.AllocaReg)).str());
+ OutStreamer.AddComment(" Bit 4-8: Offset ");
+ const MCExpr *AllocaRegExpr =
+ MCConstantExpr::create(Info.AllocaReg << 4, OutContext);
+ if (Info.StackUpdate)
+ OutStreamer.emitValue(
+ MCBinaryExpr::createOr(
+ createWordDiffExpr(OutContext, Info.StackUpdate, Info.Fn),
+ AllocaRegExpr, OutContext),
+ 1);
+ else
+ OutStreamer.emitValue(AllocaRegExpr, 1);
+
+ OutStreamer.AddComment("Length of Code");
+ OutStreamer.emitAbsoluteSymbolDiff(Info.FnEnd, Info.EPMarker, 4);
+
+ if (HasArgAreaLength) {
+ OutStreamer.AddComment("Argument Area Length");
+ OutStreamer.emitInt32(Info.CallFrameSize);
+ }
+
+ // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
+ if (Info.SavedFPRMask) {
+ OutStreamer.AddComment("FPR mask");
+ OutStreamer.emitInt16(Info.SavedFPRMask);
+ OutStreamer.AddComment("AR mask");
+ OutStreamer.emitInt16(0); // AR Mask, unused currently.
+ OutStreamer.AddComment("FPR Save Area Locator");
+ uint64_t FPRSaveAreaOffset = Info.OffsetFPR;
+ assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
+ FPRSaveAreaOffset &= 0x0FFFFFFF; // Lose top 4 bits.
+ OutStreamer.AddComment(
+ Twine(" Bit 0-3: Register R").concat(utostr(Info.FrameReg)));
+ OutStreamer.AddComment(
+ Twine(" Bit 4-31: Offset ").concat(utostr(FPRSaveAreaOffset)));
+ OutStreamer.emitInt32(FPRSaveAreaOffset |
+ (Info.FrameReg << 28)); // Offset to FPR save area
+ // with register to add
+ // value to (alloca reg).
+ }
+
+ // Emit saved VR mask to VR save area.
+ if (Info.SavedVRMask) {
+ OutStreamer.AddComment("VR mask");
+ OutStreamer.emitInt8(Info.SavedVRMask);
+ OutStreamer.emitInt8(0); // Reserved.
+ OutStreamer.emitInt16(0); // Also reserved.
+ uint64_t VRSaveAreaOffset = Info.OffsetVR;
+ assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
+ VRSaveAreaOffset &= 0x0FFFFFFF; // Lose top 4 bits.
+ OutStreamer.AddComment("VR Save Area Locator");
+ OutStreamer.AddComment(
+ Twine(" Bit 0-3: Register R").concat(utostr(Info.FrameReg)));
+ OutStreamer.AddComment(
+ Twine(" Bit 4-31: Offset ").concat(utostr(VRSaveAreaOffset)));
+ OutStreamer.emitInt32(VRSaveAreaOffset | (Info.FrameReg << 28));
+ }
+
+ // Emit C++ EH information block.
+ if (Info.PersonalityRoutine) {
+ OutStreamer.AddComment("Version");
+ OutStreamer.emitInt32(1);
+ OutStreamer.AddComment("Flags");
+ OutStreamer.emitInt32(0); // LSDA field is a WAS offset
+ OutStreamer.AddComment("Personality routine");
+ OutStreamer.emitInt64(Info.PersonalityADADisp);
+ OutStreamer.AddComment("LSDA location");
+ OutStreamer.emitInt64(Info.GCCEHADADisp);
+ }
+
+ // Emit name length and name optional section (0x01 of flags 4)
+ if (Info.Name.size())
+ emitPPA1Name(OutStreamer, Info.Name);
+
+ // Emit offset to entry point optional section (0x80 of flags 4).
+ OutStreamer.emitAbsoluteSymbolDiff(Info.EPMarker, Info.PPA1, 4);
+}
+
+void SystemZzOSStreamer::emitConstantPools() {
+ // Emit EXRL target instructions (base class prolog).
+ SystemZTargetStreamer::emitConstantPools();
+
+ // Emit deferred PPA1 blocks into the text section.
+ if (DeferredPPA1.empty())
+ return;
+ const MCObjectFileInfo &OFI = *getStreamer().getContext().getObjectFileInfo();
+ getStreamer().switchSection(OFI.getTextSection());
+ for (auto &Info : DeferredPPA1)
+ emitPPA1(Info);
+}
+
SystemZHLASMAsmStreamer &SystemZTargetHLASMStreamer::getHLASMStreamer() {
return static_cast<SystemZHLASMAsmStreamer &>(getStreamer());
}
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
index 0c98557703517..769fac11c25ca 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
@@ -9,6 +9,7 @@
#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZTARGETSTREAMER_H
#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZTARGETSTREAMER_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
@@ -71,11 +72,42 @@ class SystemZTargetStreamer : public MCTargetStreamer {
virtual void emitADA(MCSymbol *Sym, MCSection *Section) {}
};
-class SystemZTargetGOFFStreamer : public SystemZTargetStreamer {
+class SystemZzOSStreamer : public SystemZTargetStreamer {
public:
- SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {}
- const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
- const MCSymbol *Lo) override;
+ /// Information about a single function needed to emit a PPA1 block.
+ struct PPA1Info {
+ StringRef Name;
+ MCSymbol *Fn = nullptr; // Symbol marking function begin.
+ MCSymbol *FnEnd = nullptr; // Symbol marking function end.
+ MCSymbol *PPA1 = nullptr; // Symbol marking PPA1 begin.
+ MCSymbol *EPMarker = nullptr; // Symbol marking entry point.
+ MCSymbol *EndOfProlog = nullptr; // Symbol marking the end of the prolog.
+ MCSymbol *StackUpdate = nullptr; // Symbol marking the stack updating instr.
+ MCSymbol *PersonalityRoutine = nullptr;
+ MCSymbol *GCCEH = nullptr;
+ int64_t OffsetFPR = 0;
+ int64_t OffsetVR = 0;
+ uint64_t CallFrameSize = 0;
+ uint64_t PersonalityADADisp = 0; // ADA displacement for personality routine.
+ uint64_t GCCEHADADisp = 0; // ADA displacement for GCCEH symbol.
+ unsigned SizeOfFnParams = 0;
+ uint32_t FrameAndFPROffset;
+ uint32_t FrameAndVROffset;
+ uint16_t SavedGPRMask = 0;
+ uint16_t SavedFPRMask = 0;
+ uint8_t SavedVRMask = 0;
+ uint8_t FrameReg = 0;
+ uint8_t AllocaReg = 0;
+ bool IsVarArg = false;
+ bool HasStackProtector = false;
+ };
+
+ SmallVector<PPA1Info, 0> DeferredPPA1;
+
+ MCSymbol *PPA2Sym = nullptr;
+
+ SystemZzOSStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {}
+
virtual void emitExternalName(MCSymbol *Sym, StringRef Name) override {
static_cast<MCSymbolGOFF *>(Sym)->setExternalName(Name);
}
@@ -86,27 +118,27 @@ class SystemZTargetGOFFStreamer : public SystemZTargetStreamer {
static_cast<MCSymbolGOFF *>(Sym)->setADA(
static_cast<MCSectionGOFF *>(Section));
}
+
+ void emitConstantPools() override;
+ void emitPPA1(PPA1Info &Info);
};
-class SystemZTargetHLASMStreamer : public SystemZTargetStreamer {
+class SystemZTargetGOFFStreamer : public SystemZzOSStreamer {
+public:
+ SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZzOSStreamer(S) {}
+ const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
+ const MCSymbol *Lo) override;
+};
+
+class SystemZTargetHLASMStreamer : public SystemZzOSStreamer {
formatted_raw_ostream &OS;
public:
SystemZTargetHLASMStreamer(MCStreamer &S, formatted_raw_ostream &OS)
- : SystemZTargetStreamer(S), OS(OS) {}
+ : SystemZzOSStreamer(S), OS(OS) {}
SystemZHLASMAsmStreamer &getHLASMStreamer();
const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
const MCSymbol *Lo) override;
- virtual void emitExternalName(MCSymbol *Sym, StringRef Name) override {
- static_cast<MCSymbolGOFF *>(Sym)->setExternalName(Name);
- }
- virtual void emitExternalName(MCSection *Sec, StringRef Name) override {
- static_cast<MCSectionGOFF *>(Sec)->setExternalName(Name);
- }
- void emitADA(MCSymbol *Sym, MCSection *Section) override {
- static_cast<MCSymbolGOFF *>(Sym)->setADA(
- static_cast<MCSectionGOFF *>(Section));
- }
};
class SystemZTargetELFStreamer : public SystemZTargetStreamer {
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index a90df8e1e0568..a00d845c158ae 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1296,9 +1296,6 @@ bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
auto TT = OutContext.getTargetTriple();
if (TT.isOSzOS()) {
- OutStreamer->switchSection(getObjFileLowering().getTextSection());
- for (auto &Info : DeferredPPA1)
- emitPPA1(Info);
emitADASection();
emitIDRLSection(M);
// On z/OS, we need to associate an external data reference with an ED
@@ -1457,252 +1454,11 @@ 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.
- OutStreamer->emitLabel(DeferredPPA1.back().FnEnd);
+ auto *ZOS = static_cast<SystemZzOSStreamer *>(getTargetStreamer());
+ OutStreamer->emitLabel(ZOS->DeferredPPA1.back().FnEnd);
}
}
-static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
- bool StackProtector, bool FPRMask, bool VRMask,
- bool EHBlock, bool HasArgAreaLength, bool HasName) {
- 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 {
- HasArgAreaLength = (0x80 >> 1),
- FPRMask = (0x80 >> 2),
- LLVM_MARK_AS_BITMASK_ENUM(HasArgAreaLength)
- };
- enum class PPA1Flag4 : uint8_t {
- EPMOffsetPresent = (0x80 >> 0),
- VRMask = (0x80 >> 2),
- EHBlock = (0x80 >> 3),
- 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;
-
- Flags1 |= PPA1Flag1::DSA64Bit;
-
- if (VarArg)
- Flags1 |= PPA1Flag1::VarArg;
-
- if (StackProtector)
- Flags2 |= PPA1Flag2::STACKPROTECTOR;
-
- if (HasArgAreaLength)
- Flags3 |= PPA1Flag3::HasArgAreaLength; // Add emit ArgAreaLength flag.
-
- // 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.
-
- if (EHBlock)
- Flags4 |= PPA1Flag4::EHBlock; // Add optional EH block.
-
- if (HasName)
- Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block.
-
- OutStreamer->AddComment("PPA1 Flags 1");
- OutStreamer->AddComment(" Bit 0: 1 = 64-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::HasArgAreaLength) == PPA1Flag3::HasArgAreaLength)
- OutStreamer->AddComment(
- " Bit 1: 1 = Argument Area Length is in optional area");
- 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");
- if ((Flags4 & PPA1Flag4::EHBlock) == PPA1Flag4::EHBlock)
- OutStreamer->AddComment(" Bit 3: 1 = C++ EH block");
- if ((Flags4 & PPA1Flag4::ProcedureNamePresent) ==
- PPA1Flag4::ProcedureNamePresent)
- OutStreamer->AddComment(" Bit 7: 1 = Name Length and Name");
- OutStreamer->emitInt8(static_cast<uint8_t>(
- Flags4)); // Flags 4 (optional sections, always emit these).
-}
-
-static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer,
- StringRef OutName) {
- size_t NameSize = OutName.size();
- uint16_t OutSize;
- if (NameSize < UINT16_MAX) {
- OutSize = static_cast<uint16_t>(NameSize);
- } else {
- OutName = OutName.substr(0, UINT16_MAX);
- OutSize = UINT16_MAX;
- }
- // Emit padding to ensure that the next optional field word-aligned.
- uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4);
-
- SmallString<512> OutnameConv;
- ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv);
- OutName = OutnameConv.str();
-
- OutStreamer->AddComment("Length of Name");
- OutStreamer->emitInt16(OutSize);
- OutStreamer->AddComment("Name of Function");
- OutStreamer->emitBytes(OutName);
- OutStreamer->emitZeros(ExtraZeros);
-}
-
-void SystemZAsmPrinter::emitPPA1(PPA1Info &Info) {
- assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
-
- // Optional Argument Area Length.
- // Note: This represents the length of the argument area that we reserve
- // in our stack for setting up arguments for calls to other
- // routines. If this optional field is not set, LE will reserve
- // 128 bytes for the argument area. This optional field is
- // created if greater than 128 bytes is required - to guarantee
- // the required space is reserved on stack extension in the new
- // extension. This optional field is also created if the
- // routine has alloca(). This may reduce stack space
- // if alloca() call causes a stack extension.
- bool HasArgAreaLength = (Info.AllocaReg != 0) || (Info.CallFrameSize > 128);
-
- // Emit PPA1 section.
- OutStreamer->AddComment("PPA1");
- OutStreamer->emitLabel(Info.PPA1);
- 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(Info.SavedGPRMask);
- OutStreamer->AddComment("Offset to PPA2");
- OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, Info.PPA1, 4);
-
- emitPPA1Flags(OutStreamer, Info.IsVarArg, Info.HasStackProtector,
- Info.SavedFPRMask != 0, Info.SavedVRMask != 0,
- Info.PersonalityRoutine != nullptr, HasArgAreaLength,
- Info.Name.size() > 0);
-
- OutStreamer->AddComment("Length/4 of Parms");
- OutStreamer->emitInt16(
- static_cast<uint16_t>(Info.SizeOfFnParams / 4)); // Parms/4.
-
- OutStreamer->AddComment("Length/2 of Prolog ");
- if (Info.EndOfProlog)
- OutStreamer->emitValue(getTargetStreamer()->createWordDiffExpr(
- OutContext, Info.EndOfProlog, Info.Fn),
- 1);
- else
- OutStreamer->emitInt8(0);
-
- OutStreamer->AddComment("Alloca Reg + Offset/2 to SP Update");
- OutStreamer->AddComment(
- Twine(" Bit 0-3: Register R").concat(utostr(Info.AllocaReg)).str());
- OutStreamer->AddComment(" Bit 4-8: Offset ");
- const MCExpr *AllocaRegExpr =
- MCConstantExpr::create(Info.AllocaReg << 4, OutContext);
- if (Info.StackUpdate)
- OutStreamer->emitValue(
- MCBinaryExpr::createOr(getTargetStreamer()->createWordDiffExpr(
- OutContext, Info.StackUpdate, Info.Fn),
- AllocaRegExpr, OutContext),
- 1);
- else
- OutStreamer->emitValue(AllocaRegExpr, 1);
-
- OutStreamer->AddComment("Length of Code");
- OutStreamer->emitAbsoluteSymbolDiff(Info.FnEnd, Info.EPMarker, 4);
-
- if (HasArgAreaLength) {
- OutStreamer->AddComment("Argument Area Length");
- OutStreamer->emitInt32(Info.CallFrameSize);
- }
-
- // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
- if (Info.SavedFPRMask) {
- OutStreamer->AddComment("FPR mask");
- OutStreamer->emitInt16(Info.SavedFPRMask);
- OutStreamer->AddComment("AR mask");
- OutStreamer->emitInt16(0); // AR Mask, unused currently.
- OutStreamer->AddComment("FPR Save Area Locator");
- uint64_t FPRSaveAreaOffset = Info.OffsetFPR;
- assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
- FPRSaveAreaOffset &= 0x0FFFFFFF; // Lose top 4 bits.
- OutStreamer->AddComment(
- Twine(" Bit 0-3: Register R").concat(utostr(Info.FrameReg)));
- OutStreamer->AddComment(
- Twine(" Bit 4-31: Offset ").concat(utostr(FPRSaveAreaOffset)));
- OutStreamer->emitInt32(FPRSaveAreaOffset |
- (Info.FrameReg << 28)); // Offset to FPR save area
- // with register to add
- // value to (alloca reg).
- }
-
- // Emit saved VR mask to VR save area.
- if (Info.SavedVRMask) {
- OutStreamer->AddComment("VR mask");
- OutStreamer->emitInt8(Info.SavedVRMask);
- OutStreamer->emitInt8(0); // Reserved.
- OutStreamer->emitInt16(0); // Also reserved.
- uint64_t VRSaveAreaOffset = Info.OffsetVR;
- assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
- VRSaveAreaOffset &= 0x0FFFFFFF; // Lose top 4 bits.
- OutStreamer->AddComment("VR Save Area Locator");
- OutStreamer->AddComment(
- Twine(" Bit 0-3: Register R").concat(utostr(Info.FrameReg)));
- OutStreamer->AddComment(
- Twine(" Bit 4-31: Offset ").concat(utostr(VRSaveAreaOffset)));
- OutStreamer->emitInt32(VRSaveAreaOffset | (Info.FrameReg << 28));
- }
-
- // Emit C++ EH information block.
- if (Info.PersonalityRoutine) {
- OutStreamer->AddComment("Version");
- OutStreamer->emitInt32(1);
- OutStreamer->AddComment("Flags");
- OutStreamer->emitInt32(0); // LSDA field is a WAS offset
- OutStreamer->AddComment("Personality routine");
- OutStreamer->emitInt64(ADATable.insert(
- Info.PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC));
- OutStreamer->AddComment("LSDA location");
- OutStreamer->emitInt64(
- ADATable.insert(Info.GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR));
- }
-
- // Emit name length and name optional section (0x01 of flags 4)
- if (Info.Name.size())
- emitPPA1Name(OutStreamer, Info.Name);
-
- // Emit offset to entry point optional section (0x80 of flags 4).
- OutStreamer->emitAbsoluteSymbolDiff(Info.EPMarker, Info.PPA1, 4);
-}
-
// Determine the end of the prolog and the instructions which updates the stack
// register, and attach symbols to those instructions.
static void determinePrologueStackUpdateSym(MachineFunction *MF,
@@ -1781,9 +1537,10 @@ static void determinePrologueStackUpdateSym(MachineFunction *MF,
}
void SystemZAsmPrinter::calculatePPA1() {
- assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
+ auto *ZOS = static_cast<SystemZzOSStreamer *>(getTargetStreamer());
+ assert(ZOS->PPA2Sym != nullptr && "PPA2 Symbol not defined");
- PPA1Info Info;
+ SystemZzOSStreamer::PPA1Info Info;
const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
@@ -1845,6 +1602,8 @@ void SystemZAsmPrinter::calculatePPA1() {
MCSymbol *PersonalityRoutine = nullptr;
MCSymbol *GCCEH = nullptr;
+ uint64_t PersonalityADADisp = 0;
+ uint64_t GCCEHADADisp = 0;
if (!MF->getLandingPads().empty()) {
const Function *Per = dyn_cast<Function>(
MF->getFunction().getPersonalityFn()->stripPointerCasts());
@@ -1853,6 +1612,10 @@ void SystemZAsmPrinter::calculatePPA1() {
GCCEH = MF->getContext().getOrCreateSymbol(Twine("GCC_except_table") +
Twine(MF->getFunctionNumber()));
+ PersonalityADADisp =
+ ADATable.insert(PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC);
+ GCCEHADADisp =
+ ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR);
}
// Get the name of the function, with suffix _.
@@ -1876,6 +1639,8 @@ void SystemZAsmPrinter::calculatePPA1() {
Info.StackUpdate = StackUpdateSym;
Info.PersonalityRoutine = PersonalityRoutine;
Info.GCCEH = GCCEH;
+ Info.PersonalityADADisp = PersonalityADADisp;
+ Info.GCCEHADADisp = GCCEHADADisp;
Info.OffsetFPR = OffsetFPR;
Info.OffsetVR = OffsetVR;
Info.CallFrameSize = MFFrame.getMaxCallFrameSize();
@@ -1888,7 +1653,7 @@ void SystemZAsmPrinter::calculatePPA1() {
Info.IsVarArg = MF->getFunction().isVarArg();
Info.HasStackProtector = MFFrame.hasStackProtectorIndex();
- DeferredPPA1.push_back(Info);
+ ZOS->DeferredPPA1.push_back(Info);
}
void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
@@ -1898,6 +1663,7 @@ void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
}
void SystemZAsmPrinter::emitPPA2(Module &M) {
+ auto *ZOS = static_cast<SystemZzOSStreamer *>(getTargetStreamer());
OutStreamer->pushSection();
OutStreamer->switchSection(getObjFileLowering().getTextSection());
MCContext &OutContext = OutStreamer->getContext();
@@ -1907,8 +1673,9 @@ void SystemZAsmPrinter::emitPPA2(Module &M) {
OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_OSLinkage);
OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Global);
- // Create symbol and assign to class field for use in PPA1.
- PPA2Sym = OutContext.createTempSymbol("PPA2", false);
+ // Create symbol and assign to streamer field for use in PPA1.
+ ZOS->PPA2Sym = OutContext.createTempSymbol("PPA2", false);
+ MCSymbol *PPA2Sym = ZOS->PPA2Sym;
MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false);
std::time_t Time = getTranslationTime(M);
@@ -2066,6 +1833,8 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
if (Subtarget.getTargetTriple().isOSzOS()) {
calculatePPA1();
+ auto &DeferredPPA1 =
+ static_cast<SystemZzOSStreamer *>(getTargetStreamer())->DeferredPPA1;
// EntryPoint Marker
const MachineFrameInfo &MFFrame = MF->getFrameInfo();
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
index a2234314df750..20aafa4c7c96c 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
@@ -29,8 +29,6 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
static char ID;
private:
- MCSymbol *PPA2Sym;
-
SystemZTargetStreamer *getTargetStreamer() {
MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
assert(TS && "do not have a target streamer");
@@ -98,42 +96,14 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>
GOAliasMap;
- struct PPA1Info {
- StringRef Name;
- MCSymbol *Fn = nullptr; // Symbol marking function begin.
- MCSymbol *FnEnd = nullptr; // Symbol marking function end.
- MCSymbol *PPA1 = nullptr; // Symbol marking PPA1 begin.
- MCSymbol *EPMarker = nullptr; // Symbol marking entry point.
- MCSymbol *EndOfProlog = nullptr; // Symbol marking the end of the prolog.
- MCSymbol *StackUpdate = nullptr; // Symbol marking the stack updating instr.
- MCSymbol *PersonalityRoutine = nullptr;
- MCSymbol *GCCEH = nullptr;
- int64_t OffsetFPR = 0;
- int64_t OffsetVR = 0;
- uint64_t CallFrameSize = 0;
- unsigned SizeOfFnParams = 0;
- uint32_t FrameAndFPROffset;
- uint32_t FrameAndVROffset;
- uint16_t SavedGPRMask = 0;
- uint16_t SavedFPRMask = 0;
- uint8_t SavedVRMask = 0;
- uint8_t FrameReg = 0;
- uint8_t AllocaReg = 0;
- bool IsVarArg = false;
- bool HasStackProtector = false;
- };
- SmallVector<PPA1Info, 0> DeferredPPA1;
-
void calculatePPA1();
- void emitPPA1(PPA1Info &Info);
void emitPPA2(Module &M);
void emitADASection();
void emitIDRLSection(Module &M);
public:
SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
- : AsmPrinter(TM, std::move(Streamer), ID), PPA2Sym(nullptr),
- ADATable(TM.getPointerSize(0)) {}
+ : AsmPrinter(TM, std::move(Streamer), ID), ADATable(TM.getPointerSize(0)) {}
// Override AsmPrinter.
StringRef getPassName() const override { return "SystemZ Assembly Printer"; }
diff --git a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
index 5c0f1f1d09033..3253376645eaa 100644
--- a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
@@ -42,6 +42,6 @@ lpad:
; CHECK: * Bit 7: 1 = Name Length and Name
; CHECK: DC XL1'91'
; CHECK: * Personality routine
-; CHECK: DC XL8'0000000000000020'
+; CHECK: DC XL8'0000000000000000'
; CHECK: * LSDA location
-; CHECK: DC XL8'0000000000000028'
+; CHECK: DC XL8'0000000000000008'
>From dcc5148aaaa0239b5950fec013318239ba23e4d9 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Thu, 9 Jul 2026 16:02:36 -0400
Subject: [PATCH 2/3] Fix formatting
---
.../Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp | 6 +++---
.../Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h | 2 +-
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 7 +++----
llvm/lib/Target/SystemZ/SystemZAsmPrinter.h | 3 ++-
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
index 95f43a6bc76e4..db80b3c4094bd 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
@@ -237,9 +237,9 @@ void SystemZzOSStreamer::emitPPA1(PPA1Info &Info) {
OutStreamer.AddComment(
Twine(" Bit 4-31: Offset ").concat(utostr(FPRSaveAreaOffset)));
OutStreamer.emitInt32(FPRSaveAreaOffset |
- (Info.FrameReg << 28)); // Offset to FPR save area
- // with register to add
- // value to (alloca reg).
+ (Info.FrameReg << 28)); // Offset to FPR save area
+ // with register to add
+ // value to (alloca reg).
}
// Emit saved VR mask to VR save area.
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
index 769fac11c25ca..bccb3179de151 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
@@ -88,7 +88,7 @@ class SystemZzOSStreamer : public SystemZTargetStreamer {
int64_t OffsetFPR = 0;
int64_t OffsetVR = 0;
uint64_t CallFrameSize = 0;
- uint64_t PersonalityADADisp = 0; // ADA displacement for personality routine.
+ uint64_t PersonalityADADisp = 0; // ADA displacement for personality func.
uint64_t GCCEHADADisp = 0; // ADA displacement for GCCEH symbol.
unsigned SizeOfFnParams = 0;
uint32_t FrameAndFPROffset;
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index a00d845c158ae..5245892437d4a 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1612,10 +1612,9 @@ void SystemZAsmPrinter::calculatePPA1() {
GCCEH = MF->getContext().getOrCreateSymbol(Twine("GCC_except_table") +
Twine(MF->getFunctionNumber()));
- PersonalityADADisp =
- ADATable.insert(PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC);
- GCCEHADADisp =
- ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR);
+ PersonalityADADisp = ADATable.insert(PersonalityRoutine,
+ SystemZII::MO_ADA_INDIRECT_FUNC_DESC);
+ GCCEHADADisp = ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR);
}
// Get the name of the function, with suffix _.
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
index 20aafa4c7c96c..fa111fa43eed7 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
@@ -103,7 +103,8 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
public:
SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
- : AsmPrinter(TM, std::move(Streamer), ID), ADATable(TM.getPointerSize(0)) {}
+ : AsmPrinter(TM, std::move(Streamer), ID),
+ ADATable(TM.getPointerSize(0)) {}
// Override AsmPrinter.
StringRef getPassName() const override { return "SystemZ Assembly Printer"; }
>From fca014471a21b0ef9149f34d5f6ee064c14ef920 Mon Sep 17 00:00:00 2001
From: Kai Nacke <kai.peter.nacke at ibm.com>
Date: Mon, 13 Jul 2026 10:02:53 -0400
Subject: [PATCH 3/3] Address all code-related review comments
---
.../MCTargetDesc/SystemZTargetStreamer.cpp | 17 +++++----
.../MCTargetDesc/SystemZTargetStreamer.h | 35 +++++++------------
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 29 +++++++--------
3 files changed, 36 insertions(+), 45 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
index db80b3c4094bd..aea1c61fabf07 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.cpp
@@ -154,7 +154,7 @@ static void emitPPA1Name(MCStreamer &OutStreamer, StringRef OutName) {
OutStreamer.emitZeros(ExtraZeros);
}
-void SystemZzOSStreamer::emitPPA1(PPA1Info &Info) {
+void SystemZTargetzOSStreamer::emitPPA1(PPA1Info &Info) {
assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
MCStreamer &OutStreamer = getStreamer();
MCContext &OutContext = OutStreamer.getContext();
@@ -171,6 +171,10 @@ void SystemZzOSStreamer::emitPPA1(PPA1Info &Info) {
// if alloca() call causes a stack extension.
bool HasArgAreaLength = (Info.AllocaReg != 0) || (Info.CallFrameSize > 128);
+ // The personality function is present if at least one of the displacements is
+ // larger than zero.
+ bool HasPersonalityFn = Info.PersonalityADADisp > 0 || Info.GCCEHADADisp > 0;
+
// Emit PPA1 section.
OutStreamer.AddComment("PPA1");
OutStreamer.emitLabel(Info.PPA1);
@@ -184,9 +188,8 @@ void SystemZzOSStreamer::emitPPA1(PPA1Info &Info) {
OutStreamer.emitAbsoluteSymbolDiff(PPA2Sym, Info.PPA1, 4);
emitPPA1Flags(OutStreamer, Info.IsVarArg, Info.HasStackProtector,
- Info.SavedFPRMask != 0, Info.SavedVRMask != 0,
- Info.PersonalityRoutine != nullptr, HasArgAreaLength,
- Info.Name.size() > 0);
+ Info.SavedFPRMask != 0, Info.SavedVRMask != 0, HasPersonalityFn,
+ HasArgAreaLength, Info.Name.size() > 0);
OutStreamer.AddComment("Length/4 of Parms");
OutStreamer.emitInt16(
@@ -260,7 +263,7 @@ void SystemZzOSStreamer::emitPPA1(PPA1Info &Info) {
}
// Emit C++ EH information block.
- if (Info.PersonalityRoutine) {
+ if (HasPersonalityFn) {
OutStreamer.AddComment("Version");
OutStreamer.emitInt32(1);
OutStreamer.AddComment("Flags");
@@ -272,14 +275,14 @@ void SystemZzOSStreamer::emitPPA1(PPA1Info &Info) {
}
// Emit name length and name optional section (0x01 of flags 4)
- if (Info.Name.size())
+ if (Info.Name.size() > 0)
emitPPA1Name(OutStreamer, Info.Name);
// Emit offset to entry point optional section (0x80 of flags 4).
OutStreamer.emitAbsoluteSymbolDiff(Info.EPMarker, Info.PPA1, 4);
}
-void SystemZzOSStreamer::emitConstantPools() {
+void SystemZTargetzOSStreamer::emitConstantPools() {
// Emit EXRL target instructions (base class prolog).
SystemZTargetStreamer::emitConstantPools();
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
index bccb3179de151..cea56b95fb7af 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZTargetStreamer.h
@@ -60,19 +60,9 @@ class SystemZTargetStreamer : public MCTargetStreamer {
void emitConstantPools() override;
virtual void emitMachine(StringRef CPUOrCommand) {};
-
- virtual void emitExternalName(MCSymbol *Sym, StringRef Name) {}
- virtual void emitExternalName(MCSection *Sec, StringRef Name) {}
-
- virtual const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
- const MCSymbol *Lo) {
- return nullptr;
- }
-
- virtual void emitADA(MCSymbol *Sym, MCSection *Section) {}
};
-class SystemZzOSStreamer : public SystemZTargetStreamer {
+class SystemZTargetzOSStreamer : public SystemZTargetStreamer {
public:
/// Information about a single function needed to emit a PPA1 block.
struct PPA1Info {
@@ -83,8 +73,6 @@ class SystemZzOSStreamer : public SystemZTargetStreamer {
MCSymbol *EPMarker = nullptr; // Symbol marking entry point.
MCSymbol *EndOfProlog = nullptr; // Symbol marking the end of the prolog.
MCSymbol *StackUpdate = nullptr; // Symbol marking the stack updating instr.
- MCSymbol *PersonalityRoutine = nullptr;
- MCSymbol *GCCEH = nullptr;
int64_t OffsetFPR = 0;
int64_t OffsetVR = 0;
uint64_t CallFrameSize = 0;
@@ -106,36 +94,39 @@ class SystemZzOSStreamer : public SystemZTargetStreamer {
MCSymbol *PPA2Sym = nullptr;
- SystemZzOSStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {}
+ SystemZTargetzOSStreamer(MCStreamer &S) : SystemZTargetStreamer(S) {}
- virtual void emitExternalName(MCSymbol *Sym, StringRef Name) override {
+ void emitConstantPools() override;
+
+ void emitExternalName(MCSymbol *Sym, StringRef Name) {
static_cast<MCSymbolGOFF *>(Sym)->setExternalName(Name);
}
- virtual void emitExternalName(MCSection *Sec, StringRef Name) override {
+ void emitExternalName(MCSection *Sec, StringRef Name) {
static_cast<MCSectionGOFF *>(Sec)->setExternalName(Name);
}
- void emitADA(MCSymbol *Sym, MCSection *Section) override {
+ void emitADA(MCSymbol *Sym, MCSection *Section) {
static_cast<MCSymbolGOFF *>(Sym)->setADA(
static_cast<MCSectionGOFF *>(Section));
}
- void emitConstantPools() override;
void emitPPA1(PPA1Info &Info);
+ virtual const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
+ const MCSymbol *Lo) = 0;
};
-class SystemZTargetGOFFStreamer : public SystemZzOSStreamer {
+class SystemZTargetGOFFStreamer : public SystemZTargetzOSStreamer {
public:
- SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZzOSStreamer(S) {}
+ SystemZTargetGOFFStreamer(MCStreamer &S) : SystemZTargetzOSStreamer(S) {}
const MCExpr *createWordDiffExpr(MCContext &Ctx, const MCSymbol *Hi,
const MCSymbol *Lo) override;
};
-class SystemZTargetHLASMStreamer : public SystemZzOSStreamer {
+class SystemZTargetHLASMStreamer : public SystemZTargetzOSStreamer {
formatted_raw_ostream &OS;
public:
SystemZTargetHLASMStreamer(MCStreamer &S, formatted_raw_ostream &OS)
- : SystemZzOSStreamer(S), OS(OS) {}
+ : SystemZTargetzOSStreamer(S), OS(OS) {}
SystemZHLASMAsmStreamer &getHLASMStreamer();
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 5245892437d4a..0512e869fe407 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1296,6 +1296,7 @@ bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
auto TT = OutContext.getTargetTriple();
if (TT.isOSzOS()) {
+ auto *ZOS = static_cast<SystemZTargetzOSStreamer *>(getTargetStreamer());
emitADASection();
emitIDRLSection(M);
// On z/OS, we need to associate an external data reference with an ED
@@ -1306,8 +1307,7 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
if (auto *GV = dyn_cast<GlobalVariable>(&GO)) {
if (!GV->hasInitializer()) {
MCSymbol *Sym = getSymbol(GV);
- getTargetStreamer()->emitADA(
- Sym, OutContext.getObjectFileInfo()->getADASection());
+ ZOS->emitADA(Sym, OutContext.getObjectFileInfo()->getADASection());
OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeObject);
}
}
@@ -1322,6 +1322,7 @@ void SystemZAsmPrinter::emitADASection() {
const unsigned PointerSize = getDataLayout().getPointerSize();
OutStreamer->switchSection(getObjFileLowering().getADASection());
+ auto *ZOS = static_cast<SystemZTargetzOSStreamer *>(getTargetStreamer());
unsigned EmittedBytes = 0;
for (auto &Entry : ADATable.getTable()) {
const MCSymbol *Sym;
@@ -1367,7 +1368,7 @@ void SystemZAsmPrinter::emitADASection() {
OutStreamer->emitSymbolAttribute(Alias, MCSA_Extern);
MCSymbolGOFF *GOFFSym =
static_cast<llvm::MCSymbolGOFF *>(const_cast<llvm::MCSymbol *>(Sym));
- getTargetStreamer()->emitExternalName(Alias, GOFFSym->getExternalName());
+ ZOS->emitExternalName(Alias, GOFFSym->getExternalName());
EMIT_COMMENT("pointer to function descriptor");
OutStreamer->emitValue(
MCSpecifierExpr::create(MCSymbolRefExpr::create(Alias, OutContext),
@@ -1454,7 +1455,7 @@ 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.
- auto *ZOS = static_cast<SystemZzOSStreamer *>(getTargetStreamer());
+ auto *ZOS = static_cast<SystemZTargetzOSStreamer *>(getTargetStreamer());
OutStreamer->emitLabel(ZOS->DeferredPPA1.back().FnEnd);
}
}
@@ -1537,10 +1538,10 @@ static void determinePrologueStackUpdateSym(MachineFunction *MF,
}
void SystemZAsmPrinter::calculatePPA1() {
- auto *ZOS = static_cast<SystemZzOSStreamer *>(getTargetStreamer());
+ auto *ZOS = static_cast<SystemZTargetzOSStreamer *>(getTargetStreamer());
assert(ZOS->PPA2Sym != nullptr && "PPA2 Symbol not defined");
- SystemZzOSStreamer::PPA1Info Info;
+ SystemZTargetzOSStreamer::PPA1Info Info;
const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
@@ -1636,8 +1637,6 @@ void SystemZAsmPrinter::calculatePPA1() {
Info.Fn = CurrentFnSym;
Info.EndOfProlog = EndOfPrologSym;
Info.StackUpdate = StackUpdateSym;
- Info.PersonalityRoutine = PersonalityRoutine;
- Info.GCCEH = GCCEH;
Info.PersonalityADADisp = PersonalityADADisp;
Info.GCCEHADADisp = GCCEHADADisp;
Info.OffsetFPR = OffsetFPR;
@@ -1662,7 +1661,7 @@ void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
}
void SystemZAsmPrinter::emitPPA2(Module &M) {
- auto *ZOS = static_cast<SystemZzOSStreamer *>(getTargetStreamer());
+ auto *ZOS = static_cast<SystemZTargetzOSStreamer *>(getTargetStreamer());
OutStreamer->pushSection();
OutStreamer->switchSection(getObjFileLowering().getTextSection());
MCContext &OutContext = OutStreamer->getContext();
@@ -1831,9 +1830,8 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
if (Subtarget.getTargetTriple().isOSzOS()) {
+ auto *ZOS = static_cast<SystemZTargetzOSStreamer *>(getTargetStreamer());
calculatePPA1();
- auto &DeferredPPA1 =
- static_cast<SystemZzOSStreamer *>(getTargetStreamer())->DeferredPPA1;
// EntryPoint Marker
const MachineFrameInfo &MFFrame = MF->getFrameInfo();
@@ -1854,14 +1852,14 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
// Emit entry point marker section.
OutStreamer->AddComment("XPLINK Routine Layout Entry");
- OutStreamer->emitLabel(DeferredPPA1.back().EPMarker);
+ OutStreamer->emitLabel(ZOS->DeferredPPA1.back().EPMarker);
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(DeferredPPA1.back().PPA1,
- DeferredPPA1.back().EPMarker, 4);
+ OutStreamer->emitAbsoluteSymbolDiff(ZOS->DeferredPPA1.back().PPA1,
+ ZOS->DeferredPPA1.back().EPMarker, 4);
if (OutStreamer->isVerboseAsm()) {
OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
OutStreamer->AddComment("Entry Flags");
@@ -1876,8 +1874,7 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
}
OutStreamer->emitInt32(DSAAndFlags);
- getTargetStreamer()->emitADA(CurrentFnSym,
- getObjFileLowering().getADASection());
+ ZOS->emitADA(CurrentFnSym, getObjFileLowering().getADASection());
}
AsmPrinter::emitFunctionEntryLabel();
More information about the llvm-commits
mailing list