Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SystemZ][z/OS] This change adds support for the PPA2 section in zOS #68926

Merged
merged 22 commits into from
Nov 27, 2023

Conversation

ysyeda
Copy link
Contributor

@ysyeda ysyeda commented Oct 12, 2023

This PR adds support for the PPA2 fields.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen mc Machine (object) code llvm:binary-utilities labels Oct 12, 2023
@llvmbot
Copy link
Member

llvmbot commented Oct 12, 2023

@llvm/pr-subscribers-clang-driver
@llvm/pr-subscribers-llvm-binary-utilities
@llvm/pr-subscribers-mc
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-codegen

Author: Yusra Syeda (ysyeda)

Changes

This PR adds support for the PPA2 fields.


Patch is 21.58 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/68926.diff

12 Files Affected:

  • (modified) clang/include/clang/Basic/LangStandard.h (+1)
  • (modified) clang/lib/Basic/LangStandards.cpp (+39)
  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+15)
  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+11-2)
  • (modified) clang/lib/Driver/ToolChains/Clang.h (+2-1)
  • (added) clang/test/CodeGen/SystemZ/systemz-ppa2.c (+25)
  • (modified) llvm/include/llvm/BinaryFormat/GOFF.h (+1)
  • (modified) llvm/include/llvm/MC/MCObjectFileInfo.h (+4)
  • (modified) llvm/lib/MC/MCObjectFileInfo.cpp (+5)
  • (modified) llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (+196-1)
  • (modified) llvm/lib/Target/SystemZ/SystemZAsmPrinter.h (+6-1)
  • (added) llvm/test/CodeGen/SystemZ/zos-ppa2.ll (+26)
diff --git a/clang/include/clang/Basic/LangStandard.h b/clang/include/clang/Basic/LangStandard.h
index 6356f16acc811e0..d94567adf2bfb99 100644
--- a/clang/include/clang/Basic/LangStandard.h
+++ b/clang/include/clang/Basic/LangStandard.h
@@ -43,6 +43,7 @@ enum class Language : uint8_t {
   HLSL,
   ///@}
 };
