[llvm] [SystemZ][z/OS] Add exception handling for XPLINK (PR #74638)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 6 10:24:35 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mc
Author: Yusra Syeda (ysyeda)
<details>
<summary>Changes</summary>
Adds emitting the exception table and the EH registers for XPLINK.
---
Full diff: https://github.com/llvm/llvm-project/pull/74638.diff
14 Files Affected:
- (modified) llvm/include/llvm/CodeGen/CodeGenPassBuilder.h (+1)
- (modified) llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (+2)
- (modified) llvm/include/llvm/MC/MCAsmInfo.h (+2-1)
- (modified) llvm/include/llvm/MC/MCTargetOptions.h (+2)
- (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+1)
- (modified) llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (+7)
- (modified) llvm/lib/CodeGen/TargetPassConfig.cpp (+1)
- (modified) llvm/lib/MC/MCContext.cpp (+9-4)
- (modified) llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp (+1)
- (modified) llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (+32-2)
- (modified) llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp (+6)
- (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.cpp (+10)
- (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.h (+2-6)
- (added) llvm/test/CodeGen/SystemZ/zos-landingpad.ll (+41)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
index a8ab670ad77be..df506f6b446a4 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 9f92b919824d2..4a7c1ca4a5718 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 a3c9b19e859d9..56492368bd984 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 afb329eb6f935..e2dd1e0433dbe 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 3a679f1576b7b..b04de65b73344 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 143a4951c1361..edde36a087920 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 1f7c949cd6031..2b1708a9a7656 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 ba4e1c3c4107e..aa14110be210d 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 e61b07e973e93..66555fa06b068 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 3186002c57d98..2e453d6e1ec21 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 7522998fd06d8..db19c8881c685 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 873994c2e333b..b31aa5e0233d6 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 40fe433f816fa..5fbd1275daf58 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 0000000000000..481efb5935b36
--- /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:
``````````
</details>
https://github.com/llvm/llvm-project/pull/74638
More information about the llvm-commits
mailing list