diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -27,6 +27,7 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/ConvertEBCDIC.h" using namespace llvm; @@ -1043,7 +1044,8 @@ } static void emitPPA1Flags(std::unique_ptr &OutStreamer, bool VarArg, - bool StackProtector, bool FPRMask, bool VRMask) { + bool StackProtector, bool FPRMask, bool VRMask, + bool HasName) { enum class PPA1Flag1 : uint8_t { DSA64Bit = (0x80 >> 0), VarArg = (0x80 >> 7), @@ -1069,7 +1071,7 @@ auto Flags1 = PPA1Flag1(0); auto Flags2 = PPA1Flag2::ExternalProcedure; auto Flags3 = PPA1Flag3(0); - auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent; + auto Flags4 = PPA1Flag4::EPMOffsetPresent; Flags1 |= PPA1Flag1::DSA64Bit; @@ -1086,6 +1088,9 @@ if (VRMask) Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag. + if (HasName) + Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block. + OutStreamer->AddComment("PPA1 Flags 1"); if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit) OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA"); @@ -1113,10 +1118,37 @@ OutStreamer->AddComment("PPA1 Flags 4"); if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask) OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area"); + if ((Flags4 & PPA1Flag4::ProcedureNamePresent) == + PPA1Flag4::ProcedureNamePresent) + OutStreamer->AddComment(" Bit 7: 1 = Name Length and Name"); OutStreamer->emitInt8(static_cast( Flags4)); // Flags 4 (optional sections, always emit these). } +static void emitPPA1Name(std::unique_ptr &OutStreamer, + StringRef OutName) { + size_t NameSize = OutName.size(); + uint16_t OutSize; + if (NameSize < UINT16_MAX) { + OutSize = static_cast(NameSize); + } else { + OutName = OutName.substr(0, UINT16_MAX); + OutSize = UINT16_MAX; + } + // Emit padding to ensure that the next optional field word-aligned. + uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4); + + SmallString<512> OutnameConv; + ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv); + OutName = OutnameConv.str(); + + OutStreamer->AddComment("Length of Name"); + OutStreamer->emitInt16(OutSize); + OutStreamer->AddComment("Name of Function"); + OutStreamer->emitBytes(OutName); + OutStreamer->emitZeros(ExtraZeros); +} + void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) { const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo(); const SystemZSubtarget &Subtarget = MF->getSubtarget(); @@ -1208,9 +1240,12 @@ OutStreamer->AddComment("Saved GPR Mask"); OutStreamer->emitInt16(SavedGPRMask); + bool HasName = + MF->getFunction().hasName() && MF->getFunction().getName().size() > 0; + emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(), MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0, - TargetHasVector && SavedVRMask != 0); + TargetHasVector && SavedVRMask != 0, HasName); OutStreamer->AddComment("Length/4 of Parms"); OutStreamer->emitInt16( @@ -1252,6 +1287,10 @@ OutStreamer->emitInt32(FrameAndVROffset); } + // Emit name length and name optional section (0x01 of flags 4) + if (HasName) + emitPPA1Name(OutStreamer, MF->getFunction().getName()); + // Emit offset to entry point optional section (0x80 of flags 4). OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym, 4); diff --git a/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll b/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll --- a/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll +++ b/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll @@ -394,6 +394,27 @@ ret i64 %o } + +; ============================= +; Tests for PPA1 Fields +; ============================= +; CHECK-LABEL: named_func +; CHECK: .byte 129 * PPA1 Flags 4 +; CHECK-NEXT: * Bit 7: 1 = Name Length and Name +define i64 @named_func(i64 %arg) { + %sum = add i64 1, %arg + ret i64 %sum +} + +; CHECK-LABEL: __unnamed_1 +; CHECK: .byte 128 * PPA1 Flags 4 +; CHECK-NOT: * Bit 7: 1 = Name Length and Name +define void @""(ptr %p) { + call i64 (ptr) @fun1(ptr %p) + ret void +} + + declare i64 @fun(i64 %arg0) declare i64 @fun1(ptr %ptr) declare i64 @fun2(i64 %n, ptr %arr0, ptr %arr1)