Skip to content

Commit 9a38a72

Browse files
ysyedaYusra Syeda
and
Yusra Syeda
authored
[SystemZ][z/OS] This change adds support for the PPA2 section in zOS (#68926)
This PR adds support for the PPA2 fields. --------- Co-authored-by: Yusra Syeda <yusra.syeda@ibm.com>
1 parent fc6b725 commit 9a38a72

File tree

8 files changed

+300
-2
lines changed

8 files changed

+300
-2
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,41 @@ void CodeGenModule::Release() {
985985
Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
986986
getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
987987

988+
if (getTriple().isOSzOS()) {
989+
getModule().addModuleFlag(llvm::Module::Warning,
990+
"zos_product_major_version",
991+
uint32_t(CLANG_VERSION_MAJOR));
992+
getModule().addModuleFlag(llvm::Module::Warning,
993+
"zos_product_minor_version",
994+
uint32_t(CLANG_VERSION_MINOR));
995+
getModule().addModuleFlag(llvm::Module::Warning, "zos_product_patchlevel",
996+
uint32_t(CLANG_VERSION_PATCHLEVEL));
997+
std::string ProductId;
998+
#ifdef CLANG_VENDOR
999+
ProductId = #CLANG_VENDOR;
1000+
#else
1001+
ProductId = "clang";
1002+
#endif
1003+
getModule().addModuleFlag(llvm::Module::Error, "zos_product_id",
1004+
llvm::MDString::get(VMContext, ProductId));
1005+
1006+
// Record the language because we need it for the PPA2.
1007+
StringRef lang_str = languageToString(
1008+
LangStandard::getLangStandardForKind(LangOpts.LangStd).Language);
1009+
getModule().addModuleFlag(llvm::Module::Error, "zos_cu_language",
1010+
llvm::MDString::get(VMContext, lang_str));
1011+
1012+
time_t TT = PreprocessorOpts.SourceDateEpoch
1013+
? *PreprocessorOpts.SourceDateEpoch
1014+
: std::time(nullptr);
1015+
getModule().addModuleFlag(llvm::Module::Max, "zos_translation_time",
1016+
static_cast<uint64_t>(TT));
1017+
1018+
// Multiple modes will be supported here.
1019+
getModule().addModuleFlag(llvm::Module::Error, "zos_le_char_mode",
1020+
llvm::MDString::get(VMContext, "ascii"));
1021+
}
1022+
9881023
llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
9891024
if ( Arch == llvm::Triple::arm
9901025
|| Arch == llvm::Triple::armeb
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Please note the following:
2+
// + we are checking that the first bytes of the PPA2 are 0x3 0x0
3+
// for C, and 0x3 0x1 for C++
4+
// + the label for the PPA2 seems to vary on different versions.
5+
// We try to cover all cases, and use substitution blocks to
6+
// help write the tests. The contents of the PPA2 itself should
7+
// not be different.
8+
// + the [[:space:]] combines the two .byte lines into one pattern.
9+
// This is necessary because if the lines were separated, the first
10+
// .byte (i.e., the one for the 3) would, it seems, also match
11+
// the .byte line below for the 34.
12+
13+
// RUN: %clang_cc1 -triple s390x-ibm-zos -xc -S -o - %s | FileCheck %s --check-prefix CHECK-C
14+
// CHECK-C: [[PPA2:(.L)|(@@)PPA2]]:
15+
// CHECK-C-NEXT: .byte 3{{[[:space:]]*}}.byte 0
16+
// CHECK-C-NEXT: .byte 34{{$}}
17+
// CHECK-C-NEXT: .byte {{4}}
18+
// CHECK-C-NEXT: .long {{(CELQSTRT)}}-[[PPA2]]
19+
20+
// RUN: %clang_cc1 -triple s390x-ibm-zos -xc++ -S -o - %s | FileCheck %s --check-prefix CHECK-CXX
21+
// CHECK-CXX: [[PPA2:(.L)|(@@)PPA2]]:
22+
// CHECK-CXX-NEXT: .byte 3{{[[:space:]]*}}.byte 1
23+
// CHECK-CXX-NEXT: .byte 34{{$}}
24+
// CHECK-CXX-NEXT: .byte {{4}}
25+
// CHECK-CXX-NEXT: .long {{(CELQSTRT)}}-[[PPA2]]

llvm/include/llvm/BinaryFormat/GOFF.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ enum ENDEntryPointRequest : uint8_t {
167167
// \brief Subsections of the primary C_CODE section in the object file.
168168
enum SubsectionKind : uint8_t {
169169
SK_PPA1 = 2,
170+
SK_PPA2 = 4,
170171
};
171172
} // end namespace GOFF
172173

llvm/include/llvm/MC/MCObjectFileInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ class MCObjectFileInfo {
227227

228228
// GOFF specific sections.
229229
MCSection *PPA1Section = nullptr;
230+
MCSection *PPA2Section = nullptr;
230231
MCSection *ADASection = nullptr;
232+
MCSection *IDRLSection = nullptr;
231233

232234
// XCOFF specific sections
233235
MCSection *TOCBaseSection = nullptr;
@@ -431,7 +433,9 @@ class MCObjectFileInfo {
431433

432434
// GOFF specific sections.
433435
MCSection *getPPA1Section() const { return PPA1Section; }
436+
MCSection *getPPA2Section() const { return PPA2Section; }
434437
MCSection *getADASection() const { return ADASection; }
438+
MCSection *getIDRLSection() const { return IDRLSection; }
435439

436440
// XCOFF specific sections
437441
MCSection *getTOCBaseSection() const { return TOCBaseSection; }

llvm/lib/MC/MCObjectFileInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,13 @@ void MCObjectFileInfo::initGOFFMCObjectFileInfo(const Triple &T) {
547547
PPA1Section =
548548
Ctx->getGOFFSection(".ppa1", SectionKind::getMetadata(), TextSection,
549549
MCConstantExpr::create(GOFF::SK_PPA1, *Ctx));
550+
PPA2Section =
551+
Ctx->getGOFFSection(".ppa2", SectionKind::getMetadata(), TextSection,
552+
MCConstantExpr::create(GOFF::SK_PPA2, *Ctx));
550553
ADASection =
551554
Ctx->getGOFFSection(".ada", SectionKind::getData(), nullptr, nullptr);
555+
IDRLSection =
556+
Ctx->getGOFFSection("B_IDRL", SectionKind::getData(), nullptr, nullptr);
552557
}
553558

554559
void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {

llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp

Lines changed: 193 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@
2727
#include "llvm/MC/MCSectionELF.h"
2828
#include "llvm/MC/MCStreamer.h"
2929
#include "llvm/MC/TargetRegistry.h"
30+
#include "llvm/Support/Chrono.h"
3031
#include "llvm/Support/ConvertEBCDIC.h"
32+
#include "llvm/Support/FormatProviders.h"
33+
#include "llvm/Support/FormatVariadic.h"
3134

3235
using namespace llvm;
3336

@@ -953,6 +956,7 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
953956
auto TT = OutContext.getTargetTriple();
954957
if (TT.isOSzOS()) {
955958
emitADASection();
959+
emitIDRLSection(M);
956960
}
957961
emitAttributes(M);
958962
}
@@ -1026,6 +1030,72 @@ void SystemZAsmPrinter::emitADASection() {
10261030
OutStreamer->popSection();
10271031
}
10281032

1033+
static std::string getProductID(Module &M) {
1034+
std::string ProductID;
1035+
if (auto *MD = M.getModuleFlag("zos_product_id"))
1036+
ProductID = cast<MDString>(MD)->getString().str();
1037+
if (ProductID.empty())
1038+
ProductID = "LLVM";
1039+
return ProductID;
1040+
}
1041+
1042+
static uint32_t getProductVersion(Module &M) {
1043+
if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(
1044+
M.getModuleFlag("zos_product_major_version")))
1045+
return VersionVal->getZExtValue();
1046+
return LLVM_VERSION_MAJOR;
1047+
}
1048+
1049+
static uint32_t getProductRelease(Module &M) {
1050+
if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(
1051+
M.getModuleFlag("zos_product_minor_version")))
1052+
return ReleaseVal->getZExtValue();
1053+
return LLVM_VERSION_MINOR;
1054+
}
1055+
1056+
static uint32_t getProductPatch(Module &M) {
1057+
if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(
1058+
M.getModuleFlag("zos_product_patchlevel")))
1059+
return PatchVal->getZExtValue();
1060+
return LLVM_VERSION_PATCH;
1061+
}
1062+
1063+
static time_t getTranslationTime(Module &M) {
1064+
std::time_t Time = 0;
1065+
if (auto *Val = mdconst::extract_or_null<ConstantInt>(
1066+
M.getModuleFlag("zos_translation_time"))) {
1067+
long SecondsSinceEpoch = Val->getSExtValue();
1068+
Time = static_cast<time_t>(SecondsSinceEpoch);
1069+
}
1070+
return Time;
1071+
}
1072+
1073+
void SystemZAsmPrinter::emitIDRLSection(Module &M) {
1074+
OutStreamer->pushSection();
1075+
OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
1076+
constexpr unsigned IDRLDataLength = 30;
1077+
std::time_t Time = getTranslationTime(M);
1078+
1079+
uint32_t ProductVersion = getProductVersion(M);
1080+
uint32_t ProductRelease = getProductRelease(M);
1081+
1082+
std::string ProductID = getProductID(M);
1083+
1084+
SmallString<IDRLDataLength + 1> TempStr;
1085+
raw_svector_ostream O(TempStr);
1086+
O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",
1087+
ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
1088+
llvm::sys::toUtcTime(Time), "0");
1089+
SmallString<IDRLDataLength> Data;
1090+
ConverterEBCDIC::convertToEBCDIC(TempStr, Data);
1091+
1092+
OutStreamer->emitInt8(0); // Reserved.
1093+
OutStreamer->emitInt8(3); // Format.
1094+
OutStreamer->emitInt16(IDRLDataLength); // Length.
1095+
OutStreamer->emitBytes(Data.str());
1096+
OutStreamer->popSection();
1097+
}
1098+
10291099
void SystemZAsmPrinter::emitFunctionBodyEnd() {
10301100
if (TM.getTargetTriple().isOSzOS()) {
10311101
// Emit symbol for the end of function if the z/OS target streamer
@@ -1150,6 +1220,8 @@ static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer,
11501220
}
11511221

11521222
void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
1223+
assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
1224+
11531225
const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
11541226
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
11551227
const auto TargetHasVector = Subtarget.hasVector();
@@ -1239,6 +1311,8 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
12391311
OutStreamer->emitInt8(0xCE); // CEL signature.
12401312
OutStreamer->AddComment("Saved GPR Mask");
12411313
OutStreamer->emitInt16(SavedGPRMask);
1314+
OutStreamer->AddComment("Offset to PPA2");
1315+
OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4);
12421316

12431317
bool HasName =
12441318
MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
@@ -1296,6 +1370,124 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
12961370
4);
12971371
}
12981372

1373+
void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
1374+
if (TM.getTargetTriple().isOSzOS())
1375+
emitPPA2(M);
1376+
AsmPrinter::emitStartOfAsmFile(M);
1377+
}
1378+
1379+
void SystemZAsmPrinter::emitPPA2(Module &M) {
1380+
OutStreamer->pushSection();
1381+
OutStreamer->switchSection(getObjFileLowering().getPPA2Section());
1382+
MCContext &OutContext = OutStreamer->getContext();
1383+
// Make CELQSTRT symbol.
1384+
const char *StartSymbolName = "CELQSTRT";
1385+
MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
1386+
1387+
// Create symbol and assign to class field for use in PPA1.
1388+
PPA2Sym = OutContext.createTempSymbol("PPA2", false);
1389+
MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false);
1390+
1391+
std::time_t Time = getTranslationTime(M);
1392+
SmallString<15> CompilationTime; // 14 + null
1393+
raw_svector_ostream O(CompilationTime);
1394+
O << formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));
1395+
1396+
uint32_t ProductVersion = getProductVersion(M),
1397+
ProductRelease = getProductRelease(M),
1398+
ProductPatch = getProductPatch(M);
1399+
1400+
SmallString<7> Version; // 6 + null
1401+
raw_svector_ostream ostr(Version);
1402+
ostr << formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion, ProductRelease,
1403+
ProductPatch);
1404+
1405+
// Drop 0 during conversion.
1406+
SmallString<sizeof(CompilationTime) - 1> CompilationTimeStr;
1407+
SmallString<sizeof(Version) - 1> VersionStr;
1408+
1409+
ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeStr);
1410+
ConverterEBCDIC::convertToEBCDIC(Version, VersionStr);
1411+
1412+
enum class PPA2MemberId : uint8_t {
1413+
// See z/OS Language Environment Vendor Interfaces v2r5, p.23, for
1414+
// complete list. Only the C runtime is supported by this backend.
1415+
LE_C_Runtime = 3,
1416+
};
1417+
enum class PPA2MemberSubId : uint8_t {
1418+
// List of languages using the LE C runtime implementation.
1419+
C = 0x00,
1420+
CXX = 0x01,
1421+
Swift = 0x03,
1422+
Go = 0x60,
1423+
LLVMBasedLang = 0xe7,
1424+
};
1425+
// PPA2 Flags
1426+
enum class PPA2Flags : uint8_t {
1427+
CompileForBinaryFloatingPoint = 0x80,
1428+
CompiledWithXPLink = 0x01,
1429+
CompiledUnitASCII = 0x04,
1430+
HasServiceInfo = 0x20,
1431+
};
1432+
1433+
PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang;
1434+
if (auto *MD = M.getModuleFlag("zos_cu_language")) {
1435+
StringRef Language = cast<MDString>(MD)->getString();
1436+
MemberSubId = StringSwitch<PPA2MemberSubId>(Language)
1437+
.Case("C", PPA2MemberSubId::C)
1438+
.Case("C++", PPA2MemberSubId::CXX)
1439+
.Case("Swift", PPA2MemberSubId::Swift)
1440+
.Case("Go", PPA2MemberSubId::Go)
1441+
.Default(PPA2MemberSubId::LLVMBasedLang);
1442+
}
1443+
1444+
// Emit PPA2 section.
1445+
OutStreamer->emitLabel(PPA2Sym);
1446+
OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime));
1447+
OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId));
1448+
OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env
1449+
OutStreamer->emitInt8(0x04); // Control level 4 (XPLink)
1450+
OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4);
1451+
OutStreamer->emitInt32(0x00000000);
1452+
OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4);
1453+
OutStreamer->emitInt32(
1454+
0x00000000); // Offset to main entry point, always 0 (so says TR).
1455+
uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint);
1456+
Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink);
1457+
1458+
if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {
1459+
const StringRef &CharMode = cast<MDString>(MD)->getString();
1460+
if (CharMode == "ascii") {
1461+
Flgs |= static_cast<uint8_t>(
1462+
PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.
1463+
} else if (CharMode != "ebcdic") {
1464+
report_fatal_error(
1465+
"Only ascii or ebcdic are valid values for zos_le_char_mode "
1466+
"metadata");
1467+
}
1468+
}
1469+
1470+
OutStreamer->emitInt8(Flgs);
1471+
OutStreamer->emitInt8(0x00); // Reserved.
1472+
// No MD5 signature before timestamp.
1473+
// No FLOAT(AFP(VOLATILE)).
1474+
// Remaining 5 flag bits reserved.
1475+
OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits.
1476+
1477+
// Emit date and version section.
1478+
OutStreamer->emitLabel(DateVersionSym);
1479+
OutStreamer->emitBytes(CompilationTimeStr.str());
1480+
OutStreamer->emitBytes(VersionStr.str());
1481+
1482+
OutStreamer->emitInt16(0x0000); // Service level string length.
1483+
1484+
// Emit 8 byte alignment.
1485+
// Emit pointer to PPA2 label.
1486+
OutStreamer->AddComment("A(PPA2-CELQSTRT)");
1487+
OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);
1488+
OutStreamer->popSection();
1489+
}
1490+
12991491
void SystemZAsmPrinter::emitFunctionEntryLabel() {
13001492
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
13011493

@@ -1318,7 +1510,7 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
13181510
uint32_t DSASize = MFFrame.getStackSize();
13191511
bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
13201512

1321-
// Set Flags
1513+
// Set Flags.
13221514
uint8_t Flags = 0;
13231515
if (IsLeaf)
13241516
Flags |= 0x08;

llvm/lib/Target/SystemZ/SystemZAsmPrinter.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
2727
private:
2828
MCSymbol *CurrentFnPPA1Sym; // PPA1 Symbol.
2929
MCSymbol *CurrentFnEPMarkerSym; // Entry Point Marker.
30+
MCSymbol *PPA2Sym;
3031

3132
SystemZTargetStreamer *getTargetStreamer() {
3233
MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
@@ -90,12 +91,15 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
9091
AssociatedDataAreaTable ADATable;
9192

9293
void emitPPA1(MCSymbol *FnEndSym);
94+
void emitPPA2(Module &M);
9395
void emitADASection();
96+
void emitIDRLSection(Module &M);
9497

9598
public:
9699
SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
97100
: AsmPrinter(TM, std::move(Streamer)), CurrentFnPPA1Sym(nullptr),
98-
CurrentFnEPMarkerSym(nullptr), ADATable(TM.getPointerSize(0)) {}
101+
CurrentFnEPMarkerSym(nullptr), PPA2Sym(nullptr),
102+
ADATable(TM.getPointerSize(0)) {}
99103

100104
// Override AsmPrinter.
101105
StringRef getPassName() const override { return "SystemZ Assembly Printer"; }
@@ -113,6 +117,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
113117
}
114118
void emitFunctionEntryLabel() override;
115119
void emitFunctionBodyEnd() override;
120+
void emitStartOfAsmFile(Module &M) override;
116121

117122
private:
118123
void emitCallInformation(CallType CT);

0 commit comments

Comments
 (0)