+const char *LanguageToString(Language L);
 
 enum LangFeatures {
   LineComment = (1 << 0),
diff --git a/clang/lib/Basic/LangStandards.cpp b/clang/lib/Basic/LangStandards.cpp
index af9cf4f273920ee..e9b75d78e820a64 100644
--- a/clang/lib/Basic/LangStandards.cpp
+++ b/clang/lib/Basic/LangStandards.cpp
@@ -10,9 +10,48 @@
 #include "clang/Config/config.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/TargetParser/Triple.h"
 using namespace clang;
 
+const char *clang::LanguageToString(Language L) {
+  // I would like to make this function and the definition of Language
+  // in the .h file simply expand the contents of a .def file.
+  // However, in the .h the members of the enum have doxygen annotations
+  // and/or comments which would be lost.
+  switch (L) {
+  case Language::Unknown:
+    return "Unknown";
+  case Language::Asm:
+    return "Asm";
+  case Language::LLVM_IR:
+    return "LLVM_IR";
+  case Language::C:
+    return "C";
+  case Language::CXX:
+    return "CXX";
+  case Language::ObjC:
+    return "ObjC";
+  case Language::ObjCXX:
+    return "ObjCXX";
+  case Language::OpenCL:
+    return "OpenCL";
+  case Language::OpenCLCXX:
+    return "OpenCLCXX";
+  case Language::CUDA:
+    return "CUDA";
+  case Language::RenderScript:
+    return "RenderScript";
+  case Language::HIP:
+    return "HIP";
+  case Language::HLSL:
+    return "HLSL";
+  }
+
+  std::string msg = llvm::formatv("Unknown value ({0}) passed to LanguageToString", (unsigned int) L);
+  llvm_unreachable(msg.c_str());
+}
+
 #define LANGSTANDARD(id, name, lang, desc, features)                           \
   static const LangStandard Lang_##id = {name, desc, features, Language::lang};
 #include "clang/Basic/LangStandards.def"
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 754377bed7f7eef..4fd5f8ad2d94c55 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -976,6 +976,21 @@ void CodeGenModule::Release() {
       Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
   getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
 
+  if (getTriple().isOSzOS()) {
+    int32_t ProductVersion, ProductRelease, ProductPatch;
+    ProductVersion = LLVM_VERSION_MAJOR,
+    ProductRelease = LLVM_VERSION_MINOR, ProductPatch = LLVM_VERSION_PATCH;
+    getModule().addModuleFlag(llvm::Module::Warning, "Product Major Version", ProductVersion);
+    getModule().addModuleFlag(llvm::Module::Warning, "Product Minor Version", ProductRelease);
+    getModule().addModuleFlag(llvm::Module::Warning, "Product Patchlevel", ProductPatch);
+
+    // Record the language because we need it for the PPA2.
+    const char *lang_str = LanguageToString(
+        LangStandard::getLangStandardForKind(LangOpts.LangStd).Language);
+    getModule().addModuleFlag(llvm::Module::Error, "zos_cu_language",
+                              llvm::MDString::get(VMContext, lang_str));
+  }
+
   llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
   if (   Arch == llvm::Triple::arm
       || Arch == llvm::Triple::armeb
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index b91126ebed0186c..4f02fa2fc3c788a 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1738,7 +1738,7 @@ void Clang::RenderTargetOptions(const llvm::Triple &EffectiveTriple,
     break;
 
   case llvm::Triple::systemz:
-    AddSystemZTargetArgs(Args, CmdArgs);
+    AddSystemZTargetArgs(EffectiveTriple, Args, CmdArgs);
     break;
 
   case llvm::Triple::x86:
@@ -2235,7 +2235,8 @@ void Clang::AddSparcTargetArgs(const ArgList &Args,
   }
 }
 
-void Clang::AddSystemZTargetArgs(const ArgList &Args,
+void Clang::AddSystemZTargetArgs(const llvm::Triple &Triple,
+                                 const ArgList &Args,
                                  ArgStringList &CmdArgs) const {
   if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) {
     CmdArgs.push_back("-tune-cpu");
@@ -2267,6 +2268,14 @@ void Clang::AddSystemZTargetArgs(const ArgList &Args,
     CmdArgs.push_back("-mfloat-abi");
     CmdArgs.push_back("soft");
   }
+
+  if (Triple.isOSzOS()) {
+    CmdArgs.push_back("-mllvm");
+    CmdArgs.push_back(
+        Args.MakeArgString(llvm::Twine("-translation-time=")
+                               .concat(llvm::Twine(std::time(nullptr)))
+                               .str()));
+  }
 }
 
 void Clang::AddX86TargetArgs(const ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/Clang.h b/clang/lib/Driver/ToolChains/Clang.h
index 0f503c4bd1c4fea..9f065f846b4cf34 100644
--- a/clang/lib/Driver/ToolChains/Clang.h
+++ b/clang/lib/Driver/ToolChains/Clang.h
@@ -69,7 +69,8 @@ class LLVM_LIBRARY_VISIBILITY Clang : public Tool {
                           llvm::opt::ArgStringList &CmdArgs) const;
   void AddSparcTargetArgs(const llvm::opt::ArgList &Args,
                           llvm::opt::ArgStringList &CmdArgs) const;
-  void AddSystemZTargetArgs(const llvm::opt::ArgList &Args,
+  void AddSystemZTargetArgs(const llvm::Triple &Triple,
+                            const llvm::opt::ArgList &Args,
                             llvm::opt::ArgStringList &CmdArgs) const;
   void AddX86TargetArgs(const llvm::opt::ArgList &Args,
                         llvm::opt::ArgStringList &CmdArgs) const;
diff --git a/clang/test/CodeGen/SystemZ/systemz-ppa2.c b/clang/test/CodeGen/SystemZ/systemz-ppa2.c
new file mode 100644
index 000000000000000..8f396fc12c75fca
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/systemz-ppa2.c
@@ -0,0 +1,25 @@
+// Please note the following:
+//   + we are checking that the first bytes of the PPA2 are 0x3 0x0
+//     for C, and 0x3 0x1 for C++
+//   + the label for the PPA2 seems to vary on different versions.
+//     We try to cover all cases, and use substitution blocks to
+//     help write the tests. The contents of the PPA2 itself should
+//     not be different.
+//   + the [[:space:]] combines the two .byte lines into one pattern.
+//     This is necessary because if the lines were separated, the first
+//     .byte (i.e., the one for the 3) would, it seems, also match
+//     the .byte line below for the 34.
+
+// RUN: %clang --target=s390x-ibm-zos -xc -S -o - %s | FileCheck %s --check-prefix CHECK-C
+// CHECK-C:        [[PPA2:(.L)|(@@)PPA2]]:
+// CHECK-C-NEXT:   .byte        3{{[[:space:]]*}}.byte 0
+// CHECK-C-NEXT:   .byte        34{{$}}
+// CHECK-C-NEXT:   .byte        {{4}}
+// CHECK-C-NEXT:   .long        {{(CELQSTRT)}}-[[PPA2]]
+
+// RUN: %clang --target=s390x-ibm-zos -xc++ -S -o - %s | FileCheck %s --check-prefix CHECK-CXX
+// CHECK-CXX:        [[PPA2:(.L)|(@@)PPA2]]:
+// CHECK-CXX-NEXT:   .byte      3{{[[:space:]]*}}.byte 1
+// CHECK-CXX-NEXT:   .byte      34{{$}}
+// CHECK-CXX-NEXT:   .byte      {{4}}
+// CHECK-CXX-NEXT:   .long      {{(CELQSTRT)}}-[[PPA2]]
diff --git a/llvm/include/llvm/BinaryFormat/GOFF.h b/llvm/include/llvm/BinaryFormat/GOFF.h
index f1a30e41b736bda..443bcfc9479a8bc 100644
--- a/llvm/include/llvm/BinaryFormat/GOFF.h
+++ b/llvm/include/llvm/BinaryFormat/GOFF.h
@@ -167,6 +167,7 @@ enum ENDEntryPointRequest : uint8_t {
 // \brief Subsections of the primary C_CODE section in the object file.
 enum SubsectionKind : uint8_t {
   SK_PPA1 = 2,
+  SK_PPA2 = 4,
 };
 } // end namespace GOFF
 
diff --git a/llvm/include/llvm/MC/MCObjectFileInfo.h b/llvm/include/llvm/MC/MCObjectFileInfo.h
index 54f696cb795fbc1..2b2adf5012defae 100644
--- a/llvm/include/llvm/MC/MCObjectFileInfo.h
+++ b/llvm/include/llvm/MC/MCObjectFileInfo.h
@@ -227,7 +227,9 @@ class MCObjectFileInfo {
 
   // GOFF specific sections.
   MCSection *PPA1Section = nullptr;
+  MCSection *PPA2Section = nullptr;
   MCSection *ADASection = nullptr;
+  MCSection *IDRLSection = nullptr;
 
   // XCOFF specific sections
   MCSection *TOCBaseSection = nullptr;
@@ -431,7 +433,9 @@ class MCObjectFileInfo {
 
   // GOFF specific sections.
   MCSection *getPPA1Section() const { return PPA1Section; }
+  MCSection *getPPA2Section() const { return PPA2Section; }
   MCSection *getADASection() const { return ADASection; }
+  MCSection *getIDRLSection() const { return IDRLSection; }
 
   // XCOFF specific sections
   MCSection *getTOCBaseSection() const { return TOCBaseSection; }
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 0b5109e41e71711..1b30645cea3c1ca 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -547,8 +547,13 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
   PPA1Section =
       Ctx->getGOFFSection(".ppa1", SectionKind::getMetadata(), TextSection,
                           MCConstantExpr::create(GOFF::SK_PPA1, *Ctx));
+  PPA2Section =
+      Ctx->getGOFFSection(".ppa2", SectionKind::getMetadata(), TextSection,
+                          MCConstantExpr::create(GOFF::SK_PPA2, *Ctx));
   ADASection =
       Ctx->getGOFFSection(".ada", SectionKind::getData(), nullptr, nullptr);
+  IDRLSection =
+      Ctx->getGOFFSection("B_IDRL", SectionKind::getData(), nullptr, nullptr);
 }
 
 void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index b3075c150ebb36f..d963009c6c158f7 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -27,10 +27,20 @@
 #include "llvm/MC/MCSectionELF.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ConvertEBCDIC.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadic.h"
 
 using namespace llvm;
 
+cl::opt<uint64_t> TranslationTime(
+    "translation-time",
+    cl::desc("sets the time of compilation in seconds since epoch"),
+    cl::init(0));
+
 // Return an RI instruction like MI with opcode Opcode, but with the
 // GR64 register operands turned into GR32s.
 static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
@@ -953,6 +963,7 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
   auto TT = OutContext.getTargetTriple();
   if (TT.isOSzOS()) {
     emitADASection();
+    emitIDRLSection(M);
   }
   emitAttributes(M);
 }
@@ -1026,6 +1037,68 @@ void SystemZAsmPrinter::emitADASection() {
   OutStreamer->popSection();
 }
 
+static uint32_t getProductVersion(Module &M) {
+  if (auto *VersionVal = cast_or_null<ConstantAsMetadata>(
+          M.getModuleFlag("Product Major Version")))
+    return cast<ConstantInt>(VersionVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MAJOR;
+}
+
+static uint32_t getProductRelease(Module &M) {
+  if (auto *ReleaseVal = cast_or_null<ConstantAsMetadata>(
+          M.getModuleFlag("Product Minor Version")))
+    return cast<ConstantInt>(ReleaseVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MINOR;
+}
+
+static uint32_t getProductPatch(Module &M) {
+  if (auto *PatchVal = cast_or_null<ConstantAsMetadata>(
+          M.getModuleFlag("Product Patchlevel")))
+    return cast<ConstantInt>(PatchVal->getValue())->getZExtValue();
+  return LLVM_VERSION_PATCH;
+}
+
+void SystemZAsmPrinter::emitIDRLSection(Module &M) {
+  OutStreamer->pushSection();
+  OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
+  constexpr unsigned IDRLDataLength = 30;
+  std::time_t Time = TranslationTime;
+
+  uint32_t ProductVersion = getProductVersion(M);
+  uint32_t ProductRelease = getProductRelease(M);
+
+  std::string ProductID;
+  if (auto *MD = M.getModuleFlag("Product Id"))
+    ProductID = cast<MDString>(MD)->getString().str();
+
+  if (ProductID.empty()) {
+    char ProductIDFormatted[11]; // 10 + null.
+    snprintf(ProductIDFormatted, sizeof(ProductIDFormatted), "LLVM  %02d%02d",
+             ProductVersion, ProductRelease);
+    ProductID = ProductIDFormatted;
+  }
+
+  // Remove - from Product Id, which makes it consistent with legacy.
+  // The binder expects alphanumeric characters only.
+  std::size_t DashFound = ProductID.find("-");
+  if (DashFound != std::string::npos)
+    ProductID.erase(ProductID.begin() + DashFound);
+
+  SmallString<IDRLDataLength + 1> TempStr;
+  raw_svector_ostream O(TempStr);
+  O << formatv("{0}{1,0-2:d}{2,0-2:d}{3:%Y-%m-%d %H:%M:%S}", ProductID.c_str(),
+               ProductVersion, ProductRelease, llvm::sys::toUtcTime(Time));
+  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
@@ -1150,6 +1223,8 @@ static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer,
 }
 
 void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
+  assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
+
   const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
   const auto TargetHasVector = Subtarget.hasVector();
@@ -1239,6 +1314,8 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
   OutStreamer->emitInt8(0xCE); // CEL signature.
   OutStreamer->AddComment("Saved GPR Mask");
   OutStreamer->emitInt16(SavedGPRMask);
+  OutStreamer->AddComment("Offset to PPA2");
+  OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4);
 
   bool HasName =
       MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
@@ -1296,6 +1373,124 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
                                       4);
 }
 
+void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
+  if (TM.getTargetTriple().isOSzOS())
+    emitPPA2(M);
+  AsmPrinter::emitStartOfAsmFile(M);
+}
+
+void SystemZAsmPrinter::emitPPA2(Module &M) {
+  OutStreamer->pushSection();
+  OutStreamer->switchSection(getObjFileLowering().getPPA2Section());
+  MCContext &OutContext = OutStreamer->getContext();
+  // Make CELQSTRT symbol.
+  const char *StartSymbolName = "CELQSTRT";
+  MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
+
+  // Create symbol and assign to class field for use in PPA1.
+  PPA2Sym = OutContext.createTempSymbol("PPA2", false);
+  MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false);
+
+  std::time_t Time = TranslationTime;
+  SmallString<15> CompilationTime; // 14 + null
+  raw_svector_ostream O(CompilationTime);
+  O << formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));
+
+  uint32_t ProductVersion = getProductVersion(M),
+           ProductRelease = getProductRelease(M),
+           ProductPatch = getProductPatch(M);
+
+  SmallString<7> Version; // 6 + null
+  raw_svector_ostream ostr(Version);
+  ostr << formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion,
+                  ProductRelease, ProductPatch);
+
+  // Drop 0 during conversion.
+  SmallString<sizeof(CompilationTime) - 1> CompilationTimeStr;
+  SmallString<sizeof(Version) - 1> VersionStr;
+
+  ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeStr);
+  ConverterEBCDIC::convertToEBCDIC(Version, VersionStr);
+
+  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("CXX", 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);
+
+  if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {
+    const StringRef &CharMode = cast<MDString>(MD)->getString();
+    if (CharMode == "ascii") {
+      Flgs |= static_cast<uint8_t>(
+          PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.
+    } else if (CharMode != "ebcdic") {
+      report_fatal_error(
+          "Only ascii or ebcdic are valid values for zos_le_char_mode "
+          "metadata");
+    }
+  }
+
+  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(CompilationTimeStr.str());
+  OutStreamer->emitBytes(VersionStr.str());
+
+  OutStreamer->emitInt16(0x0000); // Service level string length.
+
+  // Emit 8 byte alignment.
+  // Emit pointer to PPA2 label.
+  OutStreamer->AddComment("A(PPA2-CELQSTRT)");
+  OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);
+  OutStreamer->popSection();
+}
+
 void SystemZAsmPrinter::emitFunctionEntryLabel() {
   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
 
@@ -1318,7 +1513,7 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
     uint32_t DSASize = MFFrame.getStackSize();
     bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
 
-    // Set Flags
+    // Set Flags.
     uint8_t Flags = 0;
     if (IsLeaf)
       Flags |= 0x08;
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
index c9dbbfd0b4c4335..303cce1a1b65818 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
@@ -27,6 +27,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
 private:
   MCSymbol *CurrentFnPPA1Sym;     // PPA1 Symbol.
   MCSymbol *CurrentFnEPMarkerSym; // Entry Point Marker.
+  MCSymbol *PPA2Sym;
 
   SystemZTargetStreamer *getTargetStreamer() {
     MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
@@ -90,12 +91,15 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
   AssociatedDataAreaTable ADATable;
 
   void emitPPA1(MCSymbol *FnEndSym);
+  void emitPPA2(Module &M);
   void emitADASection();
+  void emitIDRLSection(Module &M);
 
 public:
   SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
       : AsmPrinter(TM, std::move(Streamer)), Cu...
[truncated]

@github-actions
Copy link

github-actions bot commented Oct 12, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@ysyeda
Copy link
Contributor Author

ysyeda commented Oct 16, 2023

ping

clang/lib/Basic/LangStandards.cpp Outdated Show resolved Hide resolved
clang/lib/Driver/ToolChains/Clang.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp Show resolved Hide resolved
clang/lib/CodeGen/CodeGenModule.cpp Outdated Show resolved Hide resolved
clang/lib/CodeGen/CodeGenModule.cpp Outdated Show resolved Hide resolved
ysyeda added a commit that referenced this pull request Oct 27, 2023
This PR adds a function which converts the language to string. This is
intended to be used by the z/OS target, see the patch here:
#68926

---------

Co-authored-by: Yusra Syeda <[email protected]>
@ysyeda
Copy link
Contributor Author

ysyeda commented Oct 30, 2023

@uweigand can you have another look over this PR? The PR for languageToString has been approved and merged, and all your remaining comments have been addressed.

clang/include/clang/Basic/LangOptions.def Outdated Show resolved Hide resolved
clang/lib/CodeGen/CodeGenModule.cpp Show resolved Hide resolved
clang/lib/CodeGen/CodeGenModule.cpp Show resolved Hide resolved
clang/lib/CodeGen/CodeGenModule.cpp Outdated Show resolved Hide resolved
clang/lib/Driver/ToolChains/Clang.cpp Outdated Show resolved Hide resolved
@ysyeda
Copy link
Contributor Author

ysyeda commented Nov 6, 2023

ping

@ysyeda
Copy link
Contributor Author

ysyeda commented Nov 13, 2023

@uweigand your comments have been addressed. Can you please give this another review?

Copy link
Member

@uweigand uweigand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please find a couple of additional comments inline, related to module flag processing.

llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp Outdated Show resolved Hide resolved
clang/lib/CodeGen/CodeGenModule.cpp Show resolved Hide resolved
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp Outdated Show resolved Hide resolved
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp Outdated Show resolved Hide resolved
// Remove - from Product Id, which makes it consistent with legacy.
std::size_t DashFound = ProductId.find("-");
if (DashFound != std::string::npos)
ProductId.erase(ProductId.begin() + DashFound);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that this code is moved here, it could only make a difference when compiling clang with a CLANG_VENDOR containing a dash. If that is a problem for your use case, then why not simply build with the desired CLANG_VENDOR to begin with? It's a bit unclear to me which general problem this code solves at this place now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proper product id contains the dash. The only place we don't include the dash is in the PPA2 timestamp string. This is to be compat with XL. We would like all uses of CLANG_VENDOR to use the proper product id (except for this one use in PPA2).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this from this PR as it's not required for the binder.

OutStreamer->emitInt8(0); // Reserved.
OutStreamer->emitInt8(3); // Format.
OutStreamer->emitInt16(IDRLDataLength); // Length.
OutStreamer->emitBytes(Data.str());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more question about this string - the Length field is hardcoded to 30. Does that mean that there are exactly 30 bytes supposed to always follow here? I'm not sure this is guaranteed by the formatv above ...

Also, there doesn't seem to be any test that verifies the layout of this IDRL section, I think we definitely need one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added testing for the IDRL section and fixed the length to be 30 bytes.

Copy link
Member

@uweigand uweigand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This version LGTM now, thanks!

@ysyeda ysyeda merged commit 9a38a72 into llvm:main Nov 27, 2023
2 checks passed
@dyung
Copy link
Collaborator

dyung commented Nov 27, 2023

@ysyeda the test you added, clang/test/CodeGen/SystemX/systemz-ppa2.c fails if the SystemZ target (I'm guessing) is not available. Can you add the proper REQUIRES line or fix the test to work without that architecture present?

https://lab.llvm.org/buildbot/#/builders/139/builds/54293

RUN: at line 13: /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/clang -cc1 -internal-isystem /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/lib/clang/18/include -nostdsysteminc -triple s390x-ibm-zos -xc -S -o - /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGen/SystemZ/systemz-ppa2.c | /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/FileCheck /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGen/SystemZ/systemz-ppa2.c --check-prefix CHECK-C
+ /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/clang -cc1 -internal-isystem /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/lib/clang/18/include -nostdsysteminc -triple s390x-ibm-zos -xc -S -o - /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGen/SystemZ/systemz-ppa2.c
+ /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/build/bin/FileCheck /home/buildbot/buildbot-root/llvm-clang-x86_64-sie-ubuntu-fast/llvm-project/clang/test/CodeGen/SystemZ/systemz-ppa2.c --check-prefix CHECK-C
error: unable to create target: 'No available targets are compatible with triple "s390x-ibm-zos"'

; CHECK: .byte 0
; CHECK: .byte 3
; CHECK: .short 30
; CHECK: .ascii "\323\323\345\324@@@@@@\361\370\360\360\361\371\367\360\360\361\360\361\360\360\360\360\360\360\360\360"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

Based on 4236d56, it appears that this test encodes the llvm version into the test. Is there some way to change this test so it does not container the llvm version in it. It's not practical to have to update this every time there is a release.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just posted a PR to make the version check a regex if the author accepts it. #79528

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category llvm:binary-utilities mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants