[llvm] [SystemZ] Split SystemZAsmPrinter into 2 classes - ELF and XPLink (PR #214343)
Yusra Syeda via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 07:10:47 PDT 2026
https://github.com/ysyeda updated https://github.com/llvm/llvm-project/pull/214343
>From d4b158f81d79b3e6297e947774b50f31f4156a6e Mon Sep 17 00:00:00 2001
From: Yusra Syeda <yusra.syeda at ibm.com>
Date: Wed, 5 Aug 2026 17:19:53 -0400
Subject: [PATCH 1/5] split systemzasmprinter into 2 classes for elf and xplink
---
llvm/lib/Target/SystemZ/CMakeLists.txt | 2 +
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 1291 +----------------
llvm/lib/Target/SystemZ/SystemZAsmPrinter.h | 103 +-
.../Target/SystemZ/SystemZELFAsmPrinter.cpp | 478 ++++++
.../lib/Target/SystemZ/SystemZELFAsmPrinter.h | 54 +
.../SystemZ/SystemZXPLINKAsmPrinter.cpp | 864 +++++++++++
.../Target/SystemZ/SystemZXPLINKAsmPrinter.h | 127 ++
7 files changed, 1545 insertions(+), 1374 deletions(-)
create mode 100644 llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
create mode 100644 llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.h
create mode 100644 llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp
create mode 100644 llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.h
diff --git a/llvm/lib/Target/SystemZ/CMakeLists.txt b/llvm/lib/Target/SystemZ/CMakeLists.txt
index 6d94a755322df..1dd74c3ff8d5c 100644
--- a/llvm/lib/Target/SystemZ/CMakeLists.txt
+++ b/llvm/lib/Target/SystemZ/CMakeLists.txt
@@ -18,6 +18,8 @@ add_public_tablegen_target(SystemZCommonTableGen)
add_llvm_target(SystemZCodeGen
SystemZAsmPrinter.cpp
+ SystemZELFAsmPrinter.cpp
+ SystemZXPLINKAsmPrinter.cpp
SystemZCallingConv.cpp
SystemZConstantPoolValue.cpp
SystemZCopyPhysRegs.cpp
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 235d8eea84ec5..d4c274bb6bd14 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -12,32 +12,21 @@
//===----------------------------------------------------------------------===//
#include "SystemZAsmPrinter.h"
+#include "SystemZELFAsmPrinter.h"
+#include "SystemZXPLINKAsmPrinter.h"
#include "MCTargetDesc/SystemZGNUInstPrinter.h"
#include "MCTargetDesc/SystemZHLASMInstPrinter.h"
#include "MCTargetDesc/SystemZMCAsmInfo.h"
#include "MCTargetDesc/SystemZMCTargetDesc.h"
-#include "SystemZConstantPoolValue.h"
#include "SystemZMCInstLower.h"
+#include "SystemZSubtarget.h"
#include "TargetInfo/SystemZTargetInfo.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/BinaryFormat/GOFF.h"
-#include "llvm/CodeGen/MachineModuleInfoImpls.h"
-#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
-#include "llvm/IR/GlobalVariable.h"
-#include "llvm/IR/Mangler.h"
-#include "llvm/IR/Module.h"
-#include "llvm/MC/MCDirectives.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstBuilder.h"
-#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbolGOFF.h"
#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Support/Chrono.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ConvertEBCDIC.h"
-#include "llvm/Support/FormatVariadic.h"
using namespace llvm;
@@ -81,18 +70,6 @@ static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
.addImm(MI->getOperand(5).getImm());
}
-static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
- StringRef Name = "__tls_get_offset";
- return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
- SystemZ::S_PLT, Context);
-}
-
-static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
- StringRef Name = "_GLOBAL_OFFSET_TABLE_";
- return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
- Context);
-}
-
// MI is an instruction that accepts an optional alignment hint,
// and which was already lowered to LoweredMI. If the alignment
// of the original memory operand is known, update LoweredMI to
@@ -103,10 +80,9 @@ static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
return;
Align Alignment = Align(16);
- for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),
- EE = MI->memoperands_end(); MMOI != EE; ++MMOI)
- if ((*MMOI)->getAlign() < Alignment)
- Alignment = (*MMOI)->getAlign();
+ for (const MachineMemOperand *MMO : MI->memoperands())
+ if (MMO->getAlign() < Alignment)
+ Alignment = MMO->getAlign();
unsigned AlignmentHint = 0;
if (Alignment >= Align(16))
@@ -160,92 +136,6 @@ static MCInst lowerVecEltInsertion(const MachineInstr *MI, unsigned Opcode) {
.addImm(0);
}
-bool SystemZAsmPrinter::doInitialization(Module &M) {
- SM.reset();
-
- // In HLASM, the only way to represent aliases is to use the
- // extra-label-at-definition strategy. This is similar to the AIX
- // implementation with the additional caveat that all symbol attributes must
- // be emitted before the label is emitted.
- if (TM.getTargetTriple().isOSzOS()) {
- // Construct an aliasing list for each GlobalObject.
- for (const auto &Alias : M.aliases()) {
- const GlobalObject *Aliasee = Alias.getAliaseeObject();
- if (!Aliasee)
- OutContext.reportError(
- {}, "Alias without a base object is not yet supported on z/OS.");
-
- bool IsFunc = isa<Function>(Aliasee->stripPointerCasts());
- if (IsFunc) {
- if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage())
- OutContext.reportError({},
- "Weak alias/reference not supported on z/OS");
-
- GOAliasMap[Aliasee].push_back(&Alias);
- } else
- OutContext.reportError(
- {}, "Only aliases to functions is supported in GOFF.");
- }
- }
- return AsmPrinter::doInitialization(M);
-}
-
-// The XPLINK ABI requires that a no-op encoding the call type is emitted after
-// each call to a subroutine. This information can be used by the called
-// function to determine its entry point, e.g. for generating a backtrace. The
-// call type is encoded as a register number in the bcr instruction. See
-// enumeration CallType for the possible values.
-void SystemZAsmPrinter::emitCallInformation(CallType CT) {
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BCRAsm)
- .addImm(0)
- .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
-}
-
-uint32_t SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,
- unsigned SlotKind) {
- auto Key = std::make_pair(Sym, SlotKind);
- auto It = Displacements.find(Key);
-
- if (It != Displacements.end())
- return (*It).second;
-
- // Determine length of descriptor.
- uint32_t Length;
- switch (SlotKind) {
- case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
- Length = 2 * PointerSize;
- break;
- default:
- Length = PointerSize;
- break;
- }
-
- uint32_t Displacement = NextDisplacement;
- Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement;
- NextDisplacement += Length;
-
- return Displacement;
-}
-
-uint32_t
-SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) {
- MCSymbol *Sym;
- if (MO.getType() == MachineOperand::MO_GlobalAddress) {
- const GlobalValue *GV = MO.getGlobal();
- Sym = MO.getParent()->getMF()->getTarget().getSymbol(GV);
- assert(Sym && "No symbol");
- } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) {
- const char *SymName = MO.getSymbolName();
- Sym = MO.getParent()->getMF()->getContext().getOrCreateSymbol(SymName);
- assert(Sym && "No symbol");
- } else
- llvm_unreachable("Unexpected operand type");
-
- unsigned ADAslotType = MO.getTargetFlags();
- return insert(Sym, ADAslotType);
-}
-
void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),
getSubtargetInfo().getFeatureBits());
@@ -258,13 +148,6 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
.addReg(SystemZ::R14D);
break;
- case SystemZ::Return_XPLINK:
- LoweredMI = MCInstBuilder(SystemZ::B)
- .addReg(SystemZ::R7D)
- .addImm(2)
- .addReg(0);
- break;
-
case SystemZ::CondReturn:
LoweredMI = MCInstBuilder(SystemZ::BCR)
.addImm(MI->getOperand(0).getImm())
@@ -272,15 +155,6 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
.addReg(SystemZ::R14D);
break;
- case SystemZ::CondReturn_XPLINK:
- LoweredMI = MCInstBuilder(SystemZ::BC)
- .addImm(MI->getOperand(0).getImm())
- .addImm(MI->getOperand(1).getImm())
- .addReg(SystemZ::R7D)
- .addImm(2)
- .addReg(0);
- break;
-
case SystemZ::CRBReturn:
LoweredMI = MCInstBuilder(SystemZ::CRB)
.addReg(MI->getOperand(0).getReg())
@@ -353,90 +227,6 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
.addImm(0);
break;
- case SystemZ::CallBRASL_XPLINK64:
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R7D)
- .addExpr(Lower.getExpr(MI->getOperand(0),
- SystemZ::S_None)));
- emitCallInformation(CallType::BRASL7);
- return;
-
- case SystemZ::CallBASR_XPLINK64:
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
- .addReg(SystemZ::R7D)
- .addReg(MI->getOperand(0).getReg()));
- emitCallInformation(CallType::BASR76);
- return;
-
- case SystemZ::CallBASR_STACKEXT:
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
- .addReg(SystemZ::R3D)
- .addReg(MI->getOperand(0).getReg()));
- emitCallInformation(CallType::BASR33);
- return;
-
- case SystemZ::ADA_ENTRY_VALUE:
- case SystemZ::ADA_ENTRY: {
- const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
- const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
- uint32_t Disp = ADATable.insert(MI->getOperand(1));
- Register TargetReg = MI->getOperand(0).getReg();
-
- Register ADAReg = MI->getOperand(2).getReg();
- Disp += MI->getOperand(3).getImm();
- bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY;
-
- unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG;
- unsigned Op = TII->getOpcodeForOffset(Op0, Disp);
-
- Register IndexReg = 0;
- if (!Op) {
- if (TargetReg != ADAReg) {
- IndexReg = TargetReg;
- // Use TargetReg to store displacement.
- EmitToStreamer(
- *OutStreamer,
- MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
- } else
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::ALGFI)
- .addReg(TargetReg)
- .addReg(TargetReg)
- .addImm(Disp));
- Disp = 0;
- Op = Op0;
- }
- EmitToStreamer(*OutStreamer, MCInstBuilder(Op)
- .addReg(TargetReg)
- .addReg(ADAReg)
- .addImm(Disp)
- .addReg(IndexReg));
-
- return;
- }
- case SystemZ::CallBRASL:
- LoweredMI = MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R14D)
- .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT));
- break;
-
- case SystemZ::CallBASR:
- LoweredMI = MCInstBuilder(SystemZ::BASR)
- .addReg(SystemZ::R14D)
- .addReg(MI->getOperand(0).getReg());
- break;
-
- case SystemZ::CallJG:
- LoweredMI = MCInstBuilder(SystemZ::JG)
- .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT));
- break;
-
- case SystemZ::CallBRCL:
- LoweredMI = MCInstBuilder(SystemZ::BRCL)
- .addImm(MI->getOperand(0).getImm())
- .addImm(MI->getOperand(1).getImm())
- .addExpr(Lower.getExpr(MI->getOperand(2), SystemZ::S_PLT));
- break;
-
case SystemZ::CallBR:
LoweredMI = MCInstBuilder(SystemZ::BR)
.addReg(MI->getOperand(0).getReg());
@@ -521,28 +311,6 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
.addImm(0);
break;
- case SystemZ::TLS_GDCALL:
- LoweredMI =
- MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R14D)
- .addExpr(getTLSGetOffset(MF->getContext()))
- .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSGD));
- break;
-
- case SystemZ::TLS_LDCALL:
- LoweredMI =
- MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R14D)
- .addExpr(getTLSGetOffset(MF->getContext()))
- .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSLDM));
- break;
-
- case SystemZ::GOT:
- LoweredMI = MCInstBuilder(SystemZ::LARL)
- .addReg(MI->getOperand(0).getReg())
- .addExpr(getGlobalOffsetTable(MF->getContext()));
- break;
-
case SystemZ::IILF64:
LoweredMI = MCInstBuilder(SystemZ::IILF)
.addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
@@ -713,26 +481,6 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
}
break;
- case TargetOpcode::FENTRY_CALL:
- LowerFENTRY_CALL(*MI, Lower);
- return;
-
- case TargetOpcode::STACKMAP:
- LowerSTACKMAP(*MI);
- return;
-
- case TargetOpcode::PATCHPOINT:
- LowerPATCHPOINT(*MI, Lower);
- return;
-
- case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
- LowerPATCHABLE_FUNCTION_ENTER(*MI, Lower);
- return;
-
- case TargetOpcode::PATCHABLE_RET:
- LowerPATCHABLE_RET(*MI, Lower);
- return;
-
case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");
@@ -778,13 +526,6 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
case SystemZ::EH_SjLj_Setup:
return;
- case SystemZ::LOAD_TLS_BLOCK_ADDR:
- lowerLOAD_TLS_BLOCK_ADDR(*MI, Lower);
- return;
- case SystemZ::LOAD_GLOBAL_STACKGUARD_ADDR:
- lowerLOAD_GLOBAL_STACKGUARD_ADDR(*MI, Lower);
- return;
-
default:
Lower.lower(MI, LoweredMI);
break;
@@ -792,411 +533,6 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, LoweredMI);
}
-// Emit the largest nop instruction smaller than or equal to NumBytes
-// bytes. Return the size of nop emitted.
-static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
- unsigned NumBytes, const MCSubtargetInfo &STI) {
- if (NumBytes < 2) {
- llvm_unreachable("Zero nops?");
- return 0;
- }
- else if (NumBytes < 4) {
- OutStreamer.emitInstruction(
- MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
- return 2;
- }
- else if (NumBytes < 6) {
- OutStreamer.emitInstruction(
- MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
- STI);
- return 4;
- }
- else {
- MCSymbol *DotSym = OutContext.createTempSymbol();
- const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
- OutStreamer.emitLabel(DotSym);
- OutStreamer.emitInstruction(
- MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
- return 6;
- }
-}
-
-void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
- SystemZMCInstLower &Lower) {
- MCContext &Ctx = MF->getContext();
- if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
- MCSymbol *DotSym = OutContext.createTempSymbol();
- OutStreamer->pushSection();
- OutStreamer->switchSection(
- Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
- OutStreamer->emitSymbolValue(DotSym, 8);
- OutStreamer->popSection();
- OutStreamer->emitLabel(DotSym);
- }
-
- if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
- EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
- return;
- }
-
- MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
- const MCSymbolRefExpr *Op =
- MCSymbolRefExpr::create(fentry, SystemZ::S_PLT, Ctx);
- OutStreamer->emitInstruction(
- MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
- getSubtargetInfo());
-}
-
-void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
- auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();
-
- unsigned NumNOPBytes = MI.getOperand(1).getImm();
-
- auto &Ctx = OutStreamer->getContext();
- MCSymbol *MILabel = Ctx.createTempSymbol();
- OutStreamer->emitLabel(MILabel);
-
- SM.recordStackMap(*MILabel, MI);
- assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
-
- // Scan ahead to trim the shadow.
- unsigned ShadowBytes = 0;
- const MachineBasicBlock &MBB = *MI.getParent();
- MachineBasicBlock::const_iterator MII(MI);
- ++MII;
- while (ShadowBytes < NumNOPBytes) {
- if (MII == MBB.end() ||
- MII->getOpcode() == TargetOpcode::PATCHPOINT ||
- MII->getOpcode() == TargetOpcode::STACKMAP)
- break;
- ShadowBytes += TII->getInstSizeInBytes(*MII);
- if (MII->isCall())
- break;
- ++MII;
- }
-
- // Emit nops.
- while (ShadowBytes < NumNOPBytes)
- ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
- getSubtargetInfo());
-}
-
-// Lower a patchpoint of the form:
-// [<def>], <id>, <numBytes>, <target>, <numArgs>
-void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
- SystemZMCInstLower &Lower) {
- auto &Ctx = OutStreamer->getContext();
- MCSymbol *MILabel = Ctx.createTempSymbol();
- OutStreamer->emitLabel(MILabel);
-
- SM.recordPatchPoint(*MILabel, MI);
- PatchPointOpers Opers(&MI);
-
- unsigned EncodedBytes = 0;
- const MachineOperand &CalleeMO = Opers.getCallTarget();
-
- if (CalleeMO.isImm()) {
- uint64_t CallTarget = CalleeMO.getImm();
- if (CallTarget) {
- unsigned ScratchIdx = -1;
- unsigned ScratchReg = 0;
- do {
- ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
- ScratchReg = MI.getOperand(ScratchIdx).getReg();
- } while (ScratchReg == SystemZ::R0D);
-
- // Materialize the call target address
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
- .addReg(ScratchReg)
- .addImm(CallTarget & 0xFFFFFFFF));
- EncodedBytes += 6;
- if (CallTarget >> 32) {
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
- .addReg(ScratchReg)
- .addImm(CallTarget >> 32));
- EncodedBytes += 6;
- }
-
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
- .addReg(SystemZ::R14D)
- .addReg(ScratchReg));
- EncodedBytes += 2;
- }
- } else if (CalleeMO.isGlobal()) {
- const MCExpr *Expr = Lower.getExpr(CalleeMO, SystemZ::S_PLT);
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R14D)
- .addExpr(Expr));
- EncodedBytes += 6;
- }
-
- // Emit padding.
- unsigned NumBytes = Opers.getNumPatchBytes();
- assert(NumBytes >= EncodedBytes &&
- "Patchpoint can't request size less than the length of a call.");
- assert((NumBytes - EncodedBytes) % 2 == 0 &&
- "Invalid number of NOP bytes requested!");
- while (EncodedBytes < NumBytes)
- EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
- getSubtargetInfo());
-}
-
-void SystemZAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
- const MachineInstr &MI, SystemZMCInstLower &Lower) {
-
- const MachineFunction &MF = *(MI.getParent()->getParent());
- const Function &F = MF.getFunction();
-
- // If patchable-function-entry is set, emit in-function nops here.
- if (F.hasFnAttribute("patchable-function-entry")) {
- // get M-N from function attribute (CodeGenFunction subtracts N
- // from M to yield the correct patchable-function-entry).
- unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry");
- // Emit M-N 2-byte nops. Use getNop() here instead of emitNops()
- // to keep it aligned with the common code implementation emitting
- // the prefix nops.
- for (unsigned I = 0; I < Num; ++I)
- EmitToStreamer(*OutStreamer, MF.getSubtarget().getInstrInfo()->getNop());
- return;
- }
- // Otherwise, emit xray sled.
- // .begin:
- // j .end # -> stmg %r2, %r15, 16(%r15)
- // nop
- // llilf %2, FuncID
- // brasl %r14, __xray_FunctionEntry at GOT
- // .end:
- //
- // Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number
- // of instructions change.
- bool HasVectorFeature =
- TM.getMCSubtargetInfo().hasFeature(SystemZ::FeatureVector) &&
- !TM.getMCSubtargetInfo().hasFeature(SystemZ::FeatureSoftFloat);
- MCSymbol *FuncEntry = OutContext.getOrCreateSymbol(
- HasVectorFeature ? "__xray_FunctionEntryVec" : "__xray_FunctionEntry");
- MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_", true);
- MCSymbol *EndOfSled = OutContext.createTempSymbol();
- OutStreamer->emitLabel(BeginOfSled);
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::J)
- .addExpr(MCSymbolRefExpr::create(EndOfSled, OutContext)));
- EmitNop(OutContext, *OutStreamer, 2, getSubtargetInfo());
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R14D)
- .addExpr(MCSymbolRefExpr::create(
- FuncEntry, SystemZ::S_PLT, OutContext)));
- OutStreamer->emitLabel(EndOfSled);
- recordSled(BeginOfSled, MI, SledKind::FUNCTION_ENTER, 2);
-}
-
-void SystemZAsmPrinter::LowerPATCHABLE_RET(const MachineInstr &MI,
- SystemZMCInstLower &Lower) {
- unsigned OpCode = MI.getOperand(0).getImm();
- MCSymbol *FallthroughLabel = nullptr;
- if (OpCode == SystemZ::CondReturn) {
- FallthroughLabel = OutContext.createTempSymbol();
- int64_t Cond0 = MI.getOperand(1).getImm();
- int64_t Cond1 = MI.getOperand(2).getImm();
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRC)
- .addImm(Cond0)
- .addImm(Cond1 ^ Cond0)
- .addExpr(MCSymbolRefExpr::create(
- FallthroughLabel, OutContext)));
- }
- // .begin:
- // br %r14 # -> stmg %r2, %r15, 24(%r15)
- // nop
- // nop
- // llilf %2,FuncID
- // j __xray_FunctionExit at GOT
- //
- // Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number
- // of instructions change.
- bool HasVectorFeature =
- TM.getMCSubtargetInfo().hasFeature(SystemZ::FeatureVector) &&
- !TM.getMCSubtargetInfo().hasFeature(SystemZ::FeatureSoftFloat);
- MCSymbol *FuncExit = OutContext.getOrCreateSymbol(
- HasVectorFeature ? "__xray_FunctionExitVec" : "__xray_FunctionExit");
- MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_", true);
- OutStreamer->emitLabel(BeginOfSled);
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D));
- EmitNop(OutContext, *OutStreamer, 4, getSubtargetInfo());
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::J)
- .addExpr(MCSymbolRefExpr::create(
- FuncExit, SystemZ::S_PLT, OutContext)));
- if (FallthroughLabel)
- OutStreamer->emitLabel(FallthroughLabel);
- recordSled(BeginOfSled, MI, SledKind::FUNCTION_EXIT, 2);
-}
-
-void SystemZAsmPrinter::lowerLOAD_TLS_BLOCK_ADDR(const MachineInstr &MI,
- SystemZMCInstLower &Lower) {
- Register AddrReg = MI.getOperand(0).getReg();
- const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
-
- // EAR can only load the low subregister so use a shift for %a0 to produce
- // the GR containing %a0 and %a1.
- const Register Reg32 =
- MRI.getTargetRegisterInfo()->getSubReg(AddrReg, SystemZ::subreg_l32);
-
- // ear <reg>, %a0
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::EAR).addReg(Reg32).addReg(SystemZ::A0));
-
- // sllg <reg>, <reg>, 32
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::SLLG)
- .addReg(AddrReg)
- .addReg(AddrReg)
- .addReg(0)
- .addImm(32));
-
- // ear <reg>, %a1
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::EAR).addReg(Reg32).addReg(SystemZ::A1));
-}
-
-void SystemZAsmPrinter::lowerLOAD_GLOBAL_STACKGUARD_ADDR(
- const MachineInstr &MI, SystemZMCInstLower &Lower) {
- Register AddrReg = MI.getOperand(0).getReg();
- const MachineFunction &MF = *(MI.getParent()->getParent());
- const Module *M = MF.getFunction().getParent();
- const TargetLowering *TLI = MF.getSubtarget().getTargetLowering();
-
- // Obtain the global value (assert if stack guard variable can't be found).
- const GlobalVariable *GV = cast<GlobalVariable>(
- TLI->getSDagStackGuard(*M, TLI->getLibcallLoweringInfo()));
-
- // If configured, emit the `__stack_protector_loc` entry
- if (M->hasStackProtectorGuardRecord()) {
- MCSymbol *Sym = OutContext.createTempSymbol();
- OutStreamer->pushSection();
- OutStreamer->switchSection(OutContext.getELFSection(
- "__stack_protector_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
- OutStreamer->emitSymbolValue(Sym, getDataLayout().getPointerSize());
- OutStreamer->popSection();
- OutStreamer->emitLabel(Sym);
- }
- // Emit the address load.
- if (M->getPICLevel() == PICLevel::NotPIC) {
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LARL)
- .addReg(AddrReg)
- .addExpr(MCSymbolRefExpr::create(
- getSymbol(GV), OutContext)));
- } else {
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::LGRL)
- .addReg(AddrReg)
- .addExpr(MCSymbolRefExpr::create(
- getSymbol(GV), SystemZ::S_GOTENT, OutContext)));
- }
-}
-
-// The *alignment* of 128-bit vector types is different between the software
-// and hardware vector ABIs. If the there is an externally visible use of a
-// vector type in the module it should be annotated with an attribute.
-void SystemZAsmPrinter::emitAttributes(Module &M) {
- if (M.getModuleFlag("s390x-visible-vector-ABI")) {
- bool HasVectorFeature =
- TM.getMCSubtargetInfo().hasFeature(SystemZ::FeatureVector);
- OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1);
- }
-}
-
-// Convert a SystemZ-specific constant pool modifier into the associated
-// specifier.
-static uint8_t getSpecifierFromModifier(SystemZCP::SystemZCPModifier Modifier) {
- switch (Modifier) {
- case SystemZCP::TLSGD:
- return SystemZ::S_TLSGD;
- case SystemZCP::TLSLDM:
- return SystemZ::S_TLSLDM;
- case SystemZCP::DTPOFF:
- return SystemZ::S_DTPOFF;
- case SystemZCP::NTPOFF:
- return SystemZ::S_NTPOFF;
- }
- llvm_unreachable("Invalid SystemCPModifier!");
-}
-
-void SystemZAsmPrinter::emitMachineConstantPoolValue(
- MachineConstantPoolValue *MCPV) {
- auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
-
- const MCExpr *Expr = MCSymbolRefExpr::create(
- getSymbol(ZCPV->getGlobalValue()),
- getSpecifierFromModifier(ZCPV->getModifier()), OutContext);
- uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
-
- OutStreamer->emitValue(Expr, Size);
-}
-
-// Emit the ctor or dtor list taking into account the init priority.
-void SystemZAsmPrinter::emitXXStructorList(const DataLayout &DL,
- const Constant *List, bool IsCtor) {
- if (!TM.getTargetTriple().isOSBinFormatGOFF())
- return AsmPrinter::emitXXStructorList(DL, List, IsCtor);
-
- SmallVector<Structor, 8> Structors;
- preprocessXXStructorList(DL, List, Structors);
- if (Structors.empty())
- return;
-
- const Align Align = llvm::Align(4);
- const TargetLoweringObjectFileGOFF &Obj =
- static_cast<const TargetLoweringObjectFileGOFF &>(getObjFileLowering());
- for (Structor &S : Structors) {
- MCSectionGOFF *Section =
- static_cast<MCSectionGOFF *>(Obj.getStaticXtorSection(S.Priority));
- OutStreamer->switchSection(Section);
- if (OutStreamer->getCurrentSection() != OutStreamer->getPreviousSection())
- emitAlignment(Align);
-
- // The priority is provided as an input to getStaticXtorSection(), and is
- // recalculated within that function as `Prio` going to going into the
- // PR section.
- // This priority retrieved via the `SortKey` below is the recalculated
- // Priority.
- uint32_t XtorPriority = Section->getPRAttributes().SortKey;
-
- const GlobalValue *GV = dyn_cast<GlobalValue>(S.Func->stripPointerCasts());
- assert(GV && "C++ xxtor pointer was not a GlobalValue!");
- MCSymbolGOFF *Symbol = static_cast<MCSymbolGOFF *>(getSymbol(GV));
-
- // @@SQINIT entry: { unsigned prio; void (*ctor)(); void (*dtor)(); }
-
- unsigned PointerSizeInBytes = DL.getPointerSize();
-
- auto &Ctx = OutStreamer->getContext();
- const MCExpr *ADAFuncRefExpr;
- unsigned SlotKind = SystemZII::MO_ADA_DIRECT_FUNC_DESC;
-
- MCSectionGOFF *ADASection =
- static_cast<MCSectionGOFF *>(Obj.getADASection());
- assert(ADASection && "ADA section must exist for GOFF targets!");
- const MCSymbol *ADASym = ADASection->getBeginSymbol();
- assert(ADASym && "ADA symbol should already be set!");
-
- ADAFuncRefExpr = MCBinaryExpr::createAdd(
- MCSpecifierExpr::create(MCSymbolRefExpr::create(ADASym, OutContext),
- SystemZ::S_QCon, OutContext),
- MCConstantExpr::create(ADATable.insert(Symbol, SlotKind), Ctx), Ctx);
-
- emitInt32(XtorPriority);
- if (IsCtor) {
- OutStreamer->emitValue(ADAFuncRefExpr, PointerSizeInBytes);
- OutStreamer->emitIntValue(0, PointerSizeInBytes);
- } else {
- OutStreamer->emitIntValue(0, PointerSizeInBytes);
- OutStreamer->emitValue(ADAFuncRefExpr, PointerSizeInBytes);
- }
- }
-}
-
static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo,
raw_ostream &OS) {
const char *RegName;
@@ -1293,616 +629,21 @@ bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
return false;
}
-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
- // symbol, for which we use the the ED of the ADA. We also need to mark the
- // reference as being to data, otherwise we cannot bind with code generated
- // by XL.
- for (auto &GO : M.global_objects()) {
- if (auto *GV = dyn_cast<GlobalVariable>(&GO)) {
- if (!GV->hasInitializer()) {
- MCSymbol *Sym = getSymbol(GV);
- ZOS->emitADA(Sym, OutContext.getObjectFileInfo()->getADASection());
- OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeObject);
- }
- }
- }
- }
- emitAttributes(M);
-}
-
-void SystemZAsmPrinter::emitADASection() {
- OutStreamer->pushSection();
-
- 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;
- unsigned SlotKind;
- std::tie(Sym, SlotKind) = Entry.first;
- unsigned Offset = Entry.second;
- assert(Offset == EmittedBytes && "Offset not as expected");
- (void)EmittedBytes;
-#define EMIT_COMMENT(Str) \
- OutStreamer->AddComment(Twine("Offset ") \
- .concat(utostr(Offset)) \
- .concat(" " Str " ") \
- .concat(Sym->getName()));
- switch (SlotKind) {
- case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
- // Language Environment DLL logic requires function descriptors, for
- // imported functions, that are placed in the ADA to be 8 byte aligned.
- EMIT_COMMENT("function descriptor of");
- OutStreamer->emitValue(
- MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
- SystemZ::S_RCon, OutContext),
- PointerSize);
- OutStreamer->emitValue(
- MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
- SystemZ::S_VCon, OutContext),
- PointerSize);
- EmittedBytes += PointerSize * 2;
- break;
- case SystemZII::MO_ADA_DATA_SYMBOL_ADDR:
- EMIT_COMMENT("pointer to data symbol");
- OutStreamer->emitValue(
- MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
- SystemZ::S_None, OutContext),
- PointerSize);
- EmittedBytes += PointerSize;
- break;
- case SystemZII::MO_ADA_INDIRECT_FUNC_DESC: {
- MCSymbol *Alias = OutContext.getOrCreateSymbol(
- Twine(Sym->getName()).concat("@indirect"));
- OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
- OutStreamer->emitSymbolAttribute(Alias, MCSA_ELF_TypeFunction);
- OutStreamer->emitSymbolAttribute(Alias, MCSA_Global);
- OutStreamer->emitSymbolAttribute(Alias, MCSA_Extern);
- MCSymbolGOFF *GOFFSym =
- static_cast<llvm::MCSymbolGOFF *>(const_cast<llvm::MCSymbol *>(Sym));
- ZOS->emitExternalName(Alias, GOFFSym->getExternalName());
- EMIT_COMMENT("pointer to function descriptor");
- OutStreamer->emitValue(
- MCSpecifierExpr::create(MCSymbolRefExpr::create(Alias, OutContext),
- SystemZ::S_VCon, OutContext),
- PointerSize);
- EmittedBytes += PointerSize;
- break;
- }
- default:
- llvm_unreachable("Unexpected slot kind");
- }
-#undef EMIT_COMMENT
- }
- OutStreamer->popSection();
-}
-
-static std::string getProductID(Module &M) {
- std::string ProductID;
- if (auto *MD = M.getModuleFlag("zos_product_id"))
- ProductID = cast<MDString>(MD)->getString().str();
- if (ProductID.empty())
- ProductID = "LLVM";
- return ProductID;
-}
-
-static uint32_t getProductVersion(Module &M) {
- if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("zos_product_major_version")))
- return VersionVal->getZExtValue();
- return LLVM_VERSION_MAJOR;
-}
-
-static uint32_t getProductRelease(Module &M) {
- if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("zos_product_minor_version")))
- return ReleaseVal->getZExtValue();
- return LLVM_VERSION_MINOR;
-}
-
-static uint32_t getProductPatch(Module &M) {
- if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("zos_product_patchlevel")))
- return PatchVal->getZExtValue();
- return LLVM_VERSION_PATCH;
-}
-
-static time_t getTranslationTime(Module &M) {
- std::time_t Time = 0;
- if (auto *Val = mdconst::extract_or_null<ConstantInt>(
- M.getModuleFlag("zos_translation_time"))) {
- long SecondsSinceEpoch = Val->getSExtValue();
- Time = static_cast<time_t>(SecondsSinceEpoch);
- }
- return Time;
-}
-
-void SystemZAsmPrinter::emitIDRLSection(Module &M) {
- OutStreamer->pushSection();
- OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
- constexpr unsigned IDRLDataLength = 30;
- std::time_t Time = getTranslationTime(M);
-
- uint32_t ProductVersion = getProductVersion(M);
- uint32_t ProductRelease = getProductRelease(M);
-
- std::string ProductID = getProductID(M);
-
- SmallString<IDRLDataLength + 1> TempStr;
- raw_svector_ostream O(TempStr);
- O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",
- ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
- llvm::sys::toUtcTime(Time), "0");
- SmallString<IDRLDataLength> Data;
- ConverterEBCDIC::convertToEBCDIC(TempStr, Data);
-
- OutStreamer->emitInt8(0); // Reserved.
- OutStreamer->emitInt8(3); // Format.
- OutStreamer->emitInt16(IDRLDataLength); // Length.
- OutStreamer->emitBytes(Data.str());
- OutStreamer->popSection();
-}
-
-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<SystemZTargetzOSStreamer *>(getTargetStreamer());
- OutStreamer->emitLabel(ZOS->DeferredPPA1.back().FnEnd);
- }
-}
-
-// 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,
- MCSymbol *&EndOfPrologSym,
- MCSymbol *&StackUpdateSym) {
- EndOfPrologSym = nullptr;
- StackUpdateSym = nullptr;
-
- // Scan the basic block for the FENCE instruction which marks the end
- // of the prologue. We know
- // the prologue is spread at most across the first 3 basic blocks. Also record
- // the first instruction updating the stack pointer.
- const SystemZSubtarget &STI = MF->getSubtarget<SystemZSubtarget>();
- auto &Regs = STI.getSpecialRegisters<SystemZXPLINK64Registers>();
- MachineInstr *EndOfPrologMI = nullptr;
- MachineInstr *StackUpdateMI = nullptr;
- unsigned BBCount = 1;
-
- for (auto &MBB : *MF) {
- for (auto &I : MBB) {
- if (I.getOpcode() == SystemZ::FENCE)
- EndOfPrologMI = &I;
- else if (!StackUpdateMI) {
- unsigned Opcode = I.getOpcode();
- // TODO: We can instead emit a pseudo instruction in
- // SystemZFrameLowering to represent a stack adjustment instruction, and
- // check for that here, instead of having to check for multiple
- // instructions.
- if ((Opcode == SystemZ::AGHI || Opcode == SystemZ::AGFI) &&
- I.getOperand(0).getReg() == Regs.getStackPointerRegister())
- StackUpdateMI = &I;
- }
- }
-
- // Prologue can be a max of 3 BBs if we need to call stack extension code
- if (EndOfPrologMI || BBCount == 3)
- break;
-
- ++BBCount;
- }
-
- // Leaf functions do not have a prologue.
- if (EndOfPrologMI == nullptr)
- return;
-
-#ifdef EXPENSIVE_CHECKS
- // Check that the prolog length is valid.
- auto *TII = STI.getInstrInfo();
- size_t Size = 0;
-
- for (auto &MBB : *MF) {
- bool TerminateLoop = false;
- for (auto &I : MBB) {
- Size += TII->getInstSizeInBytes(I);
- if (&I == EndOfPrologMI) {
- TerminateLoop = true;
- break;
- }
- }
- if (TerminateLoop)
- break;
- }
- if (Size > 128)
- report_fatal_error(
- Twine(MF->getName()).concat(": Prolog exceeds 128 bytes"));
-#endif
-
- // Attach a temporary symbol to mark the end of the prolog.
- EndOfPrologSym = MF->getContext().createTempSymbol("end_of_prologue");
- EndOfPrologMI->setPostInstrSymbol(*MF, EndOfPrologSym);
-
- if (StackUpdateMI) {
- StackUpdateSym = MF->getContext().createTempSymbol("stack_update");
- StackUpdateMI->setPreInstrSymbol(*MF, StackUpdateSym);
- }
-}
-
-void SystemZAsmPrinter::calculatePPA1() {
- auto *ZOS = static_cast<SystemZTargetzOSStreamer *>(getTargetStreamer());
- assert(ZOS->PPA2Sym != nullptr && "PPA2 Symbol not defined");
-
- SystemZTargetzOSStreamer::PPA1Info Info;
-
- const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
- const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
-
- 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");
-
- 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());
- PersonalityRoutine = Per ? MF->getTarget().getSymbol(Per) : nullptr;
- if (PersonalityRoutine) {
- 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 _.
- std::string N(MF->getFunction().hasName()
- ? Twine(MF->getFunction().getName()).concat("_").str()
- : "");
-
- // Calculate the lables for the prolog size and the stack update symbol.
- MCSymbol *EndOfPrologSym;
- MCSymbol *StackUpdateSym;
- determinePrologueStackUpdateSym(MF, EndOfPrologSym, StackUpdateSym);
-
- // Save the calculated values.
- if (MF->getFunction().hasFnAttribute("zos-ppa1-name"))
- Info.Name =
- MF->getFunction().getFnAttribute("zos-ppa1-name").getValueAsString();
- else if (MF->getFunction().hasName())
- Info.Name = MF->getFunction().getName();
-
- Info.PPA1 = OutContext.createTempSymbol(Twine("PPA1_").concat(N), true);
- Info.EPMarker = OutContext.createTempSymbol(Twine("EPM_").concat(N), true);
- Info.FnEnd = OutContext.createTempSymbol(Twine(N).concat("end_"));
- Info.Fn = CurrentFnSym;
- Info.EndOfProlog = EndOfPrologSym;
- Info.StackUpdate = StackUpdateSym;
- Info.PersonalityADADisp = PersonalityADADisp;
- Info.GCCEHADADisp = GCCEHADADisp;
- Info.OffsetFPR = OffsetFPR;
- Info.OffsetVR = OffsetVR;
- Info.CallFrameSize = MFFrame.getMaxCallFrameSize();
- Info.SizeOfFnParams = ZFI->getSizeOfFnParams();
- Info.SavedGPRMask = SavedGPRMask;
- Info.SavedFPRMask = SavedFPRMask;
- Info.SavedVRMask = SavedVRMask;
- Info.FrameReg = FrameReg;
- Info.AllocaReg = AllocaReg;
- Info.IsVarArg = MF->getFunction().isVarArg();
- Info.HasStackProtector = MFFrame.hasStackProtectorIndex();
-
- ZOS->DeferredPPA1.push_back(Info);
-}
-
-void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
- if (TM.getTargetTriple().isOSzOS())
- emitPPA2(M);
- AsmPrinter::emitStartOfAsmFile(M);
-}
-
-void SystemZAsmPrinter::emitPPA2(Module &M) {
- auto *ZOS = static_cast<SystemZTargetzOSStreamer *>(getTargetStreamer());
- OutStreamer->pushSection();
- OutStreamer->switchSection(getObjFileLowering().getTextSection());
- MCContext &OutContext = OutStreamer->getContext();
- // Make CELQSTRT symbol.
- const char *StartSymbolName = "CELQSTRT";
- MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
- OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_OSLinkage);
- OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Global);
-
- // 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);
- SmallString<14> CompilationTimeEBCDIC, CompilationTime;
- CompilationTime = formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));
-
- uint32_t ProductVersion = getProductVersion(M),
- ProductRelease = getProductRelease(M),
- ProductPatch = getProductPatch(M);
-
- SmallString<6> VersionEBCDIC, Version;
- Version = formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion,
- ProductRelease, ProductPatch);
-
- ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeEBCDIC);
- ConverterEBCDIC::convertToEBCDIC(Version, VersionEBCDIC);
-
- enum class PPA2MemberId : uint8_t {
- // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for
- // complete list. Only the C runtime is supported by this backend.
- LE_C_Runtime = 3,
- };
- enum class PPA2MemberSubId : uint8_t {
- // List of languages using the LE C runtime implementation.
- C = 0x00,
- CXX = 0x01,
- Swift = 0x03,
- Go = 0x60,
- LLVMBasedLang = 0xe7,
- };
- // PPA2 Flags
- enum class PPA2Flags : uint8_t {
- CompileForBinaryFloatingPoint = 0x80,
- CompiledWithXPLink = 0x01,
- CompiledUnitASCII = 0x04,
- HasServiceInfo = 0x20,
- };
-
- PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang;
- if (auto *MD = M.getModuleFlag("zos_cu_language")) {
- StringRef Language = cast<MDString>(MD)->getString();
- MemberSubId = StringSwitch<PPA2MemberSubId>(Language)
- .Case("C", PPA2MemberSubId::C)
- .Case("C++", PPA2MemberSubId::CXX)
- .Case("Swift", PPA2MemberSubId::Swift)
- .Case("Go", PPA2MemberSubId::Go)
- .Default(PPA2MemberSubId::LLVMBasedLang);
- }
-
- // Emit PPA2 section.
- OutStreamer->emitLabel(PPA2Sym);
- OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime));
- OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId));
- OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env
- OutStreamer->emitInt8(0x04); // Control level 4 (XPLink)
- OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4);
- OutStreamer->emitInt32(0x00000000);
- OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4);
- OutStreamer->emitInt32(
- 0x00000000); // Offset to main entry point, always 0 (so says TR).
- uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint);
- Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink);
-
- bool IsASCII = true;
- if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {
- const StringRef &CharMode = cast<MDString>(MD)->getString();
- if (CharMode == "ebcdic")
- IsASCII = false;
- else if (CharMode != "ascii")
- OutContext.reportError(
- {}, "Only ascii or ebcdic are allowed for zos_le_char_mode");
- }
- if (IsASCII)
- Flgs |= static_cast<uint8_t>(
- PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.
-
- OutStreamer->emitInt8(Flgs);
- OutStreamer->emitInt8(0x00); // Reserved.
- // No MD5 signature before timestamp.
- // No FLOAT(AFP(VOLATILE)).
- // Remaining 5 flag bits reserved.
- OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits.
-
- // Emit date and version section.
- OutStreamer->emitLabel(DateVersionSym);
- OutStreamer->emitBytes(CompilationTimeEBCDIC.str());
- OutStreamer->emitBytes(VersionEBCDIC.str());
-
- OutStreamer->emitInt16(0x0000); // Service level string length.
-
- // The binder requires that the offset to the PPA2 be emitted in a different,
- // specially-named section.
- OutStreamer->switchSection(getObjFileLowering().getPPA2ListSection());
- // Emit 8 byte alignment.
- // Emit pointer to PPA2 label.
- OutStreamer->AddComment("A(PPA2-CELQSTRT)");
- OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);
- OutStreamer->popSection();
-}
-
-void SystemZAsmPrinter::emitGlobalAlias(const Module &M,
- const GlobalAlias &GA) {
- if (!TM.getTargetTriple().isOSzOS())
- return AsmPrinter::emitGlobalAlias(M, GA);
-
- // Aliased function labels have already been emitted for z/OS
-}
-
-const MCExpr *SystemZAsmPrinter::lowerConstant(const Constant *CV,
- const Constant *BaseCV,
- uint64_t Offset) {
- const Triple &TargetTriple = TM.getTargetTriple();
-
- if (TargetTriple.isOSzOS()) {
- const GlobalAlias *GA = dyn_cast<GlobalAlias>(CV);
- const GlobalVariable *GV = dyn_cast<GlobalVariable>(CV);
- const Function *FV = dyn_cast<Function>(CV);
- bool IsFunc = !GV && (FV || (GA && isa<Function>(GA->getAliaseeObject())));
-
- MCSymbol *Sym = NULL;
-
- if (GA)
- Sym = getSymbol(GA);
- else if (IsFunc)
- Sym = getSymbol(FV);
- else if (GV)
- Sym = getSymbol(GV);
-
- if (IsFunc) {
- OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
- if (FV->hasExternalLinkage())
- return MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
- SystemZ::S_VCon, OutContext);
- // Trigger creation of function descriptor in ADA for internal
- // functions.
- unsigned Disp = ADATable.insert(Sym, SystemZII::MO_ADA_DIRECT_FUNC_DESC);
- return MCBinaryExpr::createAdd(
- MCSpecifierExpr::create(
- MCSymbolRefExpr::create(
- getObjFileLowering().getADASection()->getBeginSymbol(),
- OutContext),
- SystemZ::S_None, OutContext),
- MCConstantExpr::create(Disp, OutContext), OutContext);
- }
- if (Sym) {
- OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeObject);
- return MCSymbolRefExpr::create(Sym, OutContext);
- }
- }
- return AsmPrinter::lowerConstant(CV);
-}
-
-void SystemZAsmPrinter::emitFunctionEntryLabel() {
- const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
-
- if (Subtarget.getTargetTriple().isOSzOS()) {
- auto *ZOS = static_cast<SystemZTargetzOSStreamer *>(getTargetStreamer());
- calculatePPA1();
-
- // EntryPoint Marker
- const MachineFrameInfo &MFFrame = MF->getFrameInfo();
- bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
- uint32_t DSASize = MFFrame.getStackSize();
- bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
-
- // Set Flags.
- uint8_t Flags = 0;
- if (IsLeaf)
- Flags |= 0x08;
- if (IsUsingAlloca)
- Flags |= 0x04;
-
- // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
- uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
- DSAAndFlags |= Flags;
-
- // Emit entry point marker section.
- OutStreamer->AddComment("XPLINK Routine Layout Entry");
- 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(ZOS->DeferredPPA1.back().PPA1,
- ZOS->DeferredPPA1.back().EPMarker, 4);
- if (OutStreamer->isVerboseAsm()) {
- OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
- OutStreamer->AddComment("Entry Flags");
- if (Flags & 0x08)
- OutStreamer->AddComment(" Bit 1: 1 = Leaf function");
- else
- OutStreamer->AddComment(" Bit 1: 0 = Non-leaf function");
- if (Flags & 0x04)
- OutStreamer->AddComment(" Bit 2: 1 = Uses alloca");
- else
- OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca");
- }
- OutStreamer->emitInt32(DSAAndFlags);
-
- ZOS->emitADA(CurrentFnSym, getObjFileLowering().getADASection());
- }
-
- AsmPrinter::emitFunctionEntryLabel();
-
- if (Subtarget.getTargetTriple().isOSzOS()) {
- const Function *F = &MF->getFunction();
- // Emit aliasing label for function entry point label.
- for (const GlobalAlias *Alias : GOAliasMap[F]) {
- MCSymbol *Sym = getSymbol(Alias);
- OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
- emitVisibility(Sym, Alias->getVisibility());
- emitLinkage(Alias, Sym);
- OutStreamer->emitLabel(Sym);
- }
- }
-}
-
char SystemZAsmPrinter::ID = 0;
INITIALIZE_PASS(SystemZAsmPrinter, "systemz-asm-printer",
"SystemZ Assembly Printer", false, false)
+static AsmPrinter *createSystemZAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> &&Streamer) {
+ if (TM.getTargetTriple().isOSzOS())
+ return new SystemZXPLINKAsmPrinter(TM, std::move(Streamer));
+ return new SystemZELFAsmPrinter(TM, std::move(Streamer));
+}
+
// Force static initialization.
extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeSystemZAsmPrinter() {
- RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
+ TargetRegistry::RegisterAsmPrinter(getTheSystemZTarget(),
+ createSystemZAsmPrinter);
}
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
index fa111fa43eed7..a3bc050110d26 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
@@ -19,100 +19,28 @@
#include "llvm/Support/Compiler.h"
namespace llvm {
+class MCExpr;
class MCStreamer;
class MachineInstr;
class Module;
class raw_ostream;
class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
-public:
- static char ID;
-
-private:
SystemZTargetStreamer *getTargetStreamer() {
MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
assert(TS && "do not have a target streamer");
return static_cast<SystemZTargetStreamer *>(TS);
}
- /// Call type information for XPLINK.
- enum class CallType {
- BASR76 = 0, // b'x000' == BASR r7,r6
- BRAS7 = 1, // b'x001' == BRAS r7,ep
- RESVD_2 = 2, // b'x010'
- BRASL7 = 3, // b'x011' == BRASL r7,ep
- RESVD_4 = 4, // b'x100'
- RESVD_5 = 5, // b'x101'
- BALR1415 = 6, // b'x110' == BALR r14,r15
- BASR33 = 7, // b'x111' == BASR r3,r3
- };
-
- // The Associated Data Area (ADA) contains descriptors which help locating
- // external symbols. For each symbol and type, the displacement into the ADA
- // is stored.
- class AssociatedDataAreaTable {
- public:
- using DisplacementTable =
- MapVector<std::pair<const MCSymbol *, unsigned>, uint32_t>;
-
- private:
- const uint64_t PointerSize;
-
- /// The mapping of name/slot type pairs to displacements.
- DisplacementTable Displacements;
-
- /// The next available displacement value. Incremented when new entries into
- /// the ADA are created.
- uint32_t NextDisplacement = 0;
-
- public:
- AssociatedDataAreaTable(uint64_t PointerSize) : PointerSize(PointerSize) {}
-
- /// @brief Add a function descriptor to the ADA.
- /// @param MI Pointer to an ADA_ENTRY instruction.
- /// @return The displacement of the descriptor into the ADA.
- uint32_t insert(const MachineOperand MO);
-
- /// @brief Get the displacement into associated data area (ADA) for a name.
- /// If no displacement is already associated with the name, assign one and
- /// return it.
- /// @param Sym The symbol for which the displacement should be returned.
- /// @param SlotKind The ADA type.
- /// @return The displacement of the descriptor into the ADA.
- uint32_t insert(const MCSymbol *Sym, unsigned SlotKind);
-
- /// Get the table of GOFF displacements. This is 'const' since it should
- /// never be modified by anything except the APIs on this class.
- const DisplacementTable &getTable() const { return Displacements; }
-
- uint32_t getNextDisplacement() const { return NextDisplacement; }
- };
-
- AssociatedDataAreaTable ADATable;
-
- // Record a list of GlobalAlias associated with a GlobalObject.
- // This is used for z/OS's extra-label-at-definition aliasing strategy.
- // This is similar to what is done for AIX.
- DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>
- GOAliasMap;
-
- void calculatePPA1();
- void emitPPA2(Module &M);
- void emitADASection();
- void emitIDRLSection(Module &M);
-
public:
+ static char ID;
+
SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
- : AsmPrinter(TM, std::move(Streamer), ID),
- ADATable(TM.getPointerSize(0)) {}
+ : AsmPrinter(TM, std::move(Streamer), ID) {}
// Override AsmPrinter.
StringRef getPassName() const override { return "SystemZ Assembly Printer"; }
void emitInstruction(const MachineInstr *MI) override;
- void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
- void emitXXStructorList(const DataLayout &DL, const Constant *List,
- bool IsCtor) override;
- void emitEndOfAsmFile(Module &M) override;
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
const char *ExtraCode, raw_ostream &OS) override;
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
@@ -126,29 +54,6 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
return false;
}
-
- bool doInitialization(Module &M) override;
- void emitFunctionEntryLabel() override;
- void emitFunctionBodyEnd() override;
- void emitStartOfAsmFile(Module &M) override;
- void emitGlobalAlias(const Module &M, const GlobalAlias &GA) override;
- const MCExpr *lowerConstant(const Constant *CV,
- const Constant *BaseCV = nullptr,
- uint64_t Offset = 0) override;
-
-private:
- void emitCallInformation(CallType CT);
- void LowerFENTRY_CALL(const MachineInstr &MI, SystemZMCInstLower &MCIL);
- void LowerSTACKMAP(const MachineInstr &MI);
- void LowerPATCHPOINT(const MachineInstr &MI, SystemZMCInstLower &Lower);
- void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI,
- SystemZMCInstLower &Lower);
- void LowerPATCHABLE_RET(const MachineInstr &MI, SystemZMCInstLower &Lower);
- void lowerLOAD_TLS_BLOCK_ADDR(const MachineInstr &MI,
- SystemZMCInstLower &Lower);
- void lowerLOAD_GLOBAL_STACKGUARD_ADDR(const MachineInstr &MI,
- SystemZMCInstLower &Lower);
- void emitAttributes(Module &M);
};
} // end namespace llvm
diff --git a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
new file mode 100644
index 0000000000000..d7f12674ea244
--- /dev/null
+++ b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
@@ -0,0 +1,478 @@
+//===-- SystemZELFAsmPrinter.cpp - SystemZ ELF asm printer ----------------===//
+//
+// 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 file implements the SystemZELFAsmPrinter class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZELFAsmPrinter.h"
+#include "MCTargetDesc/SystemZMCTargetDesc.h"
+#include "SystemZConstantPoolValue.h"
+#include "SystemZMCInstLower.h"
+#include "SystemZSubtarget.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/StackMaps.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInstBuilder.h"
+#include "llvm/MC/MCSectionELF.h"
+#include "llvm/MC/MCStreamer.h"
+
+using namespace llvm;
+
+// Emit the largest nop instruction smaller than or equal to NumBytes
+// bytes. Return the size of nop emitted.
+static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
+ unsigned NumBytes, const MCSubtargetInfo &STI) {
+ if (NumBytes < 2) {
+ llvm_unreachable("Zero nops?");
+ return 0;
+ }
+ else if (NumBytes < 4) {
+ OutStreamer.emitInstruction(
+ MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
+ return 2;
+ }
+ else if (NumBytes < 6) {
+ OutStreamer.emitInstruction(
+ MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
+ STI);
+ return 4;
+ }
+ else {
+ MCSymbol *DotSym = OutContext.createTempSymbol();
+ const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
+ OutStreamer.emitLabel(DotSym);
+ OutStreamer.emitInstruction(
+ MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
+ return 6;
+ }
+}
+
+static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
+ StringRef Name = "__tls_get_offset";
+ return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
+ SystemZ::S_PLT, Context);
+}
+
+static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
+ StringRef Name = "_GLOBAL_OFFSET_TABLE_";
+ return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
+ Context);
+}
+
+SystemZELFAsmPrinter::SystemZELFAsmPrinter(
+ TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
+ : SystemZAsmPrinter(TM, std::move(Streamer)) {}
+
+void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
+ SystemZMCInstLower Lower(MF->getContext(), *this);
+
+ switch (MI->getOpcode()) {
+ case TargetOpcode::FENTRY_CALL:
+ LowerFENTRY_CALL(*MI, Lower);
+ return;
+ case TargetOpcode::STACKMAP:
+ LowerSTACKMAP(*MI);
+ return;
+ case TargetOpcode::PATCHPOINT:
+ LowerPATCHPOINT(*MI, Lower);
+ return;
+ case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
+ LowerPATCHABLE_FUNCTION_ENTER(*MI, Lower);
+ return;
+ case TargetOpcode::PATCHABLE_RET:
+ LowerPATCHABLE_RET(*MI, Lower);
+ return;
+ case SystemZ::CallBASR: {
+ const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
+ SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BASR)
+ .addReg(Regs->getReturnFunctionAddressRegister())
+ .addReg(MI->getOperand(0).getReg()));
+ return;
+ }
+ case SystemZ::CallBRASL: {
+ const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
+ SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BRASL)
+ .addReg(Regs->getReturnFunctionAddressRegister())
+ .addExpr(Lower.getExpr(MI->getOperand(0),
+ SystemZ::S_PLT)));
+ return;
+ }
+ case SystemZ::CallJG:
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::JG).addExpr(
+ Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT)));
+ return;
+ case SystemZ::CallBRCL:
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BRCL)
+ .addImm(MI->getOperand(0).getImm())
+ .addImm(MI->getOperand(1).getImm())
+ .addExpr(Lower.getExpr(MI->getOperand(2),
+ SystemZ::S_PLT)));
+ return;
+ case SystemZ::TLS_GDCALL: {
+ const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
+ SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BRASL)
+ .addReg(Regs->getReturnFunctionAddressRegister())
+ .addExpr(getTLSGetOffset(MF->getContext()))
+ .addExpr(Lower.getExpr(MI->getOperand(0),
+ SystemZ::S_TLSGD)));
+ return;
+ }
+ case SystemZ::TLS_LDCALL: {
+ const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
+ SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BRASL)
+ .addReg(Regs->getReturnFunctionAddressRegister())
+ .addExpr(getTLSGetOffset(MF->getContext()))
+ .addExpr(Lower.getExpr(MI->getOperand(0),
+ SystemZ::S_TLSLDM)));
+ return;
+ }
+ case SystemZ::GOT:
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::LARL)
+ .addReg(MI->getOperand(0).getReg())
+ .addExpr(getGlobalOffsetTable(MF->getContext())));
+ return;
+ case SystemZ::LOAD_TLS_BLOCK_ADDR:
+ lowerLOAD_TLS_BLOCK_ADDR(*MI, Lower);
+ return;
+ case SystemZ::LOAD_GLOBAL_STACKGUARD_ADDR:
+ lowerLOAD_GLOBAL_STACKGUARD_ADDR(*MI, Lower);
+ return;
+ default:
+ SystemZAsmPrinter::emitInstruction(MI);
+ return;
+ }
+}
+
+void SystemZELFAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
+ SystemZMCInstLower &Lower) {
+ MCContext &Ctx = MF->getContext();
+ if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
+ MCSymbol *DotSym = OutContext.createTempSymbol();
+ OutStreamer->pushSection();
+ OutStreamer->switchSection(
+ Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
+ OutStreamer->emitSymbolValue(DotSym, 8);
+ OutStreamer->popSection();
+ OutStreamer->emitLabel(DotSym);
+ }
+
+ if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
+ EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
+ return;
+ }
+
+ MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
+ const MCSymbolRefExpr *Op =
+ MCSymbolRefExpr::create(fentry, SystemZ::S_PLT, Ctx);
+ OutStreamer->emitInstruction(
+ MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
+ getSubtargetInfo());
+}
+
+void SystemZELFAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
+ auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();
+
+ unsigned NumNOPBytes = MI.getOperand(1).getImm();
+
+ auto &Ctx = OutStreamer->getContext();
+ MCSymbol *MILabel = Ctx.createTempSymbol();
+ OutStreamer->emitLabel(MILabel);
+
+ SM.recordStackMap(*MILabel, MI);
+ assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
+
+ // Scan ahead to trim the shadow.
+ unsigned ShadowBytes = 0;
+ const MachineBasicBlock &MBB = *MI.getParent();
+ MachineBasicBlock::const_iterator MII(MI);
+ ++MII;
+ while (ShadowBytes < NumNOPBytes) {
+ if (MII == MBB.end() ||
+ MII->getOpcode() == TargetOpcode::PATCHPOINT ||
+ MII->getOpcode() == TargetOpcode::STACKMAP)
+ break;
+ ShadowBytes += TII->getInstSizeInBytes(*MII);
+ if (MII->isCall())
+ break;
+ ++MII;
+ }
+
+ // Emit nops.
+ while (ShadowBytes < NumNOPBytes)
+ ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
+ getSubtargetInfo());
+}
+
+// Lower a patchpoint of the form:
+// [<def>], <id>, <numBytes>, <target>, <numArgs>
+void SystemZELFAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
+ SystemZMCInstLower &Lower) {
+ auto &Ctx = OutStreamer->getContext();
+ MCSymbol *MILabel = Ctx.createTempSymbol();
+ OutStreamer->emitLabel(MILabel);
+
+ SM.recordPatchPoint(*MILabel, MI);
+ PatchPointOpers Opers(&MI);
+
+ unsigned EncodedBytes = 0;
+ const MachineOperand &CalleeMO = Opers.getCallTarget();
+
+ if (CalleeMO.isImm()) {
+ uint64_t CallTarget = CalleeMO.getImm();
+ if (CallTarget) {
+ unsigned ScratchIdx = -1;
+ unsigned ScratchReg = 0;
+ do {
+ ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
+ ScratchReg = MI.getOperand(ScratchIdx).getReg();
+ } while (ScratchReg == SystemZ::R0D);
+
+ // Materialize the call target address
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
+ .addReg(ScratchReg)
+ .addImm(CallTarget & 0xFFFFFFFF));
+ EncodedBytes += 6;
+ if (CallTarget >> 32) {
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
+ .addReg(ScratchReg)
+ .addImm(CallTarget >> 32));
+ EncodedBytes += 6;
+ }
+
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
+ .addReg(SystemZ::R14D)
+ .addReg(ScratchReg));
+ EncodedBytes += 2;
+ }
+ } else if (CalleeMO.isGlobal()) {
+ const MCExpr *Expr = Lower.getExpr(CalleeMO, SystemZ::S_PLT);
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
+ .addReg(SystemZ::R14D)
+ .addExpr(Expr));
+ EncodedBytes += 6;
+ }
+
+ // Emit padding.
+ unsigned NumBytes = Opers.getNumPatchBytes();
+ assert(NumBytes >= EncodedBytes &&
+ "Patchpoint can't request size less than the length of a call.");
+ assert((NumBytes - EncodedBytes) % 2 == 0 &&
+ "Invalid number of NOP bytes requested!");
+ while (EncodedBytes < NumBytes)
+ EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
+ getSubtargetInfo());
+}
+
+void SystemZELFAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
+ const MachineInstr &MI, SystemZMCInstLower &Lower) {
+ const MachineFunction &MF = *(MI.getParent()->getParent());
+ const Function &F = MF.getFunction();
+
+ // If patchable-function-entry is set, emit in-function nops here.
+ if (F.hasFnAttribute("patchable-function-entry")) {
+ unsigned Num = F.getFnAttributeAsParsedInteger("patchable-function-entry");
+ for (unsigned I = 0; I < Num; ++I)
+ EmitToStreamer(*OutStreamer, MF.getSubtarget().getInstrInfo()->getNop());
+ return;
+ }
+ // Otherwise, emit xray sled.
+ // .begin:
+ // j .end # -> stmg %r2, %r15, 16(%r15)
+ // nop
+ // llilf %2, FuncID
+ // brasl %r14, __xray_FunctionEntry at GOT
+ // .end:
+ //
+ // Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number
+ // of instructions change.
+ bool HasVectorFeature =
+ TM.getMCSubtargetInfo().hasFeature(SystemZ::FeatureVector) &&
+ !TM.getMCSubtargetInfo().hasFeature(SystemZ::FeatureSoftFloat);
+ MCSymbol *FuncEntry = OutContext.getOrCreateSymbol(
+ HasVectorFeature ? "__xray_FunctionEntryVec" : "__xray_FunctionEntry");
+ MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_", true);
+ MCSymbol *EndOfSled = OutContext.createTempSymbol();
+ OutStreamer->emitLabel(BeginOfSled);
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::J).addExpr(
+ MCSymbolRefExpr::create(EndOfSled, OutContext)));
+ EmitNop(OutContext, *OutStreamer, 2, getSubtargetInfo());
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BRASL)
+ .addReg(SystemZ::R14D)
+ .addExpr(MCSymbolRefExpr::create(
+ FuncEntry, SystemZ::S_PLT, OutContext)));
+ OutStreamer->emitLabel(EndOfSled);
+ recordSled(BeginOfSled, MI, SledKind::FUNCTION_ENTER, 2);
+}
+
+void SystemZELFAsmPrinter::LowerPATCHABLE_RET(const MachineInstr &MI,
+ SystemZMCInstLower &Lower) {
+ unsigned OpCode = MI.getOperand(0).getImm();
+ MCSymbol *FallthroughLabel = nullptr;
+ if (OpCode == SystemZ::CondReturn) {
+ FallthroughLabel = OutContext.createTempSymbol();
+ int64_t Cond0 = MI.getOperand(1).getImm();
+ int64_t Cond1 = MI.getOperand(2).getImm();
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BRC)
+ .addImm(Cond0)
+ .addImm(Cond1 ^ Cond0)
+ .addExpr(MCSymbolRefExpr::create(FallthroughLabel,
+ OutContext)));
+ }
+ // .begin:
+ // br %r14 # -> stmg %r2, %r15, 24(%r15)
+ // nop
+ // nop
+ // llilf %2,FuncID
+ // j __xray_FunctionExit at GOT
+ //
+ // Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number
+ // of instructions change.
+ bool HasVectorFeature =
+ TM.getMCSubtargetInfo().hasFeature(SystemZ::FeatureVector) &&
+ !TM.getMCSubtargetInfo().hasFeature(SystemZ::FeatureSoftFloat);
+ MCSymbol *FuncExit = OutContext.getOrCreateSymbol(
+ HasVectorFeature ? "__xray_FunctionExitVec" : "__xray_FunctionExit");
+ MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_", true);
+ OutStreamer->emitLabel(BeginOfSled);
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D));
+ EmitNop(OutContext, *OutStreamer, 4, getSubtargetInfo());
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::J).addExpr(MCSymbolRefExpr::create(
+ FuncExit, SystemZ::S_PLT, OutContext)));
+ if (FallthroughLabel)
+ OutStreamer->emitLabel(FallthroughLabel);
+ recordSled(BeginOfSled, MI, SledKind::FUNCTION_EXIT, 2);
+}
+
+void SystemZELFAsmPrinter::lowerLOAD_TLS_BLOCK_ADDR(
+ const MachineInstr &MI, SystemZMCInstLower &Lower) {
+ Register AddrReg = MI.getOperand(0).getReg();
+ const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
+
+ // EAR can only load the low subregister so use a shift for %a0 to produce
+ // the GR containing %a0 and %a1.
+ const Register Reg32 =
+ MRI.getTargetRegisterInfo()->getSubReg(AddrReg, SystemZ::subreg_l32);
+
+ // ear <reg>, %a0
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::EAR).addReg(Reg32).addReg(SystemZ::A0));
+
+ // sllg <reg>, <reg>, 32
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::SLLG)
+ .addReg(AddrReg)
+ .addReg(AddrReg)
+ .addReg(0)
+ .addImm(32));
+
+ // ear <reg>, %a1
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::EAR).addReg(Reg32).addReg(SystemZ::A1));
+}
+
+void SystemZELFAsmPrinter::lowerLOAD_GLOBAL_STACKGUARD_ADDR(
+ const MachineInstr &MI, SystemZMCInstLower &Lower) {
+ Register AddrReg = MI.getOperand(0).getReg();
+ const MachineFunction &MF = *(MI.getParent()->getParent());
+ const Module *M = MF.getFunction().getParent();
+ const TargetLowering *TLI = MF.getSubtarget().getTargetLowering();
+
+ // Obtain the global value (assert if stack guard variable can't be found).
+ const GlobalVariable *GV = cast<GlobalVariable>(
+ TLI->getSDagStackGuard(*M, TLI->getLibcallLoweringInfo()));
+
+ // If configured, emit the `__stack_protector_loc` entry
+ if (M->hasStackProtectorGuardRecord()) {
+ MCSymbol *Sym = OutContext.createTempSymbol();
+ OutStreamer->pushSection();
+ OutStreamer->switchSection(OutContext.getELFSection(
+ "__stack_protector_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
+ OutStreamer->emitSymbolValue(Sym, getDataLayout().getPointerSize());
+ OutStreamer->popSection();
+ OutStreamer->emitLabel(Sym);
+ }
+ // Emit the address load.
+ if (M->getPICLevel() == PICLevel::NotPIC) {
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::LARL)
+ .addReg(AddrReg)
+ .addExpr(MCSymbolRefExpr::create(getSymbol(GV),
+ OutContext)));
+ } else {
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::LGRL)
+ .addReg(AddrReg)
+ .addExpr(MCSymbolRefExpr::create(
+ getSymbol(GV), SystemZ::S_GOTENT, OutContext)));
+ }
+}
+
+// The *alignment* of 128-bit vector types is different between the software
+// and hardware vector ABIs. If there is an externally visible use of a
+// vector type in the module it should be annotated with an attribute.
+void SystemZELFAsmPrinter::emitAttributes(Module &M) {
+ if (M.getModuleFlag("s390x-visible-vector-ABI")) {
+ bool HasVectorFeature =
+ TM.getMCSubtargetInfo().hasFeature(SystemZ::FeatureVector);
+ OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1);
+ }
+}
+
+// Convert a SystemZ-specific constant pool modifier into the associated
+// specifier.
+static uint8_t getSpecifierFromModifier(SystemZCP::SystemZCPModifier Modifier) {
+ switch (Modifier) {
+ case SystemZCP::TLSGD:
+ return SystemZ::S_TLSGD;
+ case SystemZCP::TLSLDM:
+ return SystemZ::S_TLSLDM;
+ case SystemZCP::DTPOFF:
+ return SystemZ::S_DTPOFF;
+ case SystemZCP::NTPOFF:
+ return SystemZ::S_NTPOFF;
+ }
+ llvm_unreachable("Invalid SystemCPModifier!");
+}
+
+void SystemZELFAsmPrinter::emitMachineConstantPoolValue(
+ MachineConstantPoolValue *MCPV) {
+ auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
+
+ const MCExpr *Expr = MCSymbolRefExpr::create(
+ getSymbol(ZCPV->getGlobalValue()),
+ getSpecifierFromModifier(ZCPV->getModifier()), OutContext);
+ uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
+
+ OutStreamer->emitValue(Expr, Size);
+}
+
+void SystemZELFAsmPrinter::emitEndOfAsmFile(Module &M) {
+ emitAttributes(M);
+}
diff --git a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.h
new file mode 100644
index 0000000000000..2e7916840583b
--- /dev/null
+++ b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.h
@@ -0,0 +1,54 @@
+//===-- SystemZELFAsmPrinter.h - SystemZ ELF asm printer --------*- 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 file declares the SystemZELFAsmPrinter class, which owns ELF-specific
+// asm printer behaviour: ELF instruction lowering, fentry/stackmap/patchpoint,
+// TLS block address, stack-guard address, and the ELF vector-ABI attribute.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZELFASMPRINTER_H
+#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZELFASMPRINTER_H
+
+#include "MCTargetDesc/SystemZTargetStreamer.h"
+#include "SystemZAsmPrinter.h"
+#include "SystemZMCInstLower.h"
+
+namespace llvm {
+
+class LLVM_LIBRARY_VISIBILITY SystemZELFAsmPrinter : public SystemZAsmPrinter {
+ SystemZTargetStreamer *getTargetStreamer() {
+ MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
+ assert(TS && "do not have a target streamer");
+ return static_cast<SystemZTargetStreamer *>(TS);
+ }
+
+public:
+ SystemZELFAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer);
+
+ void emitInstruction(const MachineInstr *MI) override;
+ void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
+ void emitEndOfAsmFile(Module &M) override;
+
+private:
+ void LowerFENTRY_CALL(const MachineInstr &MI, SystemZMCInstLower &Lower);
+ void LowerSTACKMAP(const MachineInstr &MI);
+ void LowerPATCHPOINT(const MachineInstr &MI, SystemZMCInstLower &Lower);
+ void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI,
+ SystemZMCInstLower &Lower);
+ void LowerPATCHABLE_RET(const MachineInstr &MI, SystemZMCInstLower &Lower);
+ void lowerLOAD_TLS_BLOCK_ADDR(const MachineInstr &MI,
+ SystemZMCInstLower &Lower);
+ void lowerLOAD_GLOBAL_STACKGUARD_ADDR(const MachineInstr &MI,
+ SystemZMCInstLower &Lower);
+ void emitAttributes(Module &M);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZELFASMPRINTER_H
diff --git a/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp
new file mode 100644
index 0000000000000..72cd1ee222788
--- /dev/null
+++ b/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp
@@ -0,0 +1,864 @@
+//===-- SystemZXPLINKAsmPrinter.cpp - SystemZ XPLINK asm printer ----------===//
+//
+// 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 file implements the SystemZXPLINKAsmPrinter class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SystemZXPLINKAsmPrinter.h"
+#include "MCTargetDesc/SystemZMCTargetDesc.h"
+#include "MCTargetDesc/SystemZTargetStreamer.h"
+#include "SystemZFrameLowering.h"
+#include "SystemZInstrInfo.h"
+#include "SystemZMCInstLower.h"
+#include "SystemZMachineFunctionInfo.h"
+#include "SystemZSubtarget.h"
+#include "SystemZTargetObjectFile.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/BinaryFormat/GOFF.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalObject.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInstBuilder.h"
+#include "llvm/MC/MCSymbolGOFF.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/ConvertEBCDIC.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+
+SystemZXPLINKAsmPrinter::SystemZXPLINKAsmPrinter(
+ TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
+ : SystemZAsmPrinter(TM, std::move(Streamer)),
+ ADATable(TM.getPointerSize(0)) {}
+
+bool SystemZXPLINKAsmPrinter::doInitialization(Module &M) {
+ SM.reset();
+
+ // In HLASM, the only way to represent aliases is to use the
+ // extra-label-at-definition strategy. This is similar to the AIX
+ // implementation with the additional caveat that all symbol attributes must
+ // be emitted before the label is emitted.
+ // Construct an aliasing list for each GlobalObject.
+ for (const auto &Alias : M.aliases()) {
+ const GlobalObject *Aliasee = Alias.getAliaseeObject();
+ if (!Aliasee)
+ OutContext.reportError(
+ {}, "Alias without a base object is not yet supported on z/OS.");
+
+ bool IsFunc = isa<Function>(Aliasee->stripPointerCasts());
+ if (IsFunc) {
+ if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage())
+ OutContext.reportError({},
+ "Weak alias/reference not supported on z/OS");
+
+ GOAliasMap[Aliasee].push_back(&Alias);
+ } else
+ OutContext.reportError(
+ {}, "Only aliases to functions is supported in GOFF.");
+ }
+ return AsmPrinter::doInitialization(M);
+}
+
+// The XPLINK ABI requires that a no-op encoding the call type is emitted after
+// each call to a subroutine. This information can be used by the called
+// function to determine its entry point, e.g. for generating a backtrace. The
+// call type is encoded as a register number in the bcr instruction. See
+// enumeration CallType for the possible values.
+void SystemZXPLINKAsmPrinter::emitCallInformation(CallType CT) {
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BCRAsm)
+ .addImm(0)
+ .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
+}
+
+uint32_t SystemZXPLINKAsmPrinter::AssociatedDataAreaTable::insert(
+ const MCSymbol *Sym, unsigned SlotKind) {
+ auto Key = std::make_pair(Sym, SlotKind);
+ auto It = Displacements.find(Key);
+
+ if (It != Displacements.end())
+ return (*It).second;
+
+ // Determine length of descriptor.
+ uint32_t Length;
+ switch (SlotKind) {
+ case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
+ Length = 2 * PointerSize;
+ break;
+ default:
+ Length = PointerSize;
+ break;
+ }
+
+ uint32_t Displacement = NextDisplacement;
+ Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement;
+ NextDisplacement += Length;
+
+ return Displacement;
+}
+
+uint32_t SystemZXPLINKAsmPrinter::AssociatedDataAreaTable::insert(
+ const MachineOperand MO) {
+ MCSymbol *Sym;
+ if (MO.getType() == MachineOperand::MO_GlobalAddress) {
+ const GlobalValue *GV = MO.getGlobal();
+ Sym = MO.getParent()->getMF()->getTarget().getSymbol(GV);
+ assert(Sym && "No symbol");
+ } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) {
+ const char *SymName = MO.getSymbolName();
+ Sym = MO.getParent()->getMF()->getContext().getOrCreateSymbol(SymName);
+ assert(Sym && "No symbol");
+ } else
+ llvm_unreachable("Unexpected operand type");
+
+ unsigned ADAslotType = MO.getTargetFlags();
+ return insert(Sym, ADAslotType);
+}
+
+void SystemZXPLINKAsmPrinter::emitInstruction(const MachineInstr *MI) {
+ SystemZMCInstLower Lower(MF->getContext(), *this);
+ MCInst LoweredMI;
+
+ switch (MI->getOpcode()) {
+ case SystemZ::CallBRASL_XPLINK64:
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BRASL)
+ .addReg(SystemZ::R7D)
+ .addExpr(Lower.getExpr(MI->getOperand(0),
+ SystemZ::S_None)));
+ emitCallInformation(CallType::BRASL7);
+ return;
+
+ case SystemZ::CallBASR_XPLINK64:
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BASR)
+ .addReg(SystemZ::R7D)
+ .addReg(MI->getOperand(0).getReg()));
+ emitCallInformation(CallType::BASR76);
+ return;
+
+ case SystemZ::Return_XPLINK:
+ LoweredMI = MCInstBuilder(SystemZ::B)
+ .addReg(SystemZ::R7D)
+ .addImm(2)
+ .addReg(0);
+ break;
+
+ case SystemZ::CondReturn_XPLINK:
+ LoweredMI = MCInstBuilder(SystemZ::BC)
+ .addImm(MI->getOperand(0).getImm())
+ .addImm(MI->getOperand(1).getImm())
+ .addReg(SystemZ::R7D)
+ .addImm(2)
+ .addReg(0);
+ break;
+
+ case SystemZ::CallBASR_STACKEXT:
+ EmitToStreamer(*OutStreamer,
+ MCInstBuilder(SystemZ::BASR)
+ .addReg(SystemZ::R3D)
+ .addReg(MI->getOperand(0).getReg()));
+ emitCallInformation(CallType::BASR33);
+ return;
+
+ case SystemZ::ADA_ENTRY_VALUE:
+ case SystemZ::ADA_ENTRY: {
+ const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
+ const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
+ uint32_t Disp = ADATable.insert(MI->getOperand(1));
+ Register TargetReg = MI->getOperand(0).getReg();
+
+ Register ADAReg = MI->getOperand(2).getReg();
+ Disp += MI->getOperand(3).getImm();
+ bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY;
+
+ unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG;
+ unsigned Op = TII->getOpcodeForOffset(Op0, Disp);
+
+ Register IndexReg = 0;
+ if (!Op) {
+ if (TargetReg != ADAReg) {
+ IndexReg = TargetReg;
+ // Use TargetReg to store displacement.
+ EmitToStreamer(
+ *OutStreamer,
+ MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
+ } else
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::ALGFI)
+ .addReg(TargetReg)
+ .addReg(TargetReg)
+ .addImm(Disp));
+ Disp = 0;
+ Op = Op0;
+ }
+ EmitToStreamer(*OutStreamer, MCInstBuilder(Op)
+ .addReg(TargetReg)
+ .addReg(ADAReg)
+ .addImm(Disp)
+ .addReg(IndexReg));
+ return;
+ }
+
+ default:
+ SystemZAsmPrinter::emitInstruction(MI);
+ return;
+ }
+ EmitToStreamer(*OutStreamer, LoweredMI);
+}
+
+void SystemZXPLINKAsmPrinter::emitXXStructorList(const DataLayout &DL,
+ const Constant *List,
+ bool IsCtor) {
+ assert(TM.getTargetTriple().isOSBinFormatGOFF() && "Only GOFF supported");
+
+ SmallVector<Structor, 8> Structors;
+ preprocessXXStructorList(DL, List, Structors);
+ if (Structors.empty())
+ return;
+
+ const Align Align = llvm::Align(4);
+ const TargetLoweringObjectFileGOFF &Obj =
+ static_cast<const TargetLoweringObjectFileGOFF &>(getObjFileLowering());
+ for (Structor &S : Structors) {
+ MCSectionGOFF *Section =
+ static_cast<MCSectionGOFF *>(Obj.getStaticXtorSection(S.Priority));
+ OutStreamer->switchSection(Section);
+ if (OutStreamer->getCurrentSection() != OutStreamer->getPreviousSection())
+ emitAlignment(Align);
+
+ // The priority is provided as an input to getStaticXtorSection(), and is
+ // recalculated within that function as `Prio` going to going into the
+ // PR section.
+ // This priority retrieved via the `SortKey` below is the recalculated
+ // Priority.
+ uint32_t XtorPriority = Section->getPRAttributes().SortKey;
+
+ const GlobalValue *GV = dyn_cast<GlobalValue>(S.Func->stripPointerCasts());
+ assert(GV && "C++ xxtor pointer was not a GlobalValue!");
+ MCSymbolGOFF *Symbol = static_cast<MCSymbolGOFF *>(getSymbol(GV));
+
+ // @@SQINIT entry: { unsigned prio; void (*ctor)(); void (*dtor)(); }
+
+ unsigned PointerSizeInBytes = DL.getPointerSize();
+
+ auto &Ctx = OutStreamer->getContext();
+ const MCExpr *ADAFuncRefExpr;
+ unsigned SlotKind = SystemZII::MO_ADA_DIRECT_FUNC_DESC;
+
+ MCSectionGOFF *ADASection =
+ static_cast<MCSectionGOFF *>(Obj.getADASection());
+ assert(ADASection && "ADA section must exist for GOFF targets!");
+ const MCSymbol *ADASym = ADASection->getBeginSymbol();
+ assert(ADASym && "ADA symbol should already be set!");
+
+ ADAFuncRefExpr = MCBinaryExpr::createAdd(
+ MCSpecifierExpr::create(MCSymbolRefExpr::create(ADASym, OutContext),
+ SystemZ::S_QCon, OutContext),
+ MCConstantExpr::create(ADATable.insert(Symbol, SlotKind), Ctx), Ctx);
+
+ emitInt32(XtorPriority);
+ if (IsCtor) {
+ OutStreamer->emitValue(ADAFuncRefExpr, PointerSizeInBytes);
+ OutStreamer->emitIntValue(0, PointerSizeInBytes);
+ } else {
+ OutStreamer->emitIntValue(0, PointerSizeInBytes);
+ OutStreamer->emitValue(ADAFuncRefExpr, PointerSizeInBytes);
+ }
+ }
+}
+
+void SystemZXPLINKAsmPrinter::emitEndOfAsmFile(Module &M) {
+ auto *ZOS = getTargetStreamer();
+ emitADASection();
+ emitIDRLSection(M);
+ // On z/OS, we need to associate an external data reference with an ED
+ // symbol, for which we use the the ED of the ADA. We also need to mark the
+ // reference as being to data, otherwise we cannot bind with code generated
+ // by XL.
+ for (auto &GO : M.global_objects()) {
+ if (auto *GV = dyn_cast<GlobalVariable>(&GO)) {
+ if (!GV->hasInitializer()) {
+ MCSymbol *Sym = getSymbol(GV);
+ ZOS->emitADA(Sym, OutContext.getObjectFileInfo()->getADASection());
+ OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeObject);
+ }
+ }
+ }
+}
+
+void SystemZXPLINKAsmPrinter::emitADASection() {
+ OutStreamer->pushSection();
+
+ const unsigned PointerSize = getDataLayout().getPointerSize();
+ OutStreamer->switchSection(getObjFileLowering().getADASection());
+
+ auto *ZOS = getTargetStreamer();
+ unsigned EmittedBytes = 0;
+ for (auto &Entry : ADATable.getTable()) {
+ const MCSymbol *Sym;
+ unsigned SlotKind;
+ std::tie(Sym, SlotKind) = Entry.first;
+ unsigned Offset = Entry.second;
+ assert(Offset == EmittedBytes && "Offset not as expected");
+ (void)EmittedBytes;
+#define EMIT_COMMENT(Str) \
+ OutStreamer->AddComment(Twine("Offset ") \
+ .concat(utostr(Offset)) \
+ .concat(" " Str " ") \
+ .concat(Sym->getName()));
+ switch (SlotKind) {
+ case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
+ // Language Environment DLL logic requires function descriptors, for
+ // imported functions, that are placed in the ADA to be 8 byte aligned.
+ EMIT_COMMENT("function descriptor of");
+ OutStreamer->emitValue(
+ MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
+ SystemZ::S_RCon, OutContext),
+ PointerSize);
+ OutStreamer->emitValue(
+ MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
+ SystemZ::S_VCon, OutContext),
+ PointerSize);
+ EmittedBytes += PointerSize * 2;
+ break;
+ case SystemZII::MO_ADA_DATA_SYMBOL_ADDR:
+ EMIT_COMMENT("pointer to data symbol");
+ OutStreamer->emitValue(
+ MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
+ SystemZ::S_None, OutContext),
+ PointerSize);
+ EmittedBytes += PointerSize;
+ break;
+ case SystemZII::MO_ADA_INDIRECT_FUNC_DESC: {
+ MCSymbol *Alias = OutContext.getOrCreateSymbol(
+ Twine(Sym->getName()).concat("@indirect"));
+ OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
+ OutStreamer->emitSymbolAttribute(Alias, MCSA_ELF_TypeFunction);
+ OutStreamer->emitSymbolAttribute(Alias, MCSA_Global);
+ OutStreamer->emitSymbolAttribute(Alias, MCSA_Extern);
+ MCSymbolGOFF *GOFFSym =
+ static_cast<llvm::MCSymbolGOFF *>(const_cast<llvm::MCSymbol *>(Sym));
+ ZOS->emitExternalName(Alias, GOFFSym->getExternalName());
+ EMIT_COMMENT("pointer to function descriptor");
+ OutStreamer->emitValue(
+ MCSpecifierExpr::create(MCSymbolRefExpr::create(Alias, OutContext),
+ SystemZ::S_VCon, OutContext),
+ PointerSize);
+ EmittedBytes += PointerSize;
+ break;
+ }
+ default:
+ llvm_unreachable("Unexpected slot kind");
+ }
+#undef EMIT_COMMENT
+ }
+ OutStreamer->popSection();
+}
+
+static std::string getProductID(Module &M) {
+ std::string ProductID;
+ if (auto *MD = M.getModuleFlag("zos_product_id"))
+ ProductID = cast<MDString>(MD)->getString().str();
+ if (ProductID.empty())
+ ProductID = "LLVM";
+ return ProductID;
+}
+
+static uint32_t getProductVersion(Module &M) {
+ if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("zos_product_major_version")))
+ return VersionVal->getZExtValue();
+ return LLVM_VERSION_MAJOR;
+}
+
+static uint32_t getProductRelease(Module &M) {
+ if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("zos_product_minor_version")))
+ return ReleaseVal->getZExtValue();
+ return LLVM_VERSION_MINOR;
+}
+
+static uint32_t getProductPatch(Module &M) {
+ if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("zos_product_patchlevel")))
+ return PatchVal->getZExtValue();
+ return LLVM_VERSION_PATCH;
+}
+
+static time_t getTranslationTime(Module &M) {
+ std::time_t Time = 0;
+ if (auto *Val = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("zos_translation_time"))) {
+ long SecondsSinceEpoch = Val->getSExtValue();
+ Time = static_cast<time_t>(SecondsSinceEpoch);
+ }
+ return Time;
+}
+
+void SystemZXPLINKAsmPrinter::emitIDRLSection(Module &M) {
+ OutStreamer->pushSection();
+ OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
+ constexpr unsigned IDRLDataLength = 30;
+ std::time_t Time = getTranslationTime(M);
+
+ uint32_t ProductVersion = getProductVersion(M);
+ uint32_t ProductRelease = getProductRelease(M);
+
+ std::string ProductID = getProductID(M);
+
+ SmallString<IDRLDataLength + 1> TempStr;
+ raw_svector_ostream O(TempStr);
+ O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",
+ ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
+ llvm::sys::toUtcTime(Time), "0");
+ SmallString<IDRLDataLength> Data;
+ ConverterEBCDIC::convertToEBCDIC(TempStr, Data);
+
+ OutStreamer->emitInt8(0); // Reserved.
+ OutStreamer->emitInt8(3); // Format.
+ OutStreamer->emitInt16(IDRLDataLength); // Length.
+ OutStreamer->emitBytes(Data.str());
+ OutStreamer->popSection();
+}
+
+void SystemZXPLINKAsmPrinter::emitFunctionBodyEnd() {
+ // 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 = getTargetStreamer();
+ OutStreamer->emitLabel(ZOS->DeferredPPA1.back().FnEnd);
+}
+
+// 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,
+ MCSymbol *&EndOfPrologSym,
+ MCSymbol *&StackUpdateSym) {
+ EndOfPrologSym = nullptr;
+ StackUpdateSym = nullptr;
+
+ // Scan the basic block for the FENCE instruction which marks the end
+ // of the prologue. We know
+ // the prologue is spread at most across the first 3 basic blocks. Also record
+ // the first instruction updating the stack pointer.
+ const SystemZSubtarget &STI = MF->getSubtarget<SystemZSubtarget>();
+ auto &Regs = STI.getSpecialRegisters<SystemZXPLINK64Registers>();
+ MachineInstr *EndOfPrologMI = nullptr;
+ MachineInstr *StackUpdateMI = nullptr;
+ unsigned BBCount = 1;
+
+ for (auto &MBB : *MF) {
+ for (auto &I : MBB) {
+ if (I.getOpcode() == SystemZ::FENCE)
+ EndOfPrologMI = &I;
+ else if (!StackUpdateMI) {
+ unsigned Opcode = I.getOpcode();
+ // TODO: We can instead emit a pseudo instruction in
+ // SystemZFrameLowering to represent a stack adjustment instruction, and
+ // check for that here, instead of having to check for multiple
+ // instructions.
+ if ((Opcode == SystemZ::AGHI || Opcode == SystemZ::AGFI) &&
+ I.getOperand(0).getReg() == Regs.getStackPointerRegister())
+ StackUpdateMI = &I;
+ }
+ }
+
+ // Prologue can be a max of 3 BBs if we need to call stack extension code
+ if (EndOfPrologMI || BBCount == 3)
+ break;
+
+ ++BBCount;
+ }
+
+ // Leaf functions do not have a prologue.
+ if (EndOfPrologMI == nullptr)
+ return;
+
+#ifdef EXPENSIVE_CHECKS
+ // Check that the prolog length is valid.
+ auto *TII = STI.getInstrInfo();
+ size_t Size = 0;
+
+ for (auto &MBB : *MF) {
+ bool TerminateLoop = false;
+ for (auto &I : MBB) {
+ Size += TII->getInstSizeInBytes(I);
+ if (&I == EndOfPrologMI) {
+ TerminateLoop = true;
+ break;
+ }
+ }
+ if (TerminateLoop)
+ break;
+ }
+ if (Size > 128)
+ report_fatal_error(
+ Twine(MF->getName()).concat(": Prolog exceeds 128 bytes"));
+#endif
+
+ // Attach a temporary symbol to mark the end of the prolog.
+ EndOfPrologSym = MF->getContext().createTempSymbol("end_of_prologue");
+ EndOfPrologMI->setPostInstrSymbol(*MF, EndOfPrologSym);
+
+ if (StackUpdateMI) {
+ StackUpdateSym = MF->getContext().createTempSymbol("stack_update");
+ StackUpdateMI->setPreInstrSymbol(*MF, StackUpdateSym);
+ }
+}
+
+void SystemZXPLINKAsmPrinter::calculatePPA1() {
+ auto *ZOS = getTargetStreamer();
+ assert(ZOS->PPA2Sym != nullptr && "PPA2 Symbol not defined");
+
+ SystemZTargetzOSStreamer::PPA1Info Info;
+
+ const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
+ const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
+
+ 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");
+
+ 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());
+ PersonalityRoutine = Per ? MF->getTarget().getSymbol(Per) : nullptr;
+ if (PersonalityRoutine) {
+ 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 _.
+ std::string N(MF->getFunction().hasName()
+ ? Twine(MF->getFunction().getName()).concat("_").str()
+ : "");
+
+ // Calculate the lables for the prolog size and the stack update symbol.
+ MCSymbol *EndOfPrologSym;
+ MCSymbol *StackUpdateSym;
+ determinePrologueStackUpdateSym(MF, EndOfPrologSym, StackUpdateSym);
+
+ // Save the calculated values.
+ if (MF->getFunction().hasFnAttribute("zos-ppa1-name"))
+ Info.Name =
+ MF->getFunction().getFnAttribute("zos-ppa1-name").getValueAsString();
+ else if (MF->getFunction().hasName())
+ Info.Name = MF->getFunction().getName();
+
+ Info.PPA1 = OutContext.createTempSymbol(Twine("PPA1_").concat(N), true);
+ Info.EPMarker = OutContext.createTempSymbol(Twine("EPM_").concat(N), true);
+ Info.FnEnd = OutContext.createTempSymbol(Twine(N).concat("end_"));
+ Info.Fn = CurrentFnSym;
+ Info.EndOfProlog = EndOfPrologSym;
+ Info.StackUpdate = StackUpdateSym;
+ Info.PersonalityADADisp = PersonalityADADisp;
+ Info.GCCEHADADisp = GCCEHADADisp;
+ Info.OffsetFPR = OffsetFPR;
+ Info.OffsetVR = OffsetVR;
+ Info.CallFrameSize = MFFrame.getMaxCallFrameSize();
+ Info.SizeOfFnParams = ZFI->getSizeOfFnParams();
+ Info.SavedGPRMask = SavedGPRMask;
+ Info.SavedFPRMask = SavedFPRMask;
+ Info.SavedVRMask = SavedVRMask;
+ Info.FrameReg = FrameReg;
+ Info.AllocaReg = AllocaReg;
+ Info.IsVarArg = MF->getFunction().isVarArg();
+ Info.HasStackProtector = MFFrame.hasStackProtectorIndex();
+
+ ZOS->DeferredPPA1.push_back(Info);
+}
+
+void SystemZXPLINKAsmPrinter::emitStartOfAsmFile(Module &M) {
+ emitPPA2(M);
+ AsmPrinter::emitStartOfAsmFile(M);
+}
+
+void SystemZXPLINKAsmPrinter::emitPPA2(Module &M) {
+ auto *ZOS = getTargetStreamer();
+ OutStreamer->pushSection();
+ OutStreamer->switchSection(getObjFileLowering().getTextSection());
+ MCContext &OutContext = OutStreamer->getContext();
+ // Make CELQSTRT symbol.
+ const char *StartSymbolName = "CELQSTRT";
+ MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
+ OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_OSLinkage);
+ OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Global);
+
+ // 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);
+ SmallString<14> CompilationTimeEBCDIC, CompilationTime;
+ CompilationTime = formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));
+
+ uint32_t ProductVersion = getProductVersion(M),
+ ProductRelease = getProductRelease(M),
+ ProductPatch = getProductPatch(M);
+
+ SmallString<6> VersionEBCDIC, Version;
+ Version = formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion,
+ ProductRelease, ProductPatch);
+
+ ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeEBCDIC);
+ ConverterEBCDIC::convertToEBCDIC(Version, VersionEBCDIC);
+
+ enum class PPA2MemberId : uint8_t {
+ // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for
+ // complete list. Only the C runtime is supported by this backend.
+ LE_C_Runtime = 3,
+ };
+ enum class PPA2MemberSubId : uint8_t {
+ // List of languages using the LE C runtime implementation.
+ C = 0x00,
+ CXX = 0x01,
+ Swift = 0x03,
+ Go = 0x60,
+ LLVMBasedLang = 0xe7,
+ };
+ // PPA2 Flags
+ enum class PPA2Flags : uint8_t {
+ CompileForBinaryFloatingPoint = 0x80,
+ CompiledWithXPLink = 0x01,
+ CompiledUnitASCII = 0x04,
+ HasServiceInfo = 0x20,
+ };
+
+ PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang;
+ if (auto *MD = M.getModuleFlag("zos_cu_language")) {
+ StringRef Language = cast<MDString>(MD)->getString();
+ MemberSubId = StringSwitch<PPA2MemberSubId>(Language)
+ .Case("C", PPA2MemberSubId::C)
+ .Case("C++", PPA2MemberSubId::CXX)
+ .Case("Swift", PPA2MemberSubId::Swift)
+ .Case("Go", PPA2MemberSubId::Go)
+ .Default(PPA2MemberSubId::LLVMBasedLang);
+ }
+
+ // Emit PPA2 section.
+ OutStreamer->emitLabel(PPA2Sym);
+ OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime));
+ OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId));
+ OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env
+ OutStreamer->emitInt8(0x04); // Control level 4 (XPLink)
+ OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4);
+ OutStreamer->emitInt32(0x00000000);
+ OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4);
+ OutStreamer->emitInt32(
+ 0x00000000); // Offset to main entry point, always 0 (so says TR).
+ uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint);
+ Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink);
+
+ bool IsASCII = true;
+ if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {
+ const StringRef &CharMode = cast<MDString>(MD)->getString();
+ if (CharMode == "ebcdic")
+ IsASCII = false;
+ else if (CharMode != "ascii")
+ OutContext.reportError(
+ {}, "Only ascii or ebcdic are allowed for zos_le_char_mode");
+ }
+ if (IsASCII)
+ Flgs |= static_cast<uint8_t>(
+ PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.
+
+ OutStreamer->emitInt8(Flgs);
+ OutStreamer->emitInt8(0x00); // Reserved.
+ // No MD5 signature before timestamp.
+ // No FLOAT(AFP(VOLATILE)).
+ // Remaining 5 flag bits reserved.
+ OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits.
+
+ // Emit date and version section.
+ OutStreamer->emitLabel(DateVersionSym);
+ OutStreamer->emitBytes(CompilationTimeEBCDIC.str());
+ OutStreamer->emitBytes(VersionEBCDIC.str());
+
+ OutStreamer->emitInt16(0x0000); // Service level string length.
+
+ // The binder requires that the offset to the PPA2 be emitted in a different,
+ // specially-named section.
+ OutStreamer->switchSection(getObjFileLowering().getPPA2ListSection());
+ // Emit 8 byte alignment.
+ // Emit pointer to PPA2 label.
+ OutStreamer->AddComment("A(PPA2-CELQSTRT)");
+ OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);
+ OutStreamer->popSection();
+}
+
+void SystemZXPLINKAsmPrinter::emitGlobalAlias(const Module &M,
+ const GlobalAlias &GA) {
+ if (!TM.getTargetTriple().isOSzOS())
+ return AsmPrinter::emitGlobalAlias(M, GA);
+
+ // Aliased function labels have already been emitted for z/OS
+}
+
+const MCExpr *SystemZXPLINKAsmPrinter::lowerConstant(const Constant *CV,
+ const Constant *BaseCV,
+ uint64_t Offset) {
+ const GlobalAlias *GA = dyn_cast<GlobalAlias>(CV);
+ const GlobalVariable *GV = dyn_cast<GlobalVariable>(CV);
+ const Function *FV = dyn_cast<Function>(CV);
+ bool IsFunc = !GV && (FV || (GA && isa<Function>(GA->getAliaseeObject())));
+
+ MCSymbol *Sym = NULL;
+
+ if (GA)
+ Sym = getSymbol(GA);
+ else if (IsFunc)
+ Sym = getSymbol(FV);
+ else if (GV)
+ Sym = getSymbol(GV);
+
+ if (IsFunc) {
+ OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
+ if (FV->hasExternalLinkage())
+ return MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
+ SystemZ::S_VCon, OutContext);
+ // Trigger creation of function descriptor in ADA for internal
+ // functions.
+ unsigned Disp = ADATable.insert(Sym, SystemZII::MO_ADA_DIRECT_FUNC_DESC);
+ return MCBinaryExpr::createAdd(
+ MCSpecifierExpr::create(
+ MCSymbolRefExpr::create(
+ getObjFileLowering().getADASection()->getBeginSymbol(),
+ OutContext),
+ SystemZ::S_None, OutContext),
+ MCConstantExpr::create(Disp, OutContext), OutContext);
+ }
+ if (Sym) {
+ OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeObject);
+ return MCSymbolRefExpr::create(Sym, OutContext);
+ }
+ return AsmPrinter::lowerConstant(CV);
+}
+
+void SystemZXPLINKAsmPrinter::emitFunctionEntryLabel() {
+ auto *ZOS = getTargetStreamer();
+ calculatePPA1();
+
+ // EntryPoint Marker
+ const MachineFrameInfo &MFFrame = MF->getFrameInfo();
+ bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
+ uint32_t DSASize = MFFrame.getStackSize();
+ bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
+
+ // Set Flags.
+ uint8_t Flags = 0;
+ if (IsLeaf)
+ Flags |= 0x08;
+ if (IsUsingAlloca)
+ Flags |= 0x04;
+
+ // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
+ uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
+ DSAAndFlags |= Flags;
+
+ // Emit entry point marker section.
+ OutStreamer->AddComment("XPLINK Routine Layout Entry");
+ 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(ZOS->DeferredPPA1.back().PPA1,
+ ZOS->DeferredPPA1.back().EPMarker, 4);
+ if (OutStreamer->isVerboseAsm()) {
+ OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
+ OutStreamer->AddComment("Entry Flags");
+ if (Flags & 0x08)
+ OutStreamer->AddComment(" Bit 1: 1 = Leaf function");
+ else
+ OutStreamer->AddComment(" Bit 1: 0 = Non-leaf function");
+ if (Flags & 0x04)
+ OutStreamer->AddComment(" Bit 2: 1 = Uses alloca");
+ else
+ OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca");
+ }
+ OutStreamer->emitInt32(DSAAndFlags);
+
+ ZOS->emitADA(CurrentFnSym, getObjFileLowering().getADASection());
+
+ AsmPrinter::emitFunctionEntryLabel();
+
+ const Function *F = &MF->getFunction();
+ // Emit aliasing label for function entry point label.
+ for (const GlobalAlias *Alias : GOAliasMap[F]) {
+ MCSymbol *Sym = getSymbol(Alias);
+ OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
+ emitVisibility(Sym, Alias->getVisibility());
+ emitLinkage(Alias, Sym);
+ OutStreamer->emitLabel(Sym);
+ }
+}
diff --git a/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.h
new file mode 100644
index 0000000000000..4d480db06b2db
--- /dev/null
+++ b/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.h
@@ -0,0 +1,127 @@
+//===-- SystemZXPLINKAsmPrinter.h - SystemZ XPLINK asm printer --*- 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 file declares the SystemZXPLINKAsmPrinter class, which owns all
+// z/OS XPLINK-specific asm printer behaviour: ADA table management, PPA1/PPA2,
+// IDRL, entry-point markers, and XPLINK call/return instruction lowering.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZXPLINKASMPRINTER_H
+#define LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZXPLINKASMPRINTER_H
+
+#include "MCTargetDesc/SystemZTargetStreamer.h"
+#include "SystemZAsmPrinter.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
+
+namespace llvm {
+class MCStreamer;
+class MCSymbolGOFF;
+class MachineInstr;
+class Module;
+class raw_ostream;
+
+class LLVM_LIBRARY_VISIBILITY SystemZXPLINKAsmPrinter
+ : public SystemZAsmPrinter {
+
+ /// Call type information for XPLINK.
+ enum class CallType {
+ BASR76 = 0, // b'x000' == BASR r7,r6
+ BRAS7 = 1, // b'x001' == BRAS r7,ep
+ RESVD_2 = 2, // b'x010'
+ BRASL7 = 3, // b'x011' == BRASL r7,ep
+ RESVD_4 = 4, // b'x100'
+ RESVD_5 = 5, // b'x101'
+ BALR1415 = 6, // b'x110' == BALR r14,r15
+ BASR33 = 7, // b'x111' == BASR r3,r3
+ };
+
+ // The Associated Data Area (ADA) contains descriptors which help locating
+ // external symbols. For each symbol and type, the displacement into the ADA
+ // is stored.
+ class AssociatedDataAreaTable {
+ public:
+ using DisplacementTable =
+ MapVector<std::pair<const MCSymbol *, unsigned>, uint32_t>;
+
+ private:
+ const uint64_t PointerSize;
+
+ /// The mapping of name/slot type pairs to displacements.
+ DisplacementTable Displacements;
+
+ /// The next available displacement value. Incremented when new entries into
+ /// the ADA are created.
+ uint32_t NextDisplacement = 0;
+
+ public:
+ AssociatedDataAreaTable(uint64_t PointerSize) : PointerSize(PointerSize) {}
+
+ /// @brief Add a function descriptor to the ADA.
+ /// @param MI Pointer to an ADA_ENTRY instruction.
+ /// @return The displacement of the descriptor into the ADA.
+ uint32_t insert(const MachineOperand MO);
+
+ /// @brief Get the displacement into associated data area (ADA) for a name.
+ /// If no displacement is already associated with the name, assign one and
+ /// return it.
+ /// @param Sym The symbol for which the displacement should be returned.
+ /// @param SlotKind The ADA type.
+ /// @return The displacement of the descriptor into the ADA.
+ uint32_t insert(const MCSymbol *Sym, unsigned SlotKind);
+
+ /// Get the table of GOFF displacements. This is 'const' since it should
+ /// never be modified by anything except the APIs on this class.
+ const DisplacementTable &getTable() const { return Displacements; }
+
+ uint32_t getNextDisplacement() const { return NextDisplacement; }
+ };
+
+ AssociatedDataAreaTable ADATable;
+
+ // Record a list of GlobalAlias associated with a GlobalObject.
+ // This is used for z/OS's extra-label-at-definition aliasing strategy.
+ // This is similar to what is done for AIX.
+ DenseMap<const GlobalObject *, SmallVector<const GlobalAlias *, 1>>
+ GOAliasMap;
+
+ void calculatePPA1();
+ void emitPPA2(Module &M);
+ void emitADASection();
+ void emitIDRLSection(Module &M);
+ void emitCallInformation(CallType CT);
+
+ SystemZTargetzOSStreamer *getTargetStreamer() {
+ MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
+ assert(TS && "do not have a target streamer");
+ return static_cast<SystemZTargetzOSStreamer *>(TS);
+ }
+
+public:
+ SystemZXPLINKAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> Streamer);
+
+ // Override AsmPrinter.
+ void emitInstruction(const MachineInstr *MI) override;
+ void emitXXStructorList(const DataLayout &DL, const Constant *List,
+ bool IsCtor) override;
+ void emitEndOfAsmFile(Module &M) override;
+ bool doInitialization(Module &M) override;
+ void emitFunctionEntryLabel() override;
+ void emitFunctionBodyEnd() override;
+ void emitStartOfAsmFile(Module &M) override;
+ void emitGlobalAlias(const Module &M, const GlobalAlias &GA) override;
+ const MCExpr *lowerConstant(const Constant *CV,
+ const Constant *BaseCV = nullptr,
+ uint64_t Offset = 0) override;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_SYSTEMZ_SYSTEMZXPLINKASMPRINTER_H
>From b60efa3efd2318451ac8e465075e05394e045355 Mon Sep 17 00:00:00 2001
From: Yusra Syeda <yusra.syeda at ibm.com>
Date: Tue, 11 Aug 2026 10:36:32 -0400
Subject: [PATCH 2/5] fix formatting
---
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 9 +-
.../Target/SystemZ/SystemZELFAsmPrinter.cpp | 143 ++++++++----------
.../lib/Target/SystemZ/SystemZELFAsmPrinter.h | 2 +-
.../SystemZ/SystemZXPLINKAsmPrinter.cpp | 67 ++++----
.../Target/SystemZ/SystemZXPLINKAsmPrinter.h | 2 +-
5 files changed, 104 insertions(+), 119 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index d4c274bb6bd14..78f4ee79aa414 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -12,14 +12,14 @@
//===----------------------------------------------------------------------===//
#include "SystemZAsmPrinter.h"
-#include "SystemZELFAsmPrinter.h"
-#include "SystemZXPLINKAsmPrinter.h"
#include "MCTargetDesc/SystemZGNUInstPrinter.h"
#include "MCTargetDesc/SystemZHLASMInstPrinter.h"
#include "MCTargetDesc/SystemZMCAsmInfo.h"
#include "MCTargetDesc/SystemZMCTargetDesc.h"
+#include "SystemZELFAsmPrinter.h"
#include "SystemZMCInstLower.h"
#include "SystemZSubtarget.h"
+#include "SystemZXPLINKAsmPrinter.h"
#include "TargetInfo/SystemZTargetInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCExpr.h"
@@ -634,8 +634,9 @@ char SystemZAsmPrinter::ID = 0;
INITIALIZE_PASS(SystemZAsmPrinter, "systemz-asm-printer",
"SystemZ Assembly Printer", false, false)
-static AsmPrinter *createSystemZAsmPrinter(TargetMachine &TM,
- std::unique_ptr<MCStreamer> &&Streamer) {
+static AsmPrinter *
+createSystemZAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> &&Streamer) {
if (TM.getTargetTriple().isOSzOS())
return new SystemZXPLINKAsmPrinter(TM, std::move(Streamer));
return new SystemZELFAsmPrinter(TM, std::move(Streamer));
diff --git a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
index d7f12674ea244..c7aaca973e4f6 100644
--- a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
@@ -33,19 +33,16 @@ static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
if (NumBytes < 2) {
llvm_unreachable("Zero nops?");
return 0;
- }
- else if (NumBytes < 4) {
+ } else if (NumBytes < 4) {
OutStreamer.emitInstruction(
MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
return 2;
- }
- else if (NumBytes < 6) {
+ } else if (NumBytes < 6) {
OutStreamer.emitInstruction(
MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
STI);
return 4;
- }
- else {
+ } else {
MCSymbol *DotSym = OutContext.createTempSymbol();
const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
OutStreamer.emitLabel(DotSym);
@@ -63,12 +60,11 @@ static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
StringRef Name = "_GLOBAL_OFFSET_TABLE_";
- return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
- Context);
+ return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), Context);
}
-SystemZELFAsmPrinter::SystemZELFAsmPrinter(
- TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
+SystemZELFAsmPrinter::SystemZELFAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> Streamer)
: SystemZAsmPrinter(TM, std::move(Streamer)) {}
void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
@@ -102,46 +98,45 @@ void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
case SystemZ::CallBRASL: {
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BRASL)
- .addReg(Regs->getReturnFunctionAddressRegister())
- .addExpr(Lower.getExpr(MI->getOperand(0),
- SystemZ::S_PLT)));
+ EmitToStreamer(
+ *OutStreamer,
+ MCInstBuilder(SystemZ::BRASL)
+ .addReg(Regs->getReturnFunctionAddressRegister())
+ .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT)));
return;
}
case SystemZ::CallJG:
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::JG).addExpr(
- Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT)));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::JG)
+ .addExpr(Lower.getExpr(MI->getOperand(0),
+ SystemZ::S_PLT)));
return;
case SystemZ::CallBRCL:
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BRCL)
- .addImm(MI->getOperand(0).getImm())
- .addImm(MI->getOperand(1).getImm())
- .addExpr(Lower.getExpr(MI->getOperand(2),
- SystemZ::S_PLT)));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRCL)
+ .addImm(MI->getOperand(0).getImm())
+ .addImm(MI->getOperand(1).getImm())
+ .addExpr(Lower.getExpr(MI->getOperand(2),
+ SystemZ::S_PLT)));
return;
case SystemZ::TLS_GDCALL: {
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BRASL)
- .addReg(Regs->getReturnFunctionAddressRegister())
- .addExpr(getTLSGetOffset(MF->getContext()))
- .addExpr(Lower.getExpr(MI->getOperand(0),
- SystemZ::S_TLSGD)));
+ EmitToStreamer(
+ *OutStreamer,
+ MCInstBuilder(SystemZ::BRASL)
+ .addReg(Regs->getReturnFunctionAddressRegister())
+ .addExpr(getTLSGetOffset(MF->getContext()))
+ .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSGD)));
return;
}
case SystemZ::TLS_LDCALL: {
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BRASL)
- .addReg(Regs->getReturnFunctionAddressRegister())
- .addExpr(getTLSGetOffset(MF->getContext()))
- .addExpr(Lower.getExpr(MI->getOperand(0),
- SystemZ::S_TLSLDM)));
+ EmitToStreamer(
+ *OutStreamer,
+ MCInstBuilder(SystemZ::BRASL)
+ .addReg(Regs->getReturnFunctionAddressRegister())
+ .addExpr(getTLSGetOffset(MF->getContext()))
+ .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSLDM)));
return;
}
case SystemZ::GOT:
@@ -163,7 +158,7 @@ void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
}
void SystemZELFAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
- SystemZMCInstLower &Lower) {
+ SystemZMCInstLower &Lower) {
MCContext &Ctx = MF->getContext();
if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
MCSymbol *DotSym = OutContext.createTempSymbol();
@@ -206,8 +201,7 @@ void SystemZELFAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
MachineBasicBlock::const_iterator MII(MI);
++MII;
while (ShadowBytes < NumNOPBytes) {
- if (MII == MBB.end() ||
- MII->getOpcode() == TargetOpcode::PATCHPOINT ||
+ if (MII == MBB.end() || MII->getOpcode() == TargetOpcode::PATCHPOINT ||
MII->getOpcode() == TargetOpcode::STACKMAP)
break;
ShadowBytes += TII->getInstSizeInBytes(*MII);
@@ -225,7 +219,7 @@ void SystemZELFAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
// Lower a patchpoint of the form:
// [<def>], <id>, <numBytes>, <target>, <numArgs>
void SystemZELFAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
- SystemZMCInstLower &Lower) {
+ SystemZMCInstLower &Lower) {
auto &Ctx = OutStreamer->getContext();
MCSymbol *MILabel = Ctx.createTempSymbol();
OutStreamer->emitLabel(MILabel);
@@ -248,26 +242,26 @@ void SystemZELFAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
// Materialize the call target address
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
- .addReg(ScratchReg)
- .addImm(CallTarget & 0xFFFFFFFF));
+ .addReg(ScratchReg)
+ .addImm(CallTarget & 0xFFFFFFFF));
EncodedBytes += 6;
if (CallTarget >> 32) {
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
- .addReg(ScratchReg)
- .addImm(CallTarget >> 32));
+ .addReg(ScratchReg)
+ .addImm(CallTarget >> 32));
EncodedBytes += 6;
}
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
- .addReg(SystemZ::R14D)
- .addReg(ScratchReg));
+ .addReg(SystemZ::R14D)
+ .addReg(ScratchReg));
EncodedBytes += 2;
}
} else if (CalleeMO.isGlobal()) {
const MCExpr *Expr = Lower.getExpr(CalleeMO, SystemZ::S_PLT);
- EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R14D)
- .addExpr(Expr));
+ EmitToStreamer(
+ *OutStreamer,
+ MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R14D).addExpr(Expr));
EncodedBytes += 6;
}
@@ -313,34 +307,32 @@ void SystemZELFAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
MCSymbol *EndOfSled = OutContext.createTempSymbol();
OutStreamer->emitLabel(BeginOfSled);
EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::J).addExpr(
- MCSymbolRefExpr::create(EndOfSled, OutContext)));
+ MCInstBuilder(SystemZ::J)
+ .addExpr(MCSymbolRefExpr::create(EndOfSled, OutContext)));
EmitNop(OutContext, *OutStreamer, 2, getSubtargetInfo());
EmitToStreamer(*OutStreamer,
MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R14D)
- .addExpr(MCSymbolRefExpr::create(
- FuncEntry, SystemZ::S_PLT, OutContext)));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
+ .addReg(SystemZ::R14D)
+ .addExpr(MCSymbolRefExpr::create(
+ FuncEntry, SystemZ::S_PLT, OutContext)));
OutStreamer->emitLabel(EndOfSled);
recordSled(BeginOfSled, MI, SledKind::FUNCTION_ENTER, 2);
}
void SystemZELFAsmPrinter::LowerPATCHABLE_RET(const MachineInstr &MI,
- SystemZMCInstLower &Lower) {
+ SystemZMCInstLower &Lower) {
unsigned OpCode = MI.getOperand(0).getImm();
MCSymbol *FallthroughLabel = nullptr;
if (OpCode == SystemZ::CondReturn) {
FallthroughLabel = OutContext.createTempSymbol();
int64_t Cond0 = MI.getOperand(1).getImm();
int64_t Cond1 = MI.getOperand(2).getImm();
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BRC)
- .addImm(Cond0)
- .addImm(Cond1 ^ Cond0)
- .addExpr(MCSymbolRefExpr::create(FallthroughLabel,
- OutContext)));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRC)
+ .addImm(Cond0)
+ .addImm(Cond1 ^ Cond0)
+ .addExpr(MCSymbolRefExpr::create(
+ FallthroughLabel, OutContext)));
}
// .begin:
// br %r14 # -> stmg %r2, %r15, 24(%r15)
@@ -363,16 +355,16 @@ void SystemZELFAsmPrinter::LowerPATCHABLE_RET(const MachineInstr &MI,
EmitNop(OutContext, *OutStreamer, 4, getSubtargetInfo());
EmitToStreamer(*OutStreamer,
MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::J).addExpr(MCSymbolRefExpr::create(
- FuncExit, SystemZ::S_PLT, OutContext)));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::J)
+ .addExpr(MCSymbolRefExpr::create(
+ FuncExit, SystemZ::S_PLT, OutContext)));
if (FallthroughLabel)
OutStreamer->emitLabel(FallthroughLabel);
recordSled(BeginOfSled, MI, SledKind::FUNCTION_EXIT, 2);
}
-void SystemZELFAsmPrinter::lowerLOAD_TLS_BLOCK_ADDR(
- const MachineInstr &MI, SystemZMCInstLower &Lower) {
+void SystemZELFAsmPrinter::lowerLOAD_TLS_BLOCK_ADDR(const MachineInstr &MI,
+ SystemZMCInstLower &Lower) {
Register AddrReg = MI.getOperand(0).getReg();
const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
@@ -420,11 +412,10 @@ void SystemZELFAsmPrinter::lowerLOAD_GLOBAL_STACKGUARD_ADDR(
}
// Emit the address load.
if (M->getPICLevel() == PICLevel::NotPIC) {
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::LARL)
- .addReg(AddrReg)
- .addExpr(MCSymbolRefExpr::create(getSymbol(GV),
- OutContext)));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LARL)
+ .addReg(AddrReg)
+ .addExpr(MCSymbolRefExpr::create(
+ getSymbol(GV), OutContext)));
} else {
EmitToStreamer(*OutStreamer,
MCInstBuilder(SystemZ::LGRL)
@@ -463,7 +454,7 @@ static uint8_t getSpecifierFromModifier(SystemZCP::SystemZCPModifier Modifier) {
void SystemZELFAsmPrinter::emitMachineConstantPoolValue(
MachineConstantPoolValue *MCPV) {
- auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
+ auto *ZCPV = static_cast<SystemZConstantPoolValue *>(MCPV);
const MCExpr *Expr = MCSymbolRefExpr::create(
getSymbol(ZCPV->getGlobalValue()),
@@ -473,6 +464,4 @@ void SystemZELFAsmPrinter::emitMachineConstantPoolValue(
OutStreamer->emitValue(Expr, Size);
}
-void SystemZELFAsmPrinter::emitEndOfAsmFile(Module &M) {
- emitAttributes(M);
-}
+void SystemZELFAsmPrinter::emitEndOfAsmFile(Module &M) { emitAttributes(M); }
diff --git a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.h
index 2e7916840583b..796b568b3ff0b 100644
--- a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.h
@@ -43,7 +43,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZELFAsmPrinter : public SystemZAsmPrinter {
SystemZMCInstLower &Lower);
void LowerPATCHABLE_RET(const MachineInstr &MI, SystemZMCInstLower &Lower);
void lowerLOAD_TLS_BLOCK_ADDR(const MachineInstr &MI,
- SystemZMCInstLower &Lower);
+ SystemZMCInstLower &Lower);
void lowerLOAD_GLOBAL_STACKGUARD_ADDR(const MachineInstr &MI,
SystemZMCInstLower &Lower);
void emitAttributes(Module &M);
diff --git a/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp
index 72cd1ee222788..bb16e3cc2c169 100644
--- a/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.cpp
@@ -59,12 +59,12 @@ bool SystemZXPLINKAsmPrinter::doInitialization(Module &M) {
if (IsFunc) {
if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage())
OutContext.reportError({},
- "Weak alias/reference not supported on z/OS");
+ "Weak alias/reference not supported on z/OS");
GOAliasMap[Aliasee].push_back(&Alias);
} else
- OutContext.reportError(
- {}, "Only aliases to functions is supported in GOFF.");
+ OutContext.reportError({},
+ "Only aliases to functions is supported in GOFF.");
}
return AsmPrinter::doInitialization(M);
}
@@ -81,8 +81,9 @@ void SystemZXPLINKAsmPrinter::emitCallInformation(CallType CT) {
.addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
}
-uint32_t SystemZXPLINKAsmPrinter::AssociatedDataAreaTable::insert(
- const MCSymbol *Sym, unsigned SlotKind) {
+uint32_t
+SystemZXPLINKAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,
+ unsigned SlotKind) {
auto Key = std::make_pair(Sym, SlotKind);
auto It = Displacements.find(Key);
@@ -131,27 +132,23 @@ void SystemZXPLINKAsmPrinter::emitInstruction(const MachineInstr *MI) {
switch (MI->getOpcode()) {
case SystemZ::CallBRASL_XPLINK64:
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R7D)
- .addExpr(Lower.getExpr(MI->getOperand(0),
- SystemZ::S_None)));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
+ .addReg(SystemZ::R7D)
+ .addExpr(Lower.getExpr(MI->getOperand(0),
+ SystemZ::S_None)));
emitCallInformation(CallType::BRASL7);
return;
case SystemZ::CallBASR_XPLINK64:
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BASR)
- .addReg(SystemZ::R7D)
- .addReg(MI->getOperand(0).getReg()));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
+ .addReg(SystemZ::R7D)
+ .addReg(MI->getOperand(0).getReg()));
emitCallInformation(CallType::BASR76);
return;
case SystemZ::Return_XPLINK:
- LoweredMI = MCInstBuilder(SystemZ::B)
- .addReg(SystemZ::R7D)
- .addImm(2)
- .addReg(0);
+ LoweredMI =
+ MCInstBuilder(SystemZ::B).addReg(SystemZ::R7D).addImm(2).addReg(0);
break;
case SystemZ::CondReturn_XPLINK:
@@ -164,10 +161,9 @@ void SystemZXPLINKAsmPrinter::emitInstruction(const MachineInstr *MI) {
break;
case SystemZ::CallBASR_STACKEXT:
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BASR)
- .addReg(SystemZ::R3D)
- .addReg(MI->getOperand(0).getReg()));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
+ .addReg(SystemZ::R3D)
+ .addReg(MI->getOperand(0).getReg()));
emitCallInformation(CallType::BASR33);
return;
@@ -195,17 +191,16 @@ void SystemZXPLINKAsmPrinter::emitInstruction(const MachineInstr *MI) {
MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
} else
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::ALGFI)
- .addReg(TargetReg)
- .addReg(TargetReg)
- .addImm(Disp));
+ .addReg(TargetReg)
+ .addReg(TargetReg)
+ .addImm(Disp));
Disp = 0;
Op = Op0;
}
- EmitToStreamer(*OutStreamer, MCInstBuilder(Op)
- .addReg(TargetReg)
- .addReg(ADAReg)
- .addImm(Disp)
- .addReg(IndexReg));
+ EmitToStreamer(
+ *OutStreamer,
+ MCInstBuilder(Op).addReg(TargetReg).addReg(ADAReg).addImm(Disp).addReg(
+ IndexReg));
return;
}
@@ -217,8 +212,8 @@ void SystemZXPLINKAsmPrinter::emitInstruction(const MachineInstr *MI) {
}
void SystemZXPLINKAsmPrinter::emitXXStructorList(const DataLayout &DL,
- const Constant *List,
- bool IsCtor) {
+ const Constant *List,
+ bool IsCtor) {
assert(TM.getTargetTriple().isOSBinFormatGOFF() && "Only GOFF supported");
SmallVector<Structor, 8> Structors;
@@ -756,7 +751,7 @@ void SystemZXPLINKAsmPrinter::emitPPA2(Module &M) {
}
void SystemZXPLINKAsmPrinter::emitGlobalAlias(const Module &M,
- const GlobalAlias &GA) {
+ const GlobalAlias &GA) {
if (!TM.getTargetTriple().isOSzOS())
return AsmPrinter::emitGlobalAlias(M, GA);
@@ -764,8 +759,8 @@ void SystemZXPLINKAsmPrinter::emitGlobalAlias(const Module &M,
}
const MCExpr *SystemZXPLINKAsmPrinter::lowerConstant(const Constant *CV,
- const Constant *BaseCV,
- uint64_t Offset) {
+ const Constant *BaseCV,
+ uint64_t Offset) {
const GlobalAlias *GA = dyn_cast<GlobalAlias>(CV);
const GlobalVariable *GV = dyn_cast<GlobalVariable>(CV);
const Function *FV = dyn_cast<Function>(CV);
@@ -784,7 +779,7 @@ const MCExpr *SystemZXPLINKAsmPrinter::lowerConstant(const Constant *CV,
OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
if (FV->hasExternalLinkage())
return MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),
- SystemZ::S_VCon, OutContext);
+ SystemZ::S_VCon, OutContext);
// Trigger creation of function descriptor in ADA for internal
// functions.
unsigned Disp = ADATable.insert(Sym, SystemZII::MO_ADA_DIRECT_FUNC_DESC);
diff --git a/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.h
index 4d480db06b2db..5b3b1aa78fa42 100644
--- a/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZXPLINKAsmPrinter.h
@@ -105,7 +105,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZXPLINKAsmPrinter
public:
SystemZXPLINKAsmPrinter(TargetMachine &TM,
- std::unique_ptr<MCStreamer> Streamer);
+ std::unique_ptr<MCStreamer> Streamer);
// Override AsmPrinter.
void emitInstruction(const MachineInstr *MI) override;
>From fa05b2f41ff01d0c9398a560a5b91396066a4797 Mon Sep 17 00:00:00 2001
From: Yusra Syeda <yusra.syeda at ibm.com>
Date: Fri, 21 Aug 2026 13:42:06 -0400
Subject: [PATCH 3/5] use r14 directly
---
llvm/lib/Target/SystemZ/CMakeLists.txt | 4 ++--
llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp | 16 ++++------------
2 files changed, 6 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/CMakeLists.txt b/llvm/lib/Target/SystemZ/CMakeLists.txt
index 1dd74c3ff8d5c..51021b30fd073 100644
--- a/llvm/lib/Target/SystemZ/CMakeLists.txt
+++ b/llvm/lib/Target/SystemZ/CMakeLists.txt
@@ -18,11 +18,10 @@ add_public_tablegen_target(SystemZCommonTableGen)
add_llvm_target(SystemZCodeGen
SystemZAsmPrinter.cpp
- SystemZELFAsmPrinter.cpp
- SystemZXPLINKAsmPrinter.cpp
SystemZCallingConv.cpp
SystemZConstantPoolValue.cpp
SystemZCopyPhysRegs.cpp
+ SystemZELFAsmPrinter.cpp
SystemZElimCompare.cpp
SystemZFrameLowering.cpp
SystemZHazardRecognizer.cpp
@@ -43,6 +42,7 @@ add_llvm_target(SystemZCodeGen
SystemZTargetObjectFile.cpp
SystemZTargetTransformInfo.cpp
SystemZTDC.cpp
+ SystemZXPLINKAsmPrinter.cpp
LINK_COMPONENTS
Analysis
diff --git a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
index c7aaca973e4f6..6a935cdd91a87 100644
--- a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
@@ -87,21 +87,17 @@ void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
LowerPATCHABLE_RET(*MI, Lower);
return;
case SystemZ::CallBASR: {
- const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
- SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
EmitToStreamer(*OutStreamer,
MCInstBuilder(SystemZ::BASR)
- .addReg(Regs->getReturnFunctionAddressRegister())
+ .addReg(SystemZ::R14D)
.addReg(MI->getOperand(0).getReg()));
return;
}
case SystemZ::CallBRASL: {
- const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
- SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
EmitToStreamer(
*OutStreamer,
MCInstBuilder(SystemZ::BRASL)
- .addReg(Regs->getReturnFunctionAddressRegister())
+ .addReg(SystemZ::R14D)
.addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT)));
return;
}
@@ -118,23 +114,19 @@ void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
SystemZ::S_PLT)));
return;
case SystemZ::TLS_GDCALL: {
- const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
- SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
EmitToStreamer(
*OutStreamer,
MCInstBuilder(SystemZ::BRASL)
- .addReg(Regs->getReturnFunctionAddressRegister())
+ .addReg(SystemZ::R14D)
.addExpr(getTLSGetOffset(MF->getContext()))
.addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSGD)));
return;
}
case SystemZ::TLS_LDCALL: {
- const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
- SystemZCallingConventionRegisters *Regs = Subtarget.getSpecialRegisters();
EmitToStreamer(
*OutStreamer,
MCInstBuilder(SystemZ::BRASL)
- .addReg(Regs->getReturnFunctionAddressRegister())
+ .addReg(SystemZ::R14D)
.addExpr(getTLSGetOffset(MF->getContext()))
.addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSLDM)));
return;
>From 263d9eb73afc8b975709bf87186d15f9ec2f87b4 Mon Sep 17 00:00:00 2001
From: Yusra Syeda <yusra.syeda at ibm.com>
Date: Mon, 24 Aug 2026 12:45:42 -0400
Subject: [PATCH 4/5] formatting fix
---
.../Target/SystemZ/SystemZELFAsmPrinter.cpp | 27 +++++++++----------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
index 6a935cdd91a87..a9d47ab2c5713 100644
--- a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
@@ -87,18 +87,16 @@ void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
LowerPATCHABLE_RET(*MI, Lower);
return;
case SystemZ::CallBASR: {
- EmitToStreamer(*OutStreamer,
- MCInstBuilder(SystemZ::BASR)
- .addReg(SystemZ::R14D)
- .addReg(MI->getOperand(0).getReg()));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
+ .addReg(SystemZ::R14D)
+ .addReg(MI->getOperand(0).getReg()));
return;
}
case SystemZ::CallBRASL: {
- EmitToStreamer(
- *OutStreamer,
- MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R14D)
- .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT)));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
+ .addReg(SystemZ::R14D)
+ .addExpr(Lower.getExpr(MI->getOperand(0),
+ SystemZ::S_PLT)));
return;
}
case SystemZ::CallJG:
@@ -114,12 +112,11 @@ void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
SystemZ::S_PLT)));
return;
case SystemZ::TLS_GDCALL: {
- EmitToStreamer(
- *OutStreamer,
- MCInstBuilder(SystemZ::BRASL)
- .addReg(SystemZ::R14D)
- .addExpr(getTLSGetOffset(MF->getContext()))
- .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSGD)));
+ EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
+ .addReg(SystemZ::R14D)
+ .addExpr(getTLSGetOffset(MF->getContext()))
+ .addExpr(Lower.getExpr(MI->getOperand(0),
+ SystemZ::S_TLSGD)));
return;
}
case SystemZ::TLS_LDCALL: {
>From e6e5216065a68ab50825d6e4bc4bf04cc1154ef5 Mon Sep 17 00:00:00 2001
From: Yusra Syeda <yusra.syeda at ibm.com>
Date: Tue, 25 Aug 2026 10:10:29 -0400
Subject: [PATCH 5/5] remove braces
---
llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
index a9d47ab2c5713..5bdafa1d1da28 100644
--- a/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZELFAsmPrinter.cpp
@@ -86,19 +86,17 @@ void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
case TargetOpcode::PATCHABLE_RET:
LowerPATCHABLE_RET(*MI, Lower);
return;
- case SystemZ::CallBASR: {
+ case SystemZ::CallBASR:
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
.addReg(SystemZ::R14D)
.addReg(MI->getOperand(0).getReg()));
return;
- }
- case SystemZ::CallBRASL: {
+ case SystemZ::CallBRASL:
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
.addReg(SystemZ::R14D)
.addExpr(Lower.getExpr(MI->getOperand(0),
SystemZ::S_PLT)));
return;
- }
case SystemZ::CallJG:
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::JG)
.addExpr(Lower.getExpr(MI->getOperand(0),
@@ -111,15 +109,14 @@ void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
.addExpr(Lower.getExpr(MI->getOperand(2),
SystemZ::S_PLT)));
return;
- case SystemZ::TLS_GDCALL: {
+ case SystemZ::TLS_GDCALL:
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
.addReg(SystemZ::R14D)
.addExpr(getTLSGetOffset(MF->getContext()))
.addExpr(Lower.getExpr(MI->getOperand(0),
SystemZ::S_TLSGD)));
return;
- }
- case SystemZ::TLS_LDCALL: {
+ case SystemZ::TLS_LDCALL:
EmitToStreamer(
*OutStreamer,
MCInstBuilder(SystemZ::BRASL)
@@ -127,7 +124,6 @@ void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) {
.addExpr(getTLSGetOffset(MF->getContext()))
.addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSLDM)));
return;
- }
case SystemZ::GOT:
EmitToStreamer(*OutStreamer,
MCInstBuilder(SystemZ::LARL)
More information about the llvm-commits
mailing list