27
27
#include " llvm/MC/MCSectionELF.h"
28
28
#include " llvm/MC/MCStreamer.h"
29
29
#include " llvm/MC/TargetRegistry.h"
30
+ #include " llvm/Support/Chrono.h"
30
31
#include " llvm/Support/ConvertEBCDIC.h"
32
+ #include " llvm/Support/FormatProviders.h"
33
+ #include " llvm/Support/FormatVariadic.h"
31
34
32
35
using namespace llvm ;
33
36
@@ -953,6 +956,7 @@ void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
953
956
auto TT = OutContext.getTargetTriple ();
954
957
if (TT.isOSzOS ()) {
955
958
emitADASection ();
959
+ emitIDRLSection (M);
956
960
}
957
961
emitAttributes (M);
958
962
}
@@ -1026,6 +1030,72 @@ void SystemZAsmPrinter::emitADASection() {
1026
1030
OutStreamer->popSection ();
1027
1031
}
1028
1032
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
+
1029
1099
void SystemZAsmPrinter::emitFunctionBodyEnd () {
1030
1100
if (TM.getTargetTriple ().isOSzOS ()) {
1031
1101
// 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,
1150
1220
}
1151
1221
1152
1222
void SystemZAsmPrinter::emitPPA1 (MCSymbol *FnEndSym) {
1223
+ assert (PPA2Sym != nullptr && " PPA2 Symbol not defined" );
1224
+
1153
1225
const TargetRegisterInfo *TRI = MF->getRegInfo ().getTargetRegisterInfo ();
1154
1226
const SystemZSubtarget &Subtarget = MF->getSubtarget <SystemZSubtarget>();
1155
1227
const auto TargetHasVector = Subtarget.hasVector ();
@@ -1239,6 +1311,8 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
1239
1311
OutStreamer->emitInt8 (0xCE ); // CEL signature.
1240
1312
OutStreamer->AddComment (" Saved GPR Mask" );
1241
1313
OutStreamer->emitInt16 (SavedGPRMask);
1314
+ OutStreamer->AddComment (" Offset to PPA2" );
1315
+ OutStreamer->emitAbsoluteSymbolDiff (PPA2Sym, CurrentFnPPA1Sym, 4 );
1242
1316
1243
1317
bool HasName =
1244
1318
MF->getFunction ().hasName () && MF->getFunction ().getName ().size () > 0 ;
@@ -1296,6 +1370,124 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
1296
1370
4 );
1297
1371
}
1298
1372
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
+
1299
1491
void SystemZAsmPrinter::emitFunctionEntryLabel () {
1300
1492
const SystemZSubtarget &Subtarget = MF->getSubtarget <SystemZSubtarget>();
1301
1493
@@ -1318,7 +1510,7 @@ void SystemZAsmPrinter::emitFunctionEntryLabel() {
1318
1510
uint32_t DSASize = MFFrame.getStackSize ();
1319
1511
bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo ().empty ();
1320
1512
1321
- // Set Flags
1513
+ // Set Flags.
1322
1514
uint8_t Flags = 0 ;
1323
1515
if (IsLeaf)
1324
1516
Flags |= 0x08 ;
0 commit comments