From 6a41f396a5b18aec36a833bb37300f53658a32e8 Mon Sep 17 00:00:00 2001 From: Hubert Tong Date: Wed, 13 Mar 2019 00:12:43 +0000 Subject: [PATCH] Use AIX version detection at LLVM run-time Summary: AIX compilers define macros based on the version of the operating system. This patch implements updating of versionless AIX triples to include the host AIX version. Also, the host triple detection in the build system is adjusted to strip the AIX version information so that the run-time detection is preferred. Reviewers: xingxue, stefanp, nemanjai, jasonliu Reviewed By: xingxue Subscribers: mgorny, kristina, jdoerfert, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58798 llvm-svn: 355995 --- cmake/modules/GetHostTriple.cmake | 3 +- lib/Support/Unix/Host.inc | 17 +++++ unittests/Support/Host.cpp | 116 +++++++++++++++++++++++------- 3 files changed, 111 insertions(+), 25 deletions(-) diff --git a/cmake/modules/GetHostTriple.cmake b/cmake/modules/GetHostTriple.cmake index 7b842450b72..9a74ad6c04a 100644 --- a/cmake/modules/GetHostTriple.cmake +++ b/cmake/modules/GetHostTriple.cmake @@ -23,7 +23,8 @@ function( get_host_triple var ) if( NOT TT_RV EQUAL 0 ) message(FATAL_ERROR "Failed to execute ${config_guess}") endif( NOT TT_RV EQUAL 0 ) - set( value ${TT_OUT} ) + # Defer to dynamic detection of the host AIX version. + string(REGEX REPLACE "-aix[0-9][^-]*" "-aix" value ${TT_OUT}) endif( MSVC ) set( ${var} ${value} PARENT_SCOPE ) endfunction( get_host_triple var ) diff --git a/lib/Support/Unix/Host.inc b/lib/Support/Unix/Host.inc index 4ae261aa8cf..17d78dc18be 100644 --- a/lib/Support/Unix/Host.inc +++ b/lib/Support/Unix/Host.inc @@ -49,6 +49,23 @@ static std::string updateTripleOSVersion(std::string TargetTripleString) { TargetTripleString += "-darwin"; TargetTripleString += getOSVersion(); } + // On AIX, the AIX version and release should be that of the current host + // unless if the version has already been specified. + if (Triple(LLVM_HOST_TRIPLE).getOS() == Triple::AIX) { + Triple TT(TargetTripleString); + if (TT.getOS() == Triple::AIX && !TT.getOSMajorVersion()) { + struct utsname name; + if (uname(&name) != -1) { + std::string NewOSName = Triple::getOSTypeName(Triple::AIX); + NewOSName += name.version; + NewOSName += '.'; + NewOSName += name.release; + NewOSName += ".0.0"; + TT.setOSName(NewOSName); + return TT.str(); + } + } + } return TargetTripleString; } diff --git a/unittests/Support/Host.cpp b/unittests/Support/Host.cpp index b8093171475..89080f350aa 100644 --- a/unittests/Support/Host.cpp +++ b/unittests/Support/Host.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Host.h" +#include "llvm/Config/llvm-config.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/FileSystem.h" @@ -248,6 +249,46 @@ CPU part : 0x0a1 "tsv110"); } +static bool runAndGetCommandOutput( + const char *ExePath, ArrayRef argv, + std::unique_ptr &Buffer, off_t &Size) { + bool Success = false; + [ExePath, argv, &Buffer, &Size, &Success] { + using namespace llvm::sys; + SmallString<128> TestDirectory; + ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory)); + + SmallString<128> OutputFile(TestDirectory); + path::append(OutputFile, "out"); + StringRef OutputPath = OutputFile.str(); + + const Optional Redirects[] = { + /*STDIN=*/None, /*STDOUT=*/OutputPath, /*STDERR=*/None}; + int RetCode = ExecuteAndWait(ExePath, argv, /*env=*/llvm::None, Redirects); + ASSERT_EQ(0, RetCode); + + int FD = 0; + ASSERT_NO_ERROR(fs::openFileForRead(OutputPath, FD)); + Size = ::lseek(FD, 0, SEEK_END); + ASSERT_NE(-1, Size); + ::lseek(FD, 0, SEEK_SET); + Buffer = llvm::make_unique(Size); + ASSERT_EQ(::read(FD, Buffer.get(), Size), Size); + ::close(FD); + + ASSERT_NO_ERROR(fs::remove(OutputPath)); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); + Success = true; + }(); + return Success; +} + +TEST_F(HostTest, DummyRunAndGetCommandOutputUse) { + // Suppress defined-but-not-used warnings when the tests using the helper are + // disabled. + (void) runAndGetCommandOutput; +} + #if defined(__APPLE__) TEST_F(HostTest, getMacOSHostVersion) { using namespace llvm::sys; @@ -255,31 +296,14 @@ TEST_F(HostTest, getMacOSHostVersion) { if (!HostTriple.isMacOSX()) return; - SmallString<128> TestDirectory; - ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory)); - SmallString<128> OutputFile(TestDirectory); - path::append(OutputFile, "out"); - const char *SwVersPath = "/usr/bin/sw_vers"; StringRef argv[] = {SwVersPath, "-productVersion"}; - StringRef OutputPath = OutputFile.str(); - const Optional Redirects[] = {/*STDIN=*/None, - /*STDOUT=*/OutputPath, - /*STDERR=*/None}; - int RetCode = ExecuteAndWait(SwVersPath, argv, /*env=*/llvm::None, Redirects); - ASSERT_EQ(0, RetCode); - - int FD = 0; - ASSERT_NO_ERROR(fs::openFileForRead(OutputPath, FD)); - off_t Size = ::lseek(FD, 0, SEEK_END); - ASSERT_NE(-1, Size); - ::lseek(FD, 0, SEEK_SET); - std::unique_ptr Buffer = llvm::make_unique(Size); - ASSERT_EQ(::read(FD, Buffer.get(), Size), Size); - ::close(FD); + std::unique_ptr Buffer; + off_t Size; + ASSERT_EQ(runAndGetCommandOutput(SwVersPath, argv, Buffer, Size), true); + StringRef SystemVersion(Buffer.get(), Size); // Ensure that the two versions match. - StringRef SystemVersion(Buffer.get(), Size); unsigned SystemMajor, SystemMinor, SystemMicro; ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersion)) .getMacOSXVersion(SystemMajor, SystemMinor, SystemMicro), @@ -290,8 +314,52 @@ TEST_F(HostTest, getMacOSHostVersion) { // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin' // triples. ASSERT_EQ(std::tie(SystemMajor, SystemMinor), std::tie(HostMajor, HostMinor)); - - ASSERT_NO_ERROR(fs::remove(OutputPath)); - ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); +} +#endif + +#if defined(_AIX) +TEST_F(HostTest, AIXVersionDetect) { + using namespace llvm::sys; + + llvm::Triple HostTriple(getProcessTriple()); + ASSERT_EQ(HostTriple.getOS(), Triple::AIX); + + llvm::Triple ConfiguredHostTriple(LLVM_HOST_TRIPLE); + ASSERT_EQ(ConfiguredHostTriple.getOS(), Triple::AIX); + + const char *ExePath = "/usr/bin/oslevel"; + StringRef argv[] = {ExePath}; + std::unique_ptr Buffer; + off_t Size; + ASSERT_EQ(runAndGetCommandOutput(ExePath, argv, Buffer, Size), true); + StringRef SystemVersion(Buffer.get(), Size); + + unsigned SystemMajor, SystemMinor, SystemMicro; + llvm::Triple((Twine("powerpc-ibm-aix") + SystemVersion)) + .getOSVersion(SystemMajor, SystemMinor, SystemMicro); + + // Ensure that the host triple version (major) and release (minor) numbers, + // unless explicitly configured, match with those of the current system. + if (!ConfiguredHostTriple.getOSMajorVersion()) { + unsigned HostMajor, HostMinor, HostMicro; + HostTriple.getOSVersion(HostMajor, HostMinor, HostMicro); + ASSERT_EQ(std::tie(SystemMajor, SystemMinor), + std::tie(HostMajor, HostMinor)); + } + + llvm::Triple TargetTriple(getDefaultTargetTriple()); + if (TargetTriple.getOS() != Triple::AIX) + return; + + // Ensure that the target triple version (major) and release (minor) numbers + // match with those of the current system. + llvm::Triple ConfiguredTargetTriple(LLVM_DEFAULT_TARGET_TRIPLE); + if (ConfiguredTargetTriple.getOSMajorVersion()) + return; // The version was configured explicitly; skip. + + unsigned TargetMajor, TargetMinor, TargetMicro; + TargetTriple.getOSVersion(TargetMajor, TargetMinor, TargetMicro); + ASSERT_EQ(std::tie(SystemMajor, SystemMinor), + std::tie(TargetMajor, TargetMinor)); } #endif