Skip to content

Commit 0768253

Browse files
ysyedaYusra Syeda
andauthored
[SystemZ][z/OS] Add exception handling for XPLINK (#74638)
Adds emitting the exception table and the EH registers for XPLINK. --------- Co-authored-by: Yusra Syeda <[email protected]>
1 parent c88e74c commit 0768253

14 files changed

+119
-13
lines changed

llvm/include/llvm/CodeGen/CodeGenPassBuilder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,7 @@ void CodeGenPassBuilder<Derived>::addPassesToHandleExceptions(
695695
case ExceptionHandling::DwarfCFI:
696696
case ExceptionHandling::ARM:
697697
case ExceptionHandling::AIX:
698+
case ExceptionHandling::ZOS:
698699
addPass(DwarfEHPreparePass(&TM));
699700
break;
700701
case ExceptionHandling::WinEH:

llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ class TargetLoweringObjectFileGOFF : public TargetLoweringObjectFile {
309309
const TargetMachine &TM) const override;
310310
MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
311311
const TargetMachine &TM) const override;
312+
MCSection *getSectionForLSDA(const Function &F, const MCSymbol &FnSym,
313+
const TargetMachine &TM) const override;
312314
};
313315

314316
} // end namespace llvm

llvm/include/llvm/MC/MCAsmInfo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,8 @@ class MCAsmInfo {
799799
/// frame information to unwind.
800800
bool usesCFIForEH() const {
801801
return (ExceptionsType == ExceptionHandling::DwarfCFI ||
802-
ExceptionsType == ExceptionHandling::ARM || usesWindowsCFI());
802+
ExceptionsType == ExceptionHandling::ARM ||
803+
ExceptionsType == ExceptionHandling::ZOS || usesWindowsCFI());
803804
}
804805

805806
bool usesWindowsCFI() const {

llvm/include/llvm/MC/MCTargetOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ enum class ExceptionHandling {
2424
WinEH, ///< Windows Exception Handling
2525
Wasm, ///< WebAssembly Exception Handling
2626
AIX, ///< AIX Exception Handling
27+
ZOS, ///< z/OS MVS Exception Handling. Very similar to DwarfCFI, but the PPA1
28+
///< is used instead of an .eh_frame section.
2729
};
2830

2931
enum class EmitDwarfUnwindType {

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,7 @@ bool AsmPrinter::doInitialization(Module &M) {
583583
[[fallthrough]];
584584
case ExceptionHandling::SjLj:
585585
case ExceptionHandling::DwarfCFI:
586+
case ExceptionHandling::ZOS:
586587
ES = new DwarfCFIException(this);
587588
break;
588589
case ExceptionHandling::ARM:

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2681,6 +2681,13 @@ MCSection *TargetLoweringObjectFileGOFF::getExplicitSectionGlobal(
26812681
return SelectSectionForGlobal(GO, Kind, TM);
26822682
}
26832683

2684+
MCSection *TargetLoweringObjectFileGOFF::getSectionForLSDA(
2685+
const Function &F, const MCSymbol &FnSym, const TargetMachine &TM) const {
2686+
std::string Name = ".gcc_exception_table." + F.getName().str();
2687+
return getContext().getGOFFSection(Name, SectionKind::getData(), nullptr,
2688+
nullptr);
2689+
}
2690+
26842691
MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
26852692
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
26862693
auto *Symbol = TM.getSymbol(GO);

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,7 @@ void TargetPassConfig::addPassesToHandleExceptions() {
947947
case ExceptionHandling::DwarfCFI:
948948
case ExceptionHandling::ARM:
949949
case ExceptionHandling::AIX:
950+
case ExceptionHandling::ZOS:
950951
addPass(createDwarfEHPass(getOptLevel()));
951952
break;
952953
case ExceptionHandling::WinEH:

llvm/lib/MC/MCContext.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -650,10 +650,16 @@ MCSectionGOFF *MCContext::getGOFFSection(StringRef Section, SectionKind Kind,
650650
MCSection *Parent,
651651
const MCExpr *SubsectionId) {
652652
// Do the lookup. If we don't have a hit, return a new section.
653-
auto &GOFFSection = GOFFUniquingMap[Section.str()];
654-
if (!GOFFSection)
655-
GOFFSection = new (GOFFAllocator.Allocate())
656-
MCSectionGOFF(Section, Kind, Parent, SubsectionId);
653+
auto IterBool =
654+
GOFFUniquingMap.insert(std::make_pair(Section.str(), nullptr));
655+
auto Iter = IterBool.first;
656+
if (!IterBool.second)
657+
return Iter->second;
658+
659+
StringRef CachedName = Iter->first;
660+
MCSectionGOFF *GOFFSection = new (GOFFAllocator.Allocate())
661+
MCSectionGOFF(CachedName, Kind, Parent, SubsectionId);
662+
Iter->second = GOFFSection;
657663

658664
return GOFFSection;
659665
}

llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ SystemZMCAsmInfoGOFF::SystemZMCAsmInfoGOFF(const Triple &TT) {
3838
DotIsPC = false;
3939
EmitGNUAsmStartIndentationMarker = false;
4040
EmitLabelsInUpperCase = true;
41+
ExceptionsType = ExceptionHandling::ZOS;
4142
IsLittleEndian = false;
4243
MaxInstLength = 6;
4344
RestrictCommentStringToStartOfStatement = true;

llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,7 @@ void SystemZAsmPrinter::emitFunctionBodyEnd() {
11151115

11161116
static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
11171117
bool StackProtector, bool FPRMask, bool VRMask,
1118-
bool HasName) {
1118+
bool EHBlock, bool HasName) {
11191119
enum class PPA1Flag1 : uint8_t {
11201120
DSA64Bit = (0x80 >> 0),
11211121
VarArg = (0x80 >> 7),
@@ -1133,6 +1133,7 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
11331133
enum class PPA1Flag4 : uint8_t {
11341134
EPMOffsetPresent = (0x80 >> 0),
11351135
VRMask = (0x80 >> 2),
1136+
EHBlock = (0x80 >> 3),
11361137
ProcedureNamePresent = (0x80 >> 7),
11371138
LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
11381139
};
@@ -1158,6 +1159,9 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
11581159
if (VRMask)
11591160
Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
11601161

1162+
if (EHBlock)
1163+
Flags4 |= PPA1Flag4::EHBlock; // Add optional EH block.
1164+
11611165
if (HasName)
11621166
Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block.
11631167

@@ -1188,6 +1192,8 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
11881192
OutStreamer->AddComment("PPA1 Flags 4");
11891193
if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
11901194
OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area");
1195+
if ((Flags4 & PPA1Flag4::EHBlock) == PPA1Flag4::EHBlock)
1196+
OutStreamer->AddComment(" Bit 3: 1 = C++ EH block");
11911197
if ((Flags4 & PPA1Flag4::ProcedureNamePresent) ==
11921198
PPA1Flag4::ProcedureNamePresent)
11931199
OutStreamer->AddComment(" Bit 7: 1 = Name Length and Name");
@@ -1314,12 +1320,14 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
13141320
OutStreamer->AddComment("Offset to PPA2");
13151321
OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4);
13161322

1323+
bool NeedEmitEHBlock = !MF->getLandingPads().empty();
1324+
13171325
bool HasName =
13181326
MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
13191327

13201328
emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
13211329
MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
1322-
TargetHasVector && SavedVRMask != 0, HasName);
1330+
TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock, HasName);
13231331

13241332
OutStreamer->AddComment("Length/4 of Parms");
13251333
OutStreamer->emitInt16(
@@ -1361,6 +1369,29 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
13611369
OutStreamer->emitInt32(FrameAndVROffset);
13621370
}
13631371

1372+
// Emit C++ EH information block
1373+
const Function *Per = nullptr;
1374+
if (NeedEmitEHBlock) {
1375+
Per = dyn_cast<Function>(
1376+
MF->getFunction().getPersonalityFn()->stripPointerCasts());
1377+
MCSymbol *PersonalityRoutine =
1378+
Per ? MF->getTarget().getSymbol(Per) : nullptr;
1379+
assert(PersonalityRoutine && "Missing personality routine");
1380+
1381+
OutStreamer->AddComment("Version");
1382+
OutStreamer->emitInt32(1);
1383+
OutStreamer->AddComment("Flags");
1384+
OutStreamer->emitInt32(0); // LSDA field is a WAS offset
1385+
OutStreamer->AddComment("Personality routine");
1386+
OutStreamer->emitInt64(ADATable.insert(
1387+
PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC));
1388+
OutStreamer->AddComment("LSDA location");
1389+
MCSymbol *GCCEH = MF->getContext().getOrCreateSymbol(
1390+
Twine("GCC_except_table") + Twine(MF->getFunctionNumber()));
1391+
OutStreamer->emitInt64(
1392+
ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR));
1393+
}
1394+
13641395
// Emit name length and name optional section (0x01 of flags 4)
13651396
if (HasName)
13661397
emitPPA1Name(OutStreamer, MF->getFunction().getName());

llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/CodeGen/MachineModuleInfo.h"
1818
#include "llvm/CodeGen/MachineRegisterInfo.h"
1919
#include "llvm/CodeGen/RegisterScavenging.h"
20+
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
2021
#include "llvm/IR/Function.h"
2122
#include "llvm/Target/TargetMachine.h"
2223

@@ -994,6 +995,11 @@ bool SystemZXPLINKFrameLowering::assignCalleeSavedSpillSlots(
994995
if (hasFP(MF) || Subtarget.hasBackChain())
995996
CSI.push_back(CalleeSavedInfo(Regs.getStackPointerRegister()));
996997

998+
// If this function has an associated personality function then the
999+
// environment register R5 must be saved in the DSA.
1000+
if (!MF.getLandingPads().empty())
1001+
CSI.push_back(CalleeSavedInfo(Regs.getADARegister()));
1002+
9971003
// Scan the call-saved GPRs and find the bounds of the register spill area.
9981004
Register LowRestoreGPR = 0;
9991005
int LowRestoreOffset = INT32_MAX;

llvm/lib/Target/SystemZ/SystemZISelLowering.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,16 @@ SystemZTargetLowering::getRegisterByName(const char *RegName, LLT VT,
13621362
report_fatal_error("Invalid register name global variable");
13631363
}
13641364

1365+
Register SystemZTargetLowering::getExceptionPointerRegister(
1366+
const Constant *PersonalityFn) const {
1367+
return Subtarget.isTargetXPLINK64() ? SystemZ::R1D : SystemZ::R6D;
1368+
}
1369+
1370+
Register SystemZTargetLowering::getExceptionSelectorRegister(
1371+
const Constant *PersonalityFn) const {
1372+
return Subtarget.isTargetXPLINK64() ? SystemZ::R2D : SystemZ::R7D;
1373+
}
1374+
13651375
void SystemZTargetLowering::LowerAsmOperandForConstraint(
13661376
SDValue Op, StringRef Constraint, std::vector<SDValue> &Ops,
13671377
SelectionDAG &DAG) const {

llvm/lib/Target/SystemZ/SystemZISelLowering.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -555,16 +555,12 @@ class SystemZTargetLowering : public TargetLowering {
555555
/// If a physical register, this returns the register that receives the
556556
/// exception address on entry to an EH pad.
557557
Register
558-
getExceptionPointerRegister(const Constant *PersonalityFn) const override {
559-
return SystemZ::R6D;
560-
}
558+
getExceptionPointerRegister(const Constant *PersonalityFn) const override;
561559

562560
/// If a physical register, this returns the register that receives the
563561
/// exception typeid on entry to a landing pad.
564562
Register
565-
getExceptionSelectorRegister(const Constant *PersonalityFn) const override {
566-
return SystemZ::R7D;
567-
}
563+
getExceptionSelectorRegister(const Constant *PersonalityFn) const override;
568564

569565
/// Override to support customized stack guard loading.
570566
bool useLoadStackGuardNode() const override {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
; RUN: llc < %s -mtriple=s390x-none-zos -mcpu=z10 | FileCheck %s
2+
;
3+
; Ensures that landingpad instructions use the right Exception Pointer
4+
; and Exception Selector registers, and that the exception table is emitted.
5+
6+
declare void @callee()
7+
declare void @passeh(i8*, i32) noreturn
8+
declare i32 @__zos_cxx_personality_v2(...)
9+
10+
define void @test1() uwtable personality i32 (...)* @__zos_cxx_personality_v2 {
11+
entry:
12+
%ehptr = alloca i8*, align 8
13+
%ehsel = alloca i32, align 8
14+
invoke void @callee() to label %done unwind label %lpad
15+
done:
16+
ret void
17+
; Match the return instruction.
18+
; CHECK: b 2(7)
19+
lpad:
20+
%0 = landingpad { i8*, i32 } cleanup
21+
; The Exception Pointer is %r1; the Exception Selector, %r2.
22+
; CHECK: @BB{{[^%]*}} %lpad
23+
; CHECK-DAG: stg 1, {{.*}}
24+
; CHECK-DAG: st 2, {{.*}}
25+
%1 = extractvalue { i8*, i32 } %0, 0
26+
%2 = extractvalue { i8*, i32 } %0, 1
27+
store i8* %1, i8** %ehptr, align 8
28+
store i32 %2, i32* %ehsel, align 8
29+
call void @passeh(i8* %1, i32 %2)
30+
unreachable
31+
}
32+
33+
; Check that offsets to the FD of the personality routine and LSDA are emitted in PPA1
34+
; CHECK: .byte 145 {{.*PPA1 Flags}}
35+
; CHECK: Bit 3: 1 = C++ EH block
36+
; TODO: Emit the value instead of a dummy value.
37+
; CHECK: Personality routine
38+
; CHECK: LSDA location
39+
; Check that the exception table is emitted into .lsda section.
40+
; CHECK: .section ".gcc_exception_table.test1"
41+
; CHECK: GCC_except_table0:

0 commit comments

Comments
 (0)