Index: cmake/modules/GetHostTriple.cmake =================================================================== --- cmake/modules/GetHostTriple.cmake +++ cmake/modules/GetHostTriple.cmake @@ -23,7 +23,8 @@ 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 ) Index: lib/Support/Unix/Host.inc =================================================================== --- lib/Support/Unix/Host.inc +++ lib/Support/Unix/Host.inc @@ -49,6 +49,23 @@ 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; } Index: unittests/Support/Host.cpp =================================================================== --- unittests/Support/Host.cpp +++ 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 @@ "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 @@ 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 @@ // 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)); +} +#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; - ASSERT_NO_ERROR(fs::remove(OutputPath)); - ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); + // 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