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 #65407

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/Basic/LangStandard.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ enum class Language : uint8_t {
HLSL,
///@}
};
const char *LanguageToString(Language L);
Copy link
Member

Choose a reason for hiding this comment

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

languageToString? This file correctly uses functionName unlike many other Clang files...


enum LangFeatures {
LineComment = (1 << 0),
Expand Down
39 changes: 39 additions & 0 deletions clang/lib/Basic/LangStandards.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,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
Expand Down
13 changes: 11 additions & 2 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1735,7 +1735,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:
Expand Down Expand Up @@ -2232,7 +2232,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");
Expand Down Expand Up @@ -2264,6 +2265,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,
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Driver/ToolChains/Clang.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
25 changes: 25 additions & 0 deletions clang/test/CodeGen/SystemZ/systemz-ppa2.c
Original file line number Diff line number Diff line change
@@ -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
Copy link
Member

Choose a reason for hiding this comment

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

Use %clang_cc1 in non-driver tests

// 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]]
1 change: 1 addition & 0 deletions llvm/include/llvm/BinaryFormat/GOFF.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,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

Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/MC/MCObjectFileInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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; }
Expand Down
26 changes: 26 additions & 0 deletions llvm/include/llvm/Support/Chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,33 @@ namespace sys {
template <typename D = std::chrono::nanoseconds>
using TimePoint = std::chrono::time_point<std::chrono::system_clock, D>;

// utc_clock and utc_time are only available since C++20. Add enough code to
// support formatting date/time in UTC.
class UtcClock : public std::chrono::system_clock {};
Copy link
Member

Choose a reason for hiding this comment

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

This Support change needs to be split from this patch with a unittest in llvm/unittest/Support.

Many people will think this z/OS patch is unrelated to them.

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 created a new PR for the UTC clock changes here: #67846


template <typename D = std::chrono::nanoseconds>
using UtcTime = std::chrono::time_point<UtcClock, D>;

/// Convert a std::time_t to a UtcTime
inline UtcTime<std::chrono::seconds> toUtcTime(std::time_t T) {
using namespace std::chrono;
return UtcTime<seconds>(seconds(T));
}

/// Convert a TimePoint to std::time_t
inline std::time_t toTimeT(TimePoint<> TP) {
using namespace std::chrono;
return system_clock::to_time_t(
time_point_cast<system_clock::time_point::duration>(TP));
}

/// Convert a UtcTime to std::time_t
inline std::time_t toTimeT(UtcTime<> TP) {
using namespace std::chrono;
return system_clock::to_time_t(time_point<system_clock, seconds>(
duration_cast<seconds>(TP.time_since_epoch())));
}

/// Convert a std::time_t to a TimePoint
inline TimePoint<std::chrono::seconds>
toTimePoint(std::time_t T) {
Expand All @@ -58,6 +78,7 @@ toTimePoint(std::time_t T, uint32_t nsec) {
} // namespace sys

raw_ostream &operator<<(raw_ostream &OS, sys::TimePoint<> TP);
raw_ostream &operator<<(raw_ostream &OS, sys::UtcTime<> TP);

/// Format provider for TimePoint<>
///
Expand All @@ -73,6 +94,11 @@ struct format_provider<sys::TimePoint<>> {
StringRef Style);
};

template <> struct format_provider<sys::UtcTime<std::chrono::seconds>> {
static void format(const sys::UtcTime<std::chrono::seconds> &TP,
llvm::raw_ostream &OS, StringRef Style);
};

namespace detail {
template <typename Period> struct unit { static const char value[]; };
template <typename Period> const char unit<Period>::value[] = "";
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/MC/MCObjectFileInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
91 changes: 64 additions & 27 deletions llvm/lib/Support/Chrono.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@ static inline struct tm getStructTM(TimePoint<> TP) {
return Storage;
}

static inline struct tm getStructTMUtc(UtcTime<> TP) {
struct tm Storage;
std::time_t OurTime = toTimeT(TP);

#if defined(LLVM_ON_UNIX)
struct tm *LT = ::gmtime_r(&OurTime, &Storage);
assert(LT);
(void)LT;
#endif
#if defined(_WIN32)
int Error = ::gmtime_s(&Storage, &OurTime);
assert(!Error);
(void)Error;
#endif

return Storage;
}

raw_ostream &operator<<(raw_ostream &OS, TimePoint<> TP) {
struct tm LT = getStructTM(TP);
char Buffer[sizeof("YYYY-MM-DD HH:MM:SS")];
Expand All @@ -50,44 +68,63 @@ raw_ostream &operator<<(raw_ostream &OS, TimePoint<> TP) {
.count()));
}

void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
StringRef Style) {
template <class T>
static void format(const T &Fractional, struct tm &LT, raw_ostream &OS,
StringRef Style) {
using namespace std::chrono;
TimePoint<seconds> Truncated = time_point_cast<seconds>(T);
auto Fractional = T - Truncated;
struct tm LT = getStructTM(Truncated);
// Handle extensions first. strftime mangles unknown %x on some platforms.
if (Style.empty()) Style = "%Y-%m-%d %H:%M:%S.%N";
if (Style.empty())
Style = "%Y-%m-%d %H:%M:%S.%N";
std::string Format;
raw_string_ostream FStream(Format);
for (unsigned I = 0; I < Style.size(); ++I) {
if (Style[I] == '%' && Style.size() > I + 1) switch (Style[I + 1]) {
case 'L': // Milliseconds, from Ruby.
FStream << llvm::format(
"%.3lu", (long)duration_cast<milliseconds>(Fractional).count());
++I;
continue;
case 'f': // Microseconds, from Python.
FStream << llvm::format(
"%.6lu", (long)duration_cast<microseconds>(Fractional).count());
++I;
continue;
case 'N': // Nanoseconds, from date(1).
FStream << llvm::format(
"%.9lu", (long)duration_cast<nanoseconds>(Fractional).count());
++I;
continue;
case '%': // Consume %%, so %%f parses as (%%)f not %(%f)
FStream << "%%";
++I;
continue;
if (Style[I] == '%' && Style.size() > I + 1)
switch (Style[I + 1]) {
case 'L': // Milliseconds, from Ruby.
FStream << llvm::format(
"%.3lu", (long)duration_cast<milliseconds>(Fractional).count());
++I;
continue;
case 'f': // Microseconds, from Python.
FStream << llvm::format(
"%.6lu", (long)duration_cast<microseconds>(Fractional).count());
++I;
continue;
case 'N': // Nanoseconds, from date(1).
FStream << llvm::format(
"%.9lu", (long)duration_cast<nanoseconds>(Fractional).count());
++I;
continue;
case '%': // Consume %%, so %%f parses as (%%)f not %(%f)
FStream << "%%";
++I;
continue;
}
FStream << Style[I];
}
FStream.flush();
char Buffer[256]; // Should be enough for anywhen.
char Buffer[256]; // Should be enough for anywhen.
size_t Len = strftime(Buffer, sizeof(Buffer), Format.c_str(), &LT);
OS << (Len ? Buffer : "BAD-DATE-FORMAT");
}

void format_provider<UtcTime<std::chrono::seconds>>::format(
const UtcTime<std::chrono::seconds> &T, raw_ostream &OS, StringRef Style) {
using namespace std::chrono;
UtcTime<seconds> Truncated =
UtcTime<seconds>(duration_cast<seconds>(T.time_since_epoch()));
auto Fractional = T - Truncated;
struct tm LT = getStructTMUtc(Truncated);
llvm::format(Fractional, LT, OS, Style);
}

void format_provider<TimePoint<>>::format(const TimePoint<> &T, raw_ostream &OS,
StringRef Style) {
using namespace std::chrono;
TimePoint<seconds> Truncated = time_point_cast<seconds>(T);
auto Fractional = T - Truncated;
struct tm LT = getStructTM(Truncated);
llvm::format(Fractional, LT, OS, Style);
}

} // namespace llvm
Loading