[llvm] [SystemZ][z/OS] Add exception handling for XPLINK (PR #74638)
Yusra Syeda via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 18 11:48:36 PST 2023
https://github.com/ysyeda updated https://github.com/llvm/llvm-project/pull/74638
>From f205621233dfdfd198d2c7bc08610a2b7cae39c3 Mon Sep 17 00:00:00 2001
From: Yusra Syeda <yusra.syeda at ibm.com>
Date: Wed, 6 Dec 2023 13:13:05 -0500
Subject: [PATCH 1/2] add exception handling
---
.../include/llvm/CodeGen/CodeGenPassBuilder.h | 1 +
.../CodeGen/TargetLoweringObjectFileImpl.h | 2 +
llvm/include/llvm/MC/MCAsmInfo.h | 3 +-
llvm/include/llvm/MC/MCTargetOptions.h | 2 +
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 1 +
.../CodeGen/TargetLoweringObjectFileImpl.cpp | 7 ++++
llvm/lib/CodeGen/TargetPassConfig.cpp | 1 +
llvm/lib/MC/MCContext.cpp | 13 ++++--
.../SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp | 1 +
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 34 ++++++++++++++-
.../Target/SystemZ/SystemZFrameLowering.cpp | 6 +++
.../Target/SystemZ/SystemZISelLowering.cpp | 10 +++++
llvm/lib/Target/SystemZ/SystemZISelLowering.h | 8 +---
llvm/test/CodeGen/SystemZ/zos-landingpad.ll | 41 +++++++++++++++++++
14 files changed, 117 insertions(+), 13 deletions(-)
create mode 100644 llvm/test/CodeGen/SystemZ/zos-landingpad.ll
diff --git a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
index a8ab670ad77be3..df506f6b446a41 100644
--- a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
+++ b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
@@ -676,6 +676,7 @@ void CodeGenPassBuilder<Derived>::addPassesToHandleExceptions(
case ExceptionHandling::DwarfCFI:
case ExceptionHandling::ARM:
case ExceptionHandling::AIX:
+ case ExceptionHandling::ZOS:
addPass(DwarfEHPass(getOptLevel()));
break;
case ExceptionHandling::WinEH:
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 9f92b919824d2d..4a7c1ca4a57182 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -309,6 +309,8 @@ class TargetLoweringObjectFileGOFF : public TargetLoweringObjectFile {
const TargetMachine &TM) const override;
MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
const TargetMachine &TM) const override;
+ MCSection *getSectionForLSDA(const Function &F, const MCSymbol &FnSym,
+ const TargetMachine &TM) const override;
};
} // end namespace llvm
diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index a3c9b19e859d93..56492368bd984a 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -799,7 +799,8 @@ class MCAsmInfo {
/// frame information to unwind.
bool usesCFIForEH() const {
return (ExceptionsType == ExceptionHandling::DwarfCFI ||
- ExceptionsType == ExceptionHandling::ARM || usesWindowsCFI());
+ ExceptionsType == ExceptionHandling::ARM ||
+ ExceptionsType == ExceptionHandling::ZOS || usesWindowsCFI());
}
bool usesWindowsCFI() const {
diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h
index afb329eb6f935e..e2dd1e0433dbe4 100644
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -24,6 +24,8 @@ enum class ExceptionHandling {
WinEH, ///< Windows Exception Handling
Wasm, ///< WebAssembly Exception Handling
AIX, ///< AIX Exception Handling
+ ZOS, ///< z/OS MVS Exception Handling. Very similar to DwarfCFI, but the PPA1
+ ///< is used instead of an .eh_frame section.
};
enum class EmitDwarfUnwindType {
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 3a679f1576b7b6..b04de65b73344c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -582,6 +582,7 @@ bool AsmPrinter::doInitialization(Module &M) {
[[fallthrough]];
case ExceptionHandling::SjLj:
case ExceptionHandling::DwarfCFI:
+ case ExceptionHandling::ZOS:
ES = new DwarfCFIException(this);
break;
case ExceptionHandling::ARM:
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 143a4951c1361b..edde36a0879209 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2676,6 +2676,13 @@ MCSection *TargetLoweringObjectFileGOFF::getExplicitSectionGlobal(
return SelectSectionForGlobal(GO, Kind, TM);
}
+MCSection *TargetLoweringObjectFileGOFF::getSectionForLSDA(
+ const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const {
+ std::string Name = ".gcc_exception_table." + F.getName().str();
+ return getContext().getGOFFSection(Name, SectionKind::getData(), nullptr,
+ nullptr);
+}
+
MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
auto *Symbol = TM.getSymbol(GO);
diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp
index 1f7c949cd6031b..2b1708a9a76560 100644
--- a/llvm/lib/CodeGen/TargetPassConfig.cpp
+++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -939,6 +939,7 @@ void TargetPassConfig::addPassesToHandleExceptions() {
case ExceptionHandling::DwarfCFI:
case ExceptionHandling::ARM:
case ExceptionHandling::AIX:
+ case ExceptionHandling::ZOS:
addPass(createDwarfEHPass(getOptLevel()));
break;
case ExceptionHandling::WinEH:
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index ba4e1c3c4107ea..aa14110be210d6 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -650,10 +650,15 @@ 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, Parent, SubsectionId);
+ auto IterBool = GOFFUniquingMap.insert(std::make_pair(Section.str(), nullptr));
+ auto Iter = IterBool.first;
+ if (!IterBool.second)
+ return Iter->second;
+
+ StringRef CachedName = Iter->first;
+ MCSectionGOFF *GOFFSection = new (GOFFAllocator.Allocate())
+ MCSectionGOFF(CachedName, Kind, Parent, SubsectionId);
+ Iter->second = GOFFSection;
return GOFFSection;
}
diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp
index e61b07e973e930..66555fa06b0688 100644
--- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp
+++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp
@@ -38,6 +38,7 @@ SystemZMCAsmInfoGOFF::SystemZMCAsmInfoGOFF(const Triple &TT) {
DotIsPC = false;
EmitGNUAsmStartIndentationMarker = false;
EmitLabelsInUpperCase = true;
+ ExceptionsType = ExceptionHandling::ZOS;
IsLittleEndian = false;
MaxInstLength = 6;
RestrictCommentStringToStartOfStatement = true;
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 3186002c57d98a..2e453d6e1ec219 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1115,7 +1115,7 @@ void SystemZAsmPrinter::emitFunctionBodyEnd() {
static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
bool StackProtector, bool FPRMask, bool VRMask,
- bool HasName) {
+ bool EHBlock, bool HasName) {
enum class PPA1Flag1 : uint8_t {
DSA64Bit = (0x80 >> 0),
VarArg = (0x80 >> 7),
@@ -1133,6 +1133,7 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
enum class PPA1Flag4 : uint8_t {
EPMOffsetPresent = (0x80 >> 0),
VRMask = (0x80 >> 2),
+ EHBlock = (0x80 >> 3),
ProcedureNamePresent = (0x80 >> 7),
LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
};
@@ -1158,6 +1159,9 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
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.
@@ -1188,6 +1192,8 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
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");
@@ -1314,12 +1320,14 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
OutStreamer->AddComment("Offset to PPA2");
OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4);
+ bool NeedEmitEHBlock = !MF->getLandingPads().empty();
+
bool HasName =
MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
- TargetHasVector && SavedVRMask != 0, HasName);
+ TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock, HasName);
OutStreamer->AddComment("Length/4 of Parms");
OutStreamer->emitInt16(
@@ -1361,6 +1369,28 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
OutStreamer->emitInt32(FrameAndVROffset);
}
+ // Emit C++ EH information block
+ const Function *Per = nullptr;
+ if (NeedEmitEHBlock) {
+ Per = dyn_cast<Function>(
+ MF->getFunction().getPersonalityFn()->stripPointerCasts());
+ MCSymbol *PersonalityRoutine = Per ? MF->getTarget().getSymbol(Per) : nullptr;
+ assert(PersonalityRoutine && "Missing personality routine");
+
+ 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(
+ PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC));
+ OutStreamer->AddComment("LSDA location");
+ MCSymbol *GCCEH = MF->getContext().getOrCreateSymbol(
+ Twine("GCC_except_table") + Twine(MF->getFunctionNumber()));
+ OutStreamer->emitInt64(
+ ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR));
+ }
+
// Emit name length and name optional section (0x01 of flags 4)
if (HasName)
emitPPA1Name(OutStreamer, MF->getFunction().getName());
diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
index 7522998fd06d8e..db19c8881c685a 100644
--- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
@@ -17,6 +17,7 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/IR/Function.h"
#include "llvm/Target/TargetMachine.h"
@@ -994,6 +995,11 @@ bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots(
if (hasFP(MF) || Subtarget.hasBackChain())
CSI.push_back(CalleeSavedInfo(Regs.getStackPointerRegister()));
+ // If this function has an associated personality function then the
+ // environment register R5 must be saved in the DSA.
+ if (!MF.getLandingPads().empty())
+ CSI.push_back(CalleeSavedInfo(Regs.getADARegister()));
+
// Scan the call-saved GPRs and find the bounds of the register spill area.
Register LowRestoreGPR = 0;
int LowRestoreOffset = INT32_MAX;
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 873994c2e333bf..b31aa5e0233d60 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -1311,6 +1311,16 @@ SystemZTargetLowering::getRegisterByName(const char *RegName, LLT VT,
report_fatal_error("Invalid register name global variable");
}
+Register SystemZTargetLowering::getExceptionPointerRegister(
+ const Constant *PersonalityFn) const {
+ return Subtarget.isTargetXPLINK64() ? SystemZ::R1D : SystemZ::R6D;
+}
+
+Register SystemZTargetLowering::getExceptionSelectorRegister(
+ const Constant *PersonalityFn) const {
+ return Subtarget.isTargetXPLINK64() ? SystemZ::R2D : SystemZ::R7D;
+}
+
void SystemZTargetLowering::LowerAsmOperandForConstraint(
SDValue Op, StringRef Constraint, std::vector<SDValue> &Ops,
SelectionDAG &DAG) const {
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 40fe433f816fa6..5fbd1275daf58d 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -534,16 +534,12 @@ class SystemZTargetLowering : public TargetLowering {
/// If a physical register, this returns the register that receives the
/// exception address on entry to an EH pad.
Register
- getExceptionPointerRegister(const Constant *PersonalityFn) const override {
- return SystemZ::R6D;
- }
+ getExceptionPointerRegister(const Constant *PersonalityFn) const override;
/// If a physical register, this returns the register that receives the
/// exception typeid on entry to a landing pad.
Register
- getExceptionSelectorRegister(const Constant *PersonalityFn) const override {
- return SystemZ::R7D;
- }
+ getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
/// Override to support customized stack guard loading.
bool useLoadStackGuardNode() const override {
diff --git a/llvm/test/CodeGen/SystemZ/zos-landingpad.ll b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
new file mode 100644
index 00000000000000..481efb5935b36e
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/zos-landingpad.ll
@@ -0,0 +1,41 @@
+; RUN: llc < %s -mtriple=s390x-none-zos -mcpu=z10 | FileCheck %s
+;
+; Ensures that landingpad instructions use the right Exception Pointer
+; and Exception Selector registers, and that the exception table is emitted.
+
+declare void @callee()
+declare void @passeh(i8*, i32) noreturn
+declare i32 @__zos_cxx_personality_v2(...)
+
+define void @test1() uwtable personality i32 (...)* @__zos_cxx_personality_v2 {
+entry:
+ %ehptr = alloca i8*, align 8
+ %ehsel = alloca i32, align 8
+ invoke void @callee() to label %done unwind label %lpad
+done:
+ ret void
+; Match the return instruction.
+; CHECK: b 2(7)
+lpad:
+ %0 = landingpad { i8*, i32 } cleanup
+; The Exception Pointer is %r1; the Exception Selector, %r2.
+; CHECK: @BB{{[^%]*}} %lpad
+; CHECK-DAG: stg 1, {{.*}}
+; CHECK-DAG: st 2, {{.*}}
+ %1 = extractvalue { i8*, i32 } %0, 0
+ %2 = extractvalue { i8*, i32 } %0, 1
+ store i8* %1, i8** %ehptr, align 8
+ store i32 %2, i32* %ehsel, align 8
+ call void @passeh(i8* %1, i32 %2)
+ unreachable
+}
+
+; Check that offsets to the FD of the personality routine and LSDA are emitted in PPA1
+; CHECK: .byte 145 {{.*PPA1 Flags}}
+; CHECK: Bit 3: 1 = C++ EH block
+; TODO: Emit the value instead of a dummy value.
+; CHECK: Personality routine
+; CHECK: LSDA location
+; Check that the exception table is emitted into .lsda section.
+; CHECK: .section ".gcc_exception_table.test1"
+; CHECK: GCC_except_table0:
>From e10b8325a3071dfef7e3c7091636528a964bfd1d Mon Sep 17 00:00:00 2001
From: Yusra Syeda <yusra.syeda at ibm.com>
Date: Mon, 18 Dec 2023 14:48:22 -0500
Subject: [PATCH 2/2] fix formatting
---
llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 2 +-
llvm/lib/MC/MCContext.cpp | 3 ++-
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 3 ++-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index edde36a0879209..2df134428dbc6d 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2680,7 +2680,7 @@ MCSection *TargetLoweringObjectFileGOFF::getSectionForLSDA(
const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const {
std::string Name = ".gcc_exception_table." + F.getName().str();
return getContext().getGOFFSection(Name, SectionKind::getData(), nullptr,
- nullptr);
+ nullptr);
}
MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index aa14110be210d6..9c06658007c523 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -650,7 +650,8 @@ 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 IterBool = GOFFUniquingMap.insert(std::make_pair(Section.str(), nullptr));
+ auto IterBool =
+ GOFFUniquingMap.insert(std::make_pair(Section.str(), nullptr));
auto Iter = IterBool.first;
if (!IterBool.second)
return Iter->second;
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 2e453d6e1ec219..243461c0316e53 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1374,7 +1374,8 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
if (NeedEmitEHBlock) {
Per = dyn_cast<Function>(
MF->getFunction().getPersonalityFn()->stripPointerCasts());
- MCSymbol *PersonalityRoutine = Per ? MF->getTarget().getSymbol(Per) : nullptr;
+ MCSymbol *PersonalityRoutine =
+ Per ? MF->getTarget().getSymbol(Per) : nullptr;
assert(PersonalityRoutine && "Missing personality routine");
OutStreamer->AddComment("Version");
More information about the llvm-commits
mailing list