forked from OSchip/llvm-project
[SystemZ][z/OS] Add the PPA1 to SystemZAsmPrinter
Differential Revision: https://reviews.llvm.org/D125725
This commit is contained in:
parent
4d8268fbf4
commit
5ac411aea8
|
@ -0,0 +1,31 @@
|
||||||
|
//===-- llvm/BinaryFormat/GOFF.h - GOFF definitions --------------*- C++-*-===//
|
||||||
|
//
|
||||||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This header contains common, non-processor-specific data structures and
|
||||||
|
// constants for the GOFF file format.
|
||||||
|
//
|
||||||
|
// GOFF specifics can be found in MVS Program Management: Advanced Facilities
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_BINARYFORMAT_GOFF_H
|
||||||
|
#define LLVM_BINARYFORMAT_GOFF_H
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
namespace GOFF {
|
||||||
|
|
||||||
|
// \brief Subsections of the primary C_CODE section in the object file.
|
||||||
|
enum SubsectionKind : uint8_t {
|
||||||
|
SK_PPA1 = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace GOFF
|
||||||
|
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
|
#endif // LLVM_BINARYFORMAT_GOFF_H
|
|
@ -613,7 +613,8 @@ public:
|
||||||
unsigned Flags,
|
unsigned Flags,
|
||||||
unsigned EntrySize);
|
unsigned EntrySize);
|
||||||
|
|
||||||
MCSectionGOFF *getGOFFSection(StringRef Section, SectionKind Kind);
|
MCSectionGOFF *getGOFFSection(StringRef Section, SectionKind Kind,
|
||||||
|
MCSection *Parent, const MCExpr *SubsectionId);
|
||||||
|
|
||||||
MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
|
MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics,
|
||||||
SectionKind Kind, StringRef COMDATSymName,
|
SectionKind Kind, StringRef COMDATSymName,
|
||||||
|
|
|
@ -225,6 +225,9 @@ protected:
|
||||||
MCSection *GIATsSection = nullptr;
|
MCSection *GIATsSection = nullptr;
|
||||||
MCSection *GLJMPSection = nullptr;
|
MCSection *GLJMPSection = nullptr;
|
||||||
|
|
||||||
|
// GOFF specific sections.
|
||||||
|
MCSection *PPA1Section = nullptr;
|
||||||
|
|
||||||
// XCOFF specific sections
|
// XCOFF specific sections
|
||||||
MCSection *TOCBaseSection = nullptr;
|
MCSection *TOCBaseSection = nullptr;
|
||||||
MCSection *ReadOnly8Section = nullptr;
|
MCSection *ReadOnly8Section = nullptr;
|
||||||
|
@ -423,6 +426,9 @@ public:
|
||||||
MCSection *getGIATsSection() const { return GIATsSection; }
|
MCSection *getGIATsSection() const { return GIATsSection; }
|
||||||
MCSection *getGLJMPSection() const { return GLJMPSection; }
|
MCSection *getGLJMPSection() const { return GLJMPSection; }
|
||||||
|
|
||||||
|
// GOFF specific sections.
|
||||||
|
MCSection *getPPA1Section() const { return PPA1Section; }
|
||||||
|
|
||||||
// XCOFF specific sections
|
// XCOFF specific sections
|
||||||
MCSection *getTOCBaseSection() const { return TOCBaseSection; }
|
MCSection *getTOCBaseSection() const { return TOCBaseSection; }
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#ifndef LLVM_MC_MCSECTIONGOFF_H
|
#ifndef LLVM_MC_MCSECTIONGOFF_H
|
||||||
#define LLVM_MC_MCSECTIONGOFF_H
|
#define LLVM_MC_MCSECTIONGOFF_H
|
||||||
|
|
||||||
|
#include "llvm/BinaryFormat/GOFF.h"
|
||||||
#include "llvm/MC/MCSection.h"
|
#include "llvm/MC/MCSection.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
|
@ -24,9 +25,12 @@ class MCExpr;
|
||||||
|
|
||||||
class MCSectionGOFF final : public MCSection {
|
class MCSectionGOFF final : public MCSection {
|
||||||
private:
|
private:
|
||||||
|
MCSection *Parent;
|
||||||
|
const MCExpr *SubsectionId;
|
||||||
|
|
||||||
friend class MCContext;
|
friend class MCContext;
|
||||||
MCSectionGOFF(StringRef Name, SectionKind K)
|
MCSectionGOFF(StringRef Name, SectionKind K, MCSection *P, const MCExpr *Sub)
|
||||||
: MCSection(SV_GOFF, Name, K, nullptr) {}
|
: MCSection(SV_GOFF, Name, K, nullptr), Parent(P), SubsectionId(Sub) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
|
void printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
|
||||||
|
@ -39,6 +43,9 @@ public:
|
||||||
|
|
||||||
bool isVirtualSection() const override { return false; }
|
bool isVirtualSection() const override { return false; }
|
||||||
|
|
||||||
|
MCSection *getParent() const { return Parent; }
|
||||||
|
const MCExpr *getSubsectionId() const { return SubsectionId; }
|
||||||
|
|
||||||
static bool classof(const MCSection *S) { return S->getVariant() == SV_GOFF; }
|
static bool classof(const MCSection *S) { return S->getVariant() == SV_GOFF; }
|
||||||
};
|
};
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
|
@ -2593,8 +2593,8 @@ MCSection *TargetLoweringObjectFileGOFF::SelectSectionForGlobal(
|
||||||
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
|
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
|
||||||
auto *Symbol = TM.getSymbol(GO);
|
auto *Symbol = TM.getSymbol(GO);
|
||||||
if (Kind.isBSS())
|
if (Kind.isBSS())
|
||||||
return getContext().getGOFFSection(Symbol->getName(),
|
return getContext().getGOFFSection(Symbol->getName(), SectionKind::getBSS(),
|
||||||
SectionKind::getBSS());
|
nullptr, nullptr);
|
||||||
|
|
||||||
return getContext().getObjectFileInfo()->getTextSection();
|
return getContext().getObjectFileInfo()->getTextSection();
|
||||||
}
|
}
|
||||||
|
|
|
@ -634,11 +634,14 @@ Optional<unsigned> MCContext::getELFUniqueIDForEntsize(StringRef SectionName,
|
||||||
return (I != ELFEntrySizeMap.end()) ? Optional<unsigned>(I->second) : None;
|
return (I != ELFEntrySizeMap.end()) ? Optional<unsigned>(I->second) : None;
|
||||||
}
|
}
|
||||||
|
|
||||||
MCSectionGOFF *MCContext::getGOFFSection(StringRef Section, SectionKind Kind) {
|
MCSectionGOFF *MCContext::getGOFFSection(StringRef Section, SectionKind Kind,
|
||||||
|
MCSection *Parent,
|
||||||
|
const MCExpr *SubsectionId) {
|
||||||
// Do the lookup. If we don't have a hit, return a new section.
|
// Do the lookup. If we don't have a hit, return a new section.
|
||||||
auto &GOFFSection = GOFFUniquingMap[Section.str()];
|
auto &GOFFSection = GOFFUniquingMap[Section.str()];
|
||||||
if (!GOFFSection)
|
if (!GOFFSection)
|
||||||
GOFFSection = new (GOFFAllocator.Allocate()) MCSectionGOFF(Section, Kind);
|
GOFFSection = new (GOFFAllocator.Allocate())
|
||||||
|
MCSectionGOFF(Section, Kind, Parent, SubsectionId);
|
||||||
|
|
||||||
return GOFFSection;
|
return GOFFSection;
|
||||||
}
|
}
|
||||||
|
|
|
@ -523,8 +523,13 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
|
void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
|
||||||
TextSection = Ctx->getGOFFSection(".text", SectionKind::getText());
|
TextSection =
|
||||||
BSSSection = Ctx->getGOFFSection(".bss", SectionKind::getBSS());
|
Ctx->getGOFFSection(".text", SectionKind::getText(), nullptr, nullptr);
|
||||||
|
BSSSection =
|
||||||
|
Ctx->getGOFFSection(".bss", SectionKind::getBSS(), nullptr, nullptr);
|
||||||
|
PPA1Section =
|
||||||
|
Ctx->getGOFFSection(".ppa1", SectionKind::getMetadata(), TextSection,
|
||||||
|
MCConstantExpr::create(GOFF::SK_PPA1, *Ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
|
void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
|
||||||
|
|
|
@ -819,13 +819,253 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
|
||||||
emitStackMaps(SM);
|
emitStackMaps(SM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SystemZAsmPrinter::emitFunctionBodyEnd() {
|
||||||
|
if (TM.getTargetTriple().isOSzOS()) {
|
||||||
|
// Emit symbol for the end of function if the z/OS target streamer
|
||||||
|
// is used. This is needed to calculate the size of the function.
|
||||||
|
MCSymbol *FnEndSym = createTempSymbol("func_end");
|
||||||
|
OutStreamer->emitLabel(FnEndSym);
|
||||||
|
|
||||||
|
OutStreamer->PushSection();
|
||||||
|
OutStreamer->SwitchSection(getObjFileLowering().getPPA1Section());
|
||||||
|
emitPPA1(FnEndSym);
|
||||||
|
OutStreamer->PopSection();
|
||||||
|
|
||||||
|
CurrentFnPPA1Sym = nullptr;
|
||||||
|
CurrentFnEPMarkerSym = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
|
||||||
|
bool StackProtector, bool FPRMask, bool VRMask) {
|
||||||
|
enum class PPA1Flag1 : uint8_t {
|
||||||
|
DSA64Bit = (0x80 >> 0),
|
||||||
|
VarArg = (0x80 >> 7),
|
||||||
|
LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit)
|
||||||
|
};
|
||||||
|
enum class PPA1Flag2 : uint8_t {
|
||||||
|
ExternalProcedure = (0x80 >> 0),
|
||||||
|
STACKPROTECTOR = (0x80 >> 3),
|
||||||
|
LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
|
||||||
|
};
|
||||||
|
enum class PPA1Flag3 : uint8_t {
|
||||||
|
FPRMask = (0x80 >> 2),
|
||||||
|
LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
|
||||||
|
};
|
||||||
|
enum class PPA1Flag4 : uint8_t {
|
||||||
|
EPMOffsetPresent = (0x80 >> 0),
|
||||||
|
VRMask = (0x80 >> 2),
|
||||||
|
ProcedureNamePresent = (0x80 >> 7),
|
||||||
|
LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Declare optional section flags that can be modified.
|
||||||
|
auto Flags1 = PPA1Flag1(0);
|
||||||
|
auto Flags2 = PPA1Flag2::ExternalProcedure;
|
||||||
|
auto Flags3 = PPA1Flag3(0);
|
||||||
|
auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent;
|
||||||
|
|
||||||
|
Flags1 |= PPA1Flag1::DSA64Bit;
|
||||||
|
|
||||||
|
if (VarArg)
|
||||||
|
Flags1 |= PPA1Flag1::VarArg;
|
||||||
|
|
||||||
|
if (StackProtector)
|
||||||
|
Flags2 |= PPA1Flag2::STACKPROTECTOR;
|
||||||
|
|
||||||
|
// SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
|
||||||
|
if (FPRMask)
|
||||||
|
Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
|
||||||
|
|
||||||
|
if (VRMask)
|
||||||
|
Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
|
||||||
|
|
||||||
|
OutStreamer->AddComment("PPA1 Flags 1");
|
||||||
|
if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
|
||||||
|
OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA");
|
||||||
|
else
|
||||||
|
OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA");
|
||||||
|
if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
|
||||||
|
OutStreamer->AddComment(" Bit 7: 1 = Vararg function");
|
||||||
|
OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
|
||||||
|
|
||||||
|
OutStreamer->AddComment("PPA1 Flags 2");
|
||||||
|
if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
|
||||||
|
OutStreamer->AddComment(" Bit 0: 1 = External procedure");
|
||||||
|
if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
|
||||||
|
OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled");
|
||||||
|
else
|
||||||
|
OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled");
|
||||||
|
OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
|
||||||
|
|
||||||
|
OutStreamer->AddComment("PPA1 Flags 3");
|
||||||
|
if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
|
||||||
|
OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area");
|
||||||
|
OutStreamer->emitInt8(
|
||||||
|
static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
|
||||||
|
|
||||||
|
OutStreamer->AddComment("PPA1 Flags 4");
|
||||||
|
if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
|
||||||
|
OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area");
|
||||||
|
OutStreamer->emitInt8(static_cast<uint8_t>(
|
||||||
|
Flags4)); // Flags 4 (optional sections, always emit these).
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
|
||||||
|
const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
|
||||||
|
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
|
||||||
|
const auto TargetHasVector = Subtarget.hasVector();
|
||||||
|
|
||||||
|
const SystemZMachineFunctionInfo *ZFI =
|
||||||
|
MF->getInfo<SystemZMachineFunctionInfo>();
|
||||||
|
const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
|
||||||
|
Subtarget.getFrameLowering());
|
||||||
|
const MachineFrameInfo &MFFrame = MF->getFrameInfo();
|
||||||
|
|
||||||
|
// Get saved GPR/FPR/VPR masks.
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
|
||||||
|
uint16_t SavedGPRMask = 0;
|
||||||
|
uint16_t SavedFPRMask = 0;
|
||||||
|
uint8_t SavedVRMask = 0;
|
||||||
|
int64_t OffsetFPR = 0;
|
||||||
|
int64_t OffsetVR = 0;
|
||||||
|
const int64_t TopOfStack =
|
||||||
|
MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
|
||||||
|
|
||||||
|
// Loop over the spilled registers. The CalleeSavedInfo can't be used because
|
||||||
|
// it does not contain all spilled registers.
|
||||||
|
for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
|
||||||
|
E = ZFI->getSpillGPRRegs().HighGPR;
|
||||||
|
I && E && I <= E; ++I) {
|
||||||
|
unsigned V = TRI->getEncodingValue((Register)I);
|
||||||
|
assert(V < 16 && "GPR index out of range");
|
||||||
|
SavedGPRMask |= 1 << (15 - V);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &CS : CSI) {
|
||||||
|
unsigned Reg = CS.getReg();
|
||||||
|
unsigned I = TRI->getEncodingValue(Reg);
|
||||||
|
|
||||||
|
if (SystemZ::FP64BitRegClass.contains(Reg)) {
|
||||||
|
assert(I < 16 && "FPR index out of range");
|
||||||
|
SavedFPRMask |= 1 << (15 - I);
|
||||||
|
int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
|
||||||
|
if (Temp < OffsetFPR)
|
||||||
|
OffsetFPR = Temp;
|
||||||
|
} else if (SystemZ::VR128BitRegClass.contains(Reg)) {
|
||||||
|
assert(I >= 16 && I <= 23 && "VPR index out of range");
|
||||||
|
unsigned BitNum = I - 16;
|
||||||
|
SavedVRMask |= 1 << (7 - BitNum);
|
||||||
|
int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
|
||||||
|
if (Temp < OffsetVR)
|
||||||
|
OffsetVR = Temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust the offset.
|
||||||
|
OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
|
||||||
|
OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
|
||||||
|
|
||||||
|
// Get alloca register.
|
||||||
|
uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
|
||||||
|
uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
|
||||||
|
assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
|
||||||
|
|
||||||
|
// Build FPR save area offset.
|
||||||
|
uint32_t FrameAndFPROffset = 0;
|
||||||
|
if (SavedFPRMask) {
|
||||||
|
uint64_t FPRSaveAreaOffset = OffsetFPR;
|
||||||
|
assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
|
||||||
|
|
||||||
|
FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
|
||||||
|
FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build VR save area offset.
|
||||||
|
uint32_t FrameAndVROffset = 0;
|
||||||
|
if (TargetHasVector && SavedVRMask) {
|
||||||
|
uint64_t VRSaveAreaOffset = OffsetVR;
|
||||||
|
assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
|
||||||
|
|
||||||
|
FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
|
||||||
|
FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit PPA1 section.
|
||||||
|
OutStreamer->AddComment("PPA1");
|
||||||
|
OutStreamer->emitLabel(CurrentFnPPA1Sym);
|
||||||
|
OutStreamer->AddComment("Version");
|
||||||
|
OutStreamer->emitInt8(0x02); // Version.
|
||||||
|
OutStreamer->AddComment("LE Signature X'CE'");
|
||||||
|
OutStreamer->emitInt8(0xCE); // CEL signature.
|
||||||
|
OutStreamer->AddComment("Saved GPR Mask");
|
||||||
|
OutStreamer->emitInt16(SavedGPRMask);
|
||||||
|
|
||||||
|
emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
|
||||||
|
MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
|
||||||
|
TargetHasVector && SavedVRMask != 0);
|
||||||
|
|
||||||
|
OutStreamer->AddComment("Length/4 of Parms");
|
||||||
|
OutStreamer->emitInt16(
|
||||||
|
static_cast<uint16_t>(MFFrame.getMaxCallFrameSize() / 4)); // Parms/4.
|
||||||
|
OutStreamer->AddComment("Length of Code");
|
||||||
|
OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
|
||||||
|
|
||||||
|
// Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
|
||||||
|
if (SavedFPRMask) {
|
||||||
|
OutStreamer->AddComment("FPR mask");
|
||||||
|
OutStreamer->emitInt16(SavedFPRMask);
|
||||||
|
OutStreamer->AddComment("AR mask");
|
||||||
|
OutStreamer->emitInt16(0); // AR Mask, unused currently.
|
||||||
|
OutStreamer->AddComment("FPR Save Area Locator");
|
||||||
|
OutStreamer->AddComment(Twine(" Bit 0-3: Register R")
|
||||||
|
.concat(utostr(FrameAndFPROffset >> 28))
|
||||||
|
.str());
|
||||||
|
OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")
|
||||||
|
.concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
|
||||||
|
.str());
|
||||||
|
OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
|
||||||
|
// register to add value to
|
||||||
|
// (alloca reg).
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit saved VR mask to VR save area.
|
||||||
|
if (TargetHasVector && SavedVRMask) {
|
||||||
|
OutStreamer->AddComment("VR mask");
|
||||||
|
OutStreamer->emitInt8(SavedVRMask);
|
||||||
|
OutStreamer->emitInt8(0); // Reserved.
|
||||||
|
OutStreamer->emitInt16(0); // Also reserved.
|
||||||
|
OutStreamer->AddComment("VR Save Area Locator");
|
||||||
|
OutStreamer->AddComment(Twine(" Bit 0-3: Register R")
|
||||||
|
.concat(utostr(FrameAndVROffset >> 28))
|
||||||
|
.str());
|
||||||
|
OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")
|
||||||
|
.concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
|
||||||
|
.str());
|
||||||
|
OutStreamer->emitInt32(FrameAndVROffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit offset to entry point optional section (0x80 of flags 4).
|
||||||
|
OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
|
||||||
|
4);
|
||||||
|
}
|
||||||
|
|
||||||
void SystemZAsmPrinter::emitFunctionEntryLabel() {
|
void SystemZAsmPrinter::emitFunctionEntryLabel() {
|
||||||
const SystemZSubtarget &Subtarget =
|
const SystemZSubtarget &Subtarget =
|
||||||
static_cast<const SystemZSubtarget &>(MF->getSubtarget());
|
static_cast<const SystemZSubtarget &>(MF->getSubtarget());
|
||||||
|
|
||||||
if (Subtarget.getTargetTriple().isOSzOS()) {
|
if (Subtarget.getTargetTriple().isOSzOS()) {
|
||||||
MCContext &OutContext = OutStreamer->getContext();
|
MCContext &OutContext = OutStreamer->getContext();
|
||||||
MCSymbol *EPMarkerSym = OutContext.createTempSymbol("CM_", true);
|
|
||||||
|
// Save information for later use.
|
||||||
|
std::string N(MF->getFunction().hasName()
|
||||||
|
? Twine(MF->getFunction().getName()).concat("_").str()
|
||||||
|
: "");
|
||||||
|
|
||||||
|
CurrentFnEPMarkerSym =
|
||||||
|
OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);
|
||||||
|
CurrentFnPPA1Sym =
|
||||||
|
OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);
|
||||||
|
|
||||||
// EntryPoint Marker
|
// EntryPoint Marker
|
||||||
const MachineFrameInfo &MFFrame = MF->getFrameInfo();
|
const MachineFrameInfo &MFFrame = MF->getFrameInfo();
|
||||||
|
@ -844,11 +1084,14 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
|
||||||
|
|
||||||
// Emit entry point marker section.
|
// Emit entry point marker section.
|
||||||
OutStreamer->AddComment("XPLINK Routine Layout Entry");
|
OutStreamer->AddComment("XPLINK Routine Layout Entry");
|
||||||
OutStreamer->emitLabel(EPMarkerSym);
|
OutStreamer->emitLabel(CurrentFnEPMarkerSym);
|
||||||
OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
|
OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
|
||||||
OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
|
OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
|
||||||
OutStreamer->AddComment("Mark Type C'1'");
|
OutStreamer->AddComment("Mark Type C'1'");
|
||||||
OutStreamer->emitInt8(0xF1); // Mark Type.
|
OutStreamer->emitInt8(0xF1); // Mark Type.
|
||||||
|
OutStreamer->AddComment("Offset to PPA1");
|
||||||
|
OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,
|
||||||
|
4);
|
||||||
if (OutStreamer->isVerboseAsm()) {
|
if (OutStreamer->isVerboseAsm()) {
|
||||||
OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
|
OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
|
||||||
OutStreamer->AddComment("Entry Flags");
|
OutStreamer->AddComment("Entry Flags");
|
||||||
|
|
|
@ -26,6 +26,8 @@ class raw_ostream;
|
||||||
class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
|
class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
|
||||||
private:
|
private:
|
||||||
StackMaps SM;
|
StackMaps SM;
|
||||||
|
MCSymbol *CurrentFnPPA1Sym; // PPA1 Symbol.
|
||||||
|
MCSymbol *CurrentFnEPMarkerSym; // Entry Point Marker.
|
||||||
|
|
||||||
SystemZTargetStreamer *getTargetStreamer() {
|
SystemZTargetStreamer *getTargetStreamer() {
|
||||||
MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
|
MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
|
||||||
|
@ -45,9 +47,12 @@ private:
|
||||||
BASR33 = 7, // b'x111' == BASR r3,r3
|
BASR33 = 7, // b'x111' == BASR r3,r3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void emitPPA1(MCSymbol *FnEndSym);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
|
SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
|
||||||
: AsmPrinter(TM, std::move(Streamer)), SM(*this) {}
|
: AsmPrinter(TM, std::move(Streamer)), SM(*this),
|
||||||
|
CurrentFnPPA1Sym(nullptr), CurrentFnEPMarkerSym(nullptr) {}
|
||||||
|
|
||||||
// Override AsmPrinter.
|
// Override AsmPrinter.
|
||||||
StringRef getPassName() const override { return "SystemZ Assembly Printer"; }
|
StringRef getPassName() const override { return "SystemZ Assembly Printer"; }
|
||||||
|
@ -64,6 +69,7 @@ public:
|
||||||
return AsmPrinter::doInitialization(M);
|
return AsmPrinter::doInitialization(M);
|
||||||
}
|
}
|
||||||
void emitFunctionEntryLabel() override;
|
void emitFunctionEntryLabel() override;
|
||||||
|
void emitFunctionBodyEnd() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void emitCallInformation(CallType CT);
|
void emitCallInformation(CallType CT);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
; RUN: llc -mtriple s390x-ibm-zos < %s | FileCheck %s
|
; RUN: llc -mtriple s390x-ibm-zos < %s | FileCheck %s
|
||||||
; REQUIRES: systemz-registered-target
|
; REQUIRES: systemz-registered-target
|
||||||
|
|
||||||
; CHECK: @@CM_0: * @void_test
|
; CHECK: @@EPM_void_test_0: * @void_test
|
||||||
; CHECK: * XPLINK Routine Layout Entry
|
; CHECK: * XPLINK Routine Layout Entry
|
||||||
; CHECK: .long 12779717 * Eyecatcher 0x00C300C500C500
|
; CHECK: .long 12779717 * Eyecatcher 0x00C300C500C500
|
||||||
; CHECK: .short 197
|
; CHECK: .short 197
|
||||||
|
@ -10,6 +10,24 @@
|
||||||
; CHECK: .long 128 * DSA Size 0x80
|
; CHECK: .long 128 * DSA Size 0x80
|
||||||
; CHECK: * Entry Flags
|
; CHECK: * Entry Flags
|
||||||
; CHECK: * Bit 2: 0 = Does not use alloca
|
; CHECK: * Bit 2: 0 = Does not use alloca
|
||||||
|
; CHECK: @@func_end0:
|
||||||
|
; CHECK: .section ".ppa1"
|
||||||
|
; CHECK: @@PPA1_void_test_0: * PPA1
|
||||||
|
; CHECK: .byte 2 * Version
|
||||||
|
; CHECK: .byte 206 * LE Signature X'CE'
|
||||||
|
; CHECK: .short 768 * Saved GPR Mask
|
||||||
|
; CHECK: .byte 128 * PPA1 Flags 1
|
||||||
|
; CHECK: * Bit 0: 1 = 64-bit DSA
|
||||||
|
; CHECK: .byte 128 * PPA1 Flags 2
|
||||||
|
; CHECK: * Bit 0: 1 = External procedure
|
||||||
|
; CHECK: * Bit 3: 0 = STACKPROTECT is not enabled
|
||||||
|
; CHECK: .byte 0 * PPA1 Flags 3
|
||||||
|
; CHECK: .byte 129 * PPA1 Flags 4
|
||||||
|
; CHECK: .short 0 * Length/4 of Parms
|
||||||
|
; CHECK: .long @@func_end0-@@EPM_void_test_0 * Length of Code
|
||||||
|
; CHECK: .long @@EPM_void_test_0-@@PPA1_void_test_0
|
||||||
|
; CHECK: .section ".text"
|
||||||
|
; CHECK: * -- End function
|
||||||
define void @void_test() {
|
define void @void_test() {
|
||||||
entry:
|
entry:
|
||||||
ret void
|
ret void
|
||||||
|
|
Loading…
Reference in New Issue