[clang] f740bcb - [AIX] supporting -X options for llvm-ranlib in AIX OS

via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 22 06:42:00 PDT 2023


Author: zhijian
Date: 2023-08-22T09:41:33-04:00
New Revision: f740bcb3707a17ed4ccd52157089011a586cc2a6

URL: https://github.com/llvm/llvm-project/commit/f740bcb3707a17ed4ccd52157089011a586cc2a6
DIFF: https://github.com/llvm/llvm-project/commit/f740bcb3707a17ed4ccd52157089011a586cc2a6.diff

LOG: [AIX] supporting -X options for llvm-ranlib in AIX OS

Summary:

llvm-ar is symlinked as llvm-ranlib and will act as ranlib when invoked in that mode. llvm-ar since [[ https://github.ibm.com/compiler/llvm-project/commit/4f2cfbe5314b064625b2c87bde6ce5c8d04004c5 | compiler/llvm-project at 4f2cfbe ]] supports the -X options, but doesn't seem to accept them when running as llvm-ranlib.

In AIX OS , according to https://www.ibm.com/docs/en/aix/7.2?topic=r-ranlib-command

-X mode 	Specifies the type of object file ranlib should examine. The mode must be one of the following:

32
    Processes only 32-bit object files
64
    Processes only 64-bit object files
32_64, any
    Processes both 32-bit and 64-bit object files

The default is to process 32-bit object files (ignore 64-bit objects). The mode can also be set with the OBJECT_MODE environment variable. For example, OBJECT_MODE=64 causes ranlib to process any 64-bit objects and ignore 32-bit objects. The -X flag overrides the OBJECT_MODE variable.

Reviewers: James Henderson, MaskRay, Stephen Peckham
Differential Revision: https://reviews.llvm.org/D142660

Added: 
    llvm/test/tools/llvm-ranlib/AIX-X-option-non-AIX.test
    llvm/test/tools/llvm-ranlib/aix-X-option.test

Modified: 
    clang/lib/Driver/OffloadBundler.cpp
    clang/test/lit.cfg.py
    clang/tools/clang-offload-packager/ClangOffloadPackager.cpp
    llvm/include/llvm/Object/Archive.h
    llvm/include/llvm/Object/ArchiveWriter.h
    llvm/lib/ObjCopy/Archive.cpp
    llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
    llvm/lib/Object/Archive.cpp
    llvm/lib/Object/ArchiveWriter.cpp
    llvm/lib/Object/COFFImportFile.cpp
    llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
    llvm/tools/llvm-ar/llvm-ar.cpp
    llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Driver/OffloadBundler.cpp b/clang/lib/Driver/OffloadBundler.cpp
index 0ddfb07fdad5ba..d11c41605bf39e 100644
--- a/clang/lib/Driver/OffloadBundler.cpp
+++ b/clang/lib/Driver/OffloadBundler.cpp
@@ -1265,8 +1265,9 @@ Error OffloadBundler::UnbundleArchive() {
         OutputArchivesMap.find(Target);
     if (CurArchiveMembers != OutputArchivesMap.end()) {
       if (Error WriteErr = writeArchive(FileName, CurArchiveMembers->getValue(),
-                                        true, getDefaultArchiveKindForHost(),
-                                        true, false, nullptr))
+                                        SymtabWritingMode::NormalSymtab,
+                                        getDefaultArchiveKindForHost(), true,
+                                        false, nullptr))
         return WriteErr;
     } else if (!BundlerConfig.AllowMissingBundles) {
       std::string ErrMsg =
@@ -1280,9 +1281,9 @@ Error OffloadBundler::UnbundleArchive() {
              // the missing input file.
       std::vector<llvm::NewArchiveMember> EmptyArchive;
       EmptyArchive.clear();
-      if (Error WriteErr = writeArchive(FileName, EmptyArchive, true,
-                                        getDefaultArchiveKindForHost(), true,
-                                        false, nullptr))
+      if (Error WriteErr = writeArchive(
+              FileName, EmptyArchive, SymtabWritingMode::NormalSymtab,
+              getDefaultArchiveKindForHost(), true, false, nullptr))
         return WriteErr;
     }
   }

diff  --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py
index 68e038475a5c75..815ea219aaa81e 100644
--- a/clang/test/lit.cfg.py
+++ b/clang/test/lit.cfg.py
@@ -380,16 +380,15 @@ def exclude_unsupported_files_for_aix(dirname):
 elif platform.system() == "AIX":
     config.environment["AIXTHREAD_STK"] = "4194304"
 
-# The llvm-nm tool supports an environment variable "OBJECT_MODE" on AIX OS, which
+# Some tools support an environment variable "OBJECT_MODE" on AIX OS, which
 # controls the kind of objects they will support. If there is no "OBJECT_MODE"
 # environment variable specified, the default behaviour is to support 32-bit
 # objects only. In order to not affect most test cases, which expect to support
 # 32-bit and 64-bit objects by default, set the environment variable
-# "OBJECT_MODE" to 'any' for llvm-nm on AIX OS.
+# "OBJECT_MODE" to "any" by default on AIX OS.
 
 if "system-aix" in config.available_features:
-    config.substitutions.append(("llvm-nm", "env OBJECT_MODE=any llvm-nm"))
-    config.substitutions.append(("llvm-ar", "env OBJECT_MODE=any llvm-ar"))
+   config.environment["OBJECT_MODE"] = "any"
 
 # It is not realistically possible to account for all options that could
 # possibly be present in system and user configuration files, so disable

diff  --git a/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp b/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp
index f028ea9a20a58f..7100727015e7b7 100644
--- a/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp
+++ b/clang/tools/clang-offload-packager/ClangOffloadPackager.cpp
@@ -192,9 +192,9 @@ static Error unbundleImages() {
             Binary->getImage(),
             Binary->getMemoryBufferRef().getBufferIdentifier()));
 
-      if (Error E = writeArchive(Args["file"], Members, true,
-                                 Archive::getDefaultKindForHost(), true, false,
-                                 nullptr))
+      if (Error E = writeArchive(
+              Args["file"], Members, SymtabWritingMode::NormalSymtab,
+              Archive::getDefaultKindForHost(), true, false, nullptr))
         return E;
     } else if (Args.count("file")) {
       if (Extracted.size() > 1)

diff  --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h
index 27f504779c4f52..3dd99a46507a24 100644
--- a/llvm/include/llvm/Object/Archive.h
+++ b/llvm/include/llvm/Object/Archive.h
@@ -411,12 +411,17 @@ class BigArchive : public Archive {
   uint64_t FirstChildOffset = 0;
   uint64_t LastChildOffset = 0;
   std::string MergedGlobalSymtabBuf;
+  bool Has32BitGlobalSymtab = false;
+  bool Has64BitGlobalSymtab = false;
 
 public:
   BigArchive(MemoryBufferRef Source, Error &Err);
   uint64_t getFirstChildOffset() const override { return FirstChildOffset; }
   uint64_t getLastChildOffset() const { return LastChildOffset; }
   bool isEmpty() const override { return getFirstChildOffset() == 0; }
+
+  bool has32BitGlobalSymtab() { return Has32BitGlobalSymtab; }
+  bool has64BitGlobalSymtab() { return Has64BitGlobalSymtab; }
 };
 
 } // end namespace object

diff  --git a/llvm/include/llvm/Object/ArchiveWriter.h b/llvm/include/llvm/Object/ArchiveWriter.h
index c89246f1d5694e..7f915929cd7219 100644
--- a/llvm/include/llvm/Object/ArchiveWriter.h
+++ b/llvm/include/llvm/Object/ArchiveWriter.h
@@ -40,8 +40,16 @@ struct NewArchiveMember {
 
 Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To);
 
+enum class SymtabWritingMode {
+  NoSymtab,     // Do not write symbol table.
+  NormalSymtab, // Write symbol table. For the Big Archive format, write both
+                // 32-bit and 64-bit symbol tables.
+  BigArchive32, // Only write the 32-bit symbol table.
+  BigArchive64  // Only write the 64-bit symbol table.
+};
+
 Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
-                   bool WriteSymtab, object::Archive::Kind Kind,
+                   SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
                    bool Deterministic, bool Thin,
                    std::unique_ptr<MemoryBuffer> OldArchiveBuf = nullptr,
                    bool IsEC = false);
@@ -49,8 +57,9 @@ Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
 // writeArchiveToBuffer is similar to writeArchive but returns the Archive in a
 // buffer instead of writing it out to a file.
 Expected<std::unique_ptr<MemoryBuffer>>
-writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers, bool WriteSymtab,
-                     object::Archive::Kind Kind, bool Deterministic, bool Thin);
+writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers,
+                     SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
+                     bool Deterministic, bool Thin);
 }
 
 #endif

diff  --git a/llvm/lib/ObjCopy/Archive.cpp b/llvm/lib/ObjCopy/Archive.cpp
index 742ca0b890cf26..b6da4dc1e239c8 100644
--- a/llvm/lib/ObjCopy/Archive.cpp
+++ b/llvm/lib/ObjCopy/Archive.cpp
@@ -60,8 +60,9 @@ createNewArchiveMembers(const MultiFormatConfig &Config, const Archive &Ar) {
 // For thin archives it writes the archive file itself as well as its members.
 static Error deepWriteArchive(StringRef ArcName,
                               ArrayRef<NewArchiveMember> NewMembers,
-                              bool WriteSymtab, object::Archive::Kind Kind,
-                              bool Deterministic, bool Thin) {
+                              SymtabWritingMode WriteSymtab,
+                              object::Archive::Kind Kind, bool Deterministic,
+                              bool Thin) {
   if (Kind == object::Archive::K_BSD && !NewMembers.empty() &&
       NewMembers.front().detectKindFromObject() == object::Archive::K_DARWIN)
     Kind = object::Archive::K_DARWIN;
@@ -102,8 +103,10 @@ Error executeObjcopyOnArchive(const MultiFormatConfig &Config,
     return NewArchiveMembersOrErr.takeError();
   const CommonConfig &CommonConfig = Config.getCommonConfig();
   return deepWriteArchive(CommonConfig.OutputFilename, *NewArchiveMembersOrErr,
-                          Ar.hasSymbolTable(), Ar.kind(),
-                          CommonConfig.DeterministicArchives, Ar.isThin());
+                          Ar.hasSymbolTable() ? SymtabWritingMode::NormalSymtab
+                                              : SymtabWritingMode::NoSymtab,
+                          Ar.kind(), CommonConfig.DeterministicArchives,
+                          Ar.isThin());
 }
 
 } // end namespace objcopy

diff  --git a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
index e26b363df21cc9..9d55c3d8a1a486 100644
--- a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
+++ b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp
@@ -490,10 +490,12 @@ Error objcopy::macho::executeObjcopyOnMachOUniversalBinary(
       if (Kind == object::Archive::K_BSD)
         Kind = object::Archive::K_DARWIN;
       Expected<std::unique_ptr<MemoryBuffer>> OutputBufferOrErr =
-          writeArchiveToBuffer(*NewArchiveMembersOrErr,
-                               (*ArOrErr)->hasSymbolTable(), Kind,
-                               Config.getCommonConfig().DeterministicArchives,
-                               (*ArOrErr)->isThin());
+          writeArchiveToBuffer(
+              *NewArchiveMembersOrErr,
+              (*ArOrErr)->hasSymbolTable() ? SymtabWritingMode::NormalSymtab
+                                           : SymtabWritingMode::NoSymtab,
+              Kind, Config.getCommonConfig().DeterministicArchives,
+              (*ArOrErr)->isThin());
       if (!OutputBufferOrErr)
         return OutputBufferOrErr.takeError();
       Expected<std::unique_ptr<Binary>> BinaryOrErr =

diff  --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp
index 9920145a2f3c19..bf9a1ce1de88bb 100644
--- a/llvm/lib/Object/Archive.cpp
+++ b/llvm/lib/Object/Archive.cpp
@@ -1392,6 +1392,8 @@ BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)
                                   GlobSymtab32Loc, GlobSymtab32Size, "32-bit");
     if (Err)
       return;
+
+    Has32BitGlobalSymtab = true;
   }
 
   if (GlobSymtab64Offset) {
@@ -1400,6 +1402,8 @@ BigArchive::BigArchive(MemoryBufferRef Source, Error &Err)
                                   GlobSymtab64Loc, GlobSymtab64Size, "64-bit");
     if (Err)
       return;
+
+    Has64BitGlobalSymtab = true;
   }
 
   SmallVector<GlobalSymtabInfo> SymtabInfos;

diff  --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp
index d79a5c6bef302e..abd25c4a846094 100644
--- a/llvm/lib/Object/ArchiveWriter.cpp
+++ b/llvm/lib/Object/ArchiveWriter.cpp
@@ -680,7 +680,7 @@ getSymbols(MemoryBufferRef Buf, uint16_t Index, raw_ostream &SymNames,
 static Expected<std::vector<MemberData>>
 computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
                   object::Archive::Kind Kind, bool Thin, bool Deterministic,
-                  bool NeedSymbols, SymMap *SymMap,
+                  SymtabWritingMode NeedSymbols, SymMap *SymMap,
                   ArrayRef<NewArchiveMember> NewMembers) {
   static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
 
@@ -796,7 +796,7 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
     Out.flush();
 
     std::vector<unsigned> Symbols;
-    if (NeedSymbols) {
+    if (NeedSymbols != SymtabWritingMode::NoSymtab) {
       Expected<std::vector<unsigned>> SymbolsOrErr =
           getSymbols(Buf, Index, SymNames, SymMap, HasObject);
       if (!SymbolsOrErr)
@@ -860,7 +860,8 @@ Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To) {
 
 static Error writeArchiveToStream(raw_ostream &Out,
                                   ArrayRef<NewArchiveMember> NewMembers,
-                                  bool WriteSymtab, object::Archive::Kind Kind,
+                                  SymtabWritingMode WriteSymtab,
+                                  object::Archive::Kind Kind,
                                   bool Deterministic, bool Thin, bool IsEC) {
   assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode");
 
@@ -897,6 +898,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
   uint64_t LastMemberHeaderOffset = 0;
   uint64_t NumSyms = 0;
   uint64_t NumSyms32 = 0; // Store symbol number of 32-bit member files.
+  bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab;
 
   for (const auto &M : Data) {
     // Record the start of the member's offset
@@ -910,7 +912,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
     // symbols; the second global symbol table does the same for 64-bit file
     // members. As a big archive can have both 32-bit and 64-bit file members,
     // we need to know the number of symbols in each symbol table individually.
-    if (isAIXBigArchive(Kind) && WriteSymtab) {
+    if (isAIXBigArchive(Kind) && ShouldWriteSymtab) {
       Expected<bool> Is64BitOrErr = is64BitSymbolicFile(M.Data);
       if (Error E = Is64BitOrErr.takeError())
         return E;
@@ -924,7 +926,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
 
   // The symbol table is put at the end of the big archive file. The symbol
   // table is at the start of the archive file for other archive formats.
-  if (WriteSymtab && !is64BitKind(Kind)) {
+  if (ShouldWriteSymtab && !is64BitKind(Kind)) {
     // We assume 32-bit offsets to see if 32-bit symbols are possible or not.
     HeadersSize = computeHeadersSize(Kind, Data.size(), StringTableSize,
                                      NumSyms, SymNamesBuf.size(),
@@ -962,7 +964,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
     Out << "!<arch>\n";
 
   if (!isAIXBigArchive(Kind)) {
-    if (WriteSymtab) {
+    if (ShouldWriteSymtab) {
       if (!HeadersSize)
         HeadersSize = computeHeadersSize(
             Kind, Data.size(), StringTableSize, NumSyms, SymNamesBuf.size(),
@@ -978,7 +980,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
       Out << StringTableMember.Header << StringTableMember.Data
           << StringTableMember.Padding;
 
-    if (WriteSymtab && SymMap.ECMap.size())
+    if (ShouldWriteSymtab && SymMap.ECMap.size())
       writeECSymbols(Out, Kind, Deterministic, Data, SymMap);
 
     for (const MemberData &M : Data)
@@ -1017,7 +1019,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
     raw_svector_ostream SymNames32(SymNamesBuf32);
     raw_svector_ostream SymNames64(SymNamesBuf64);
 
-    if (WriteSymtab && NumSyms)
+    if (ShouldWriteSymtab && NumSyms)
       // Generate the symbol names for the members.
       for (const NewArchiveMember &M : NewMembers) {
         MemoryBufferRef Buf = M.Buf->getMemBufferRef();
@@ -1041,11 +1043,15 @@ static Error writeArchiveToStream(raw_ostream &Out,
     // the offset to the 32-bit global symbol table, and the 'GlobSym64Offset'
     // contains the offset to the 64-bit global symbol table.
     uint64_t GlobalSymbolOffset =
-        (WriteSymtab && NumSyms32 > 0) ? MemberTableEndOffset : 0;
+        (ShouldWriteSymtab &&
+         (WriteSymtab != SymtabWritingMode::BigArchive64) && NumSyms32 > 0)
+            ? MemberTableEndOffset
+            : 0;
 
     uint64_t GlobalSymbolOffset64 = 0;
     uint64_t NumSyms64 = NumSyms - NumSyms32;
-    if (WriteSymtab && NumSyms64 > 0) {
+    if (ShouldWriteSymtab && (WriteSymtab != SymtabWritingMode::BigArchive32) &&
+        NumSyms64 > 0) {
       if (GlobalSymbolOffset == 0)
         GlobalSymbolOffset64 = MemberTableEndOffset;
       else
@@ -1095,7 +1101,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
         Out << '\0'; // Name table must be tail padded to an even number of
                      // bytes.
 
-      if (WriteSymtab) {
+      if (ShouldWriteSymtab) {
         // Write global symbol table for 32-bit file members.
         if (GlobalSymbolOffset) {
           writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf32,
@@ -1121,7 +1127,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
 }
 
 Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
-                   bool WriteSymtab, object::Archive::Kind Kind,
+                   SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
                    bool Deterministic, bool Thin,
                    std::unique_ptr<MemoryBuffer> OldArchiveBuf, bool IsEC) {
   Expected<sys::fs::TempFile> Temp =
@@ -1153,9 +1159,9 @@ Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
 }
 
 Expected<std::unique_ptr<MemoryBuffer>>
-writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers, bool WriteSymtab,
-                     object::Archive::Kind Kind, bool Deterministic,
-                     bool Thin) {
+writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers,
+                     SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
+                     bool Deterministic, bool Thin) {
   SmallVector<char, 0> ArchiveBufferVector;
   raw_svector_ostream ArchiveStream(ArchiveBufferVector);
 

diff  --git a/llvm/lib/Object/COFFImportFile.cpp b/llvm/lib/Object/COFFImportFile.cpp
index f20fa9ff6f3230..5e3508ba34aec5 100644
--- a/llvm/lib/Object/COFFImportFile.cpp
+++ b/llvm/lib/Object/COFFImportFile.cpp
@@ -610,7 +610,7 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,
         OF.createShortImport(*Name, E.Ordinal, ImportType, NameType));
   }
 
-  return writeArchive(Path, Members, /*WriteSymtab*/ true,
+  return writeArchive(Path, Members, SymtabWritingMode::NormalSymtab,
                       MinGW ? object::Archive::K_GNU : object::Archive::K_COFF,
                       /*Deterministic*/ true, /*Thin*/ false);
 }

diff  --git a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
index 158bbbdfc9b897..1c140edb07ac73 100644
--- a/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
+++ b/llvm/lib/ToolDrivers/llvm-lib/LibDriver.cpp
@@ -482,12 +482,10 @@ int llvm::libDriverMain(ArrayRef<const char *> ArgsArr) {
   std::reverse(Members.begin(), Members.end());
 
   bool Thin = Args.hasArg(OPT_llvmlibthin);
-  if (Error E =
-          writeArchive(OutputPath, Members,
-                       /*WriteSymtab=*/true,
-                       Thin ? object::Archive::K_GNU : object::Archive::K_COFF,
-                       /*Deterministic*/ true, Thin, nullptr,
-                       COFF::isArm64EC(LibMachine))) {
+  if (Error E = writeArchive(
+          OutputPath, Members, SymtabWritingMode::NormalSymtab,
+          Thin ? object::Archive::K_GNU : object::Archive::K_COFF,
+          /*Deterministic=*/true, Thin, nullptr, COFF::isArm64EC(LibMachine))) {
     handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
       llvm::errs() << OutputPath << ": " << EI.message() << "\n";
     });

diff  --git a/llvm/test/tools/llvm-ranlib/AIX-X-option-non-AIX.test b/llvm/test/tools/llvm-ranlib/AIX-X-option-non-AIX.test
new file mode 100644
index 00000000000000..537fe09219ec1f
--- /dev/null
+++ b/llvm/test/tools/llvm-ranlib/AIX-X-option-non-AIX.test
@@ -0,0 +1,6 @@
+# UNSUPPORTED: system-aix
+## Test the -X option is not supported on non-AIX os.
+
+# RUN: not llvm-ranlib -X32 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefix=INVALID-X-OPTION %s
+
+# INVALID-X-OPTION: error: -X32 option not supported on non AIX OS

diff  --git a/llvm/test/tools/llvm-ranlib/aix-X-option.test b/llvm/test/tools/llvm-ranlib/aix-X-option.test
new file mode 100644
index 00000000000000..60b849d3bd4941
--- /dev/null
+++ b/llvm/test/tools/llvm-ranlib/aix-X-option.test
@@ -0,0 +1,130 @@
+# REQUIRES: system-aix
+## Test the -X option.
+## The option specifies the type of object file on which llvm-ranlib will operate.
+
+# RUN: rm -rf %t && mkdir %t && cd %t
+# RUN: yaml2obj --docnum=1 -DFLAG=0x1DF %s -o t32_1.o
+# RUN: yaml2obj --docnum=1 -DFLAG=0x1F7 %s -o t64_1.o
+# RUN: yaml2obj --docnum=2 -DFLAG=0x1DF %s -o t32_2.o
+# RUN: yaml2obj --docnum=2 -DFLAG=0x1F7 %s -o t64_2.o
+
+# RUN: llvm-ar qS t_all.a t32_1.o t64_1.o t32_2.o t64_2.o
+# RUN: cp t_all.a t_X32.a
+# RUN: cp t_all.a t_X64.a
+# RUN: cp t_all.a t_X32_64.a
+
+## Test the OBJECT_MODE environment variable when adding symbol table.
+# RUN: unset OBJECT_MODE
+# RUN: llvm-ranlib t_X32.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s
+# RUN: cp t_all.a t_X32.a
+# RUN: env OBJECT_MODE=32 llvm-ranlib t_X32.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s
+
+# RUN: env OBJECT_MODE=64 llvm-ranlib t_X64.a
+# RUN: llvm-nm --print-armap t_X64.a 2>&1 | FileCheck --check-prefixes=GLOB64 --implicit-check-not="in t32" %s
+
+# RUN: env OBJECT_MODE=32_64 llvm-ranlib t_X32_64.a
+# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+# RUN: cp t_all.a t_X32_64.a
+# RUN: env OBJECT_MODE=any llvm-ranlib t_X32_64.a
+# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+
+# RUN: cp t_all.a t_X32.a
+# RUN: cp t_all.a t_X64.a
+# RUN: cp t_all.a t_X32_64.a
+
+## Test the -X option when adding symbol table.
+# RUN: llvm-ranlib -X32 t_X32.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s
+# RUN: llvm-ranlib -X64 t_X32.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+
+# RUN: llvm-ranlib -X64 t_X64.a
+# RUN: llvm-nm --print-armap t_X64.a 2>&1 | FileCheck --check-prefixes=GLOB64 --implicit-check-not="in t32" %s
+# RUN: llvm-ranlib -X32 t_X64.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+
+# RUN: llvm-ranlib -X32_64 t_X32_64.a
+# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+# RUN: cp t_all.a t_X32_64.a
+# RUN: llvm-ranlib -Xany t_X32_64.a
+# RUN: llvm-nm --print-armap t_X32_64.a 2>&1 | FileCheck --check-prefixes=GLOB32,GLOB64 %s
+
+# RUN: cp t_all.a t_X32.a
+# RUN: cp t_all.a t_X64.a
+
+## Test that the -X option will override the "OBJECT_MODE" environment variable.
+# RUN: env OBJECT_MODE=32_64 llvm-ranlib -X32 t_X32.a
+# RUN: llvm-nm --print-armap t_X32.a 2>&1 | FileCheck --check-prefixes=GLOB32 --implicit-check-not="in t64" %s
+
+# RUN: env OBJECT_MODE=32 llvm-ranlib -X64 t_X64.a
+# RUN: llvm-nm --print-armap t_X64.a 2>&1 | FileCheck --check-prefixes=GLOB64 --implicit-check-not="in t32" %s
+
+# GLOB32:      sym1_0x1DF in t32_1.o
+# GLOB32-NEXT: sym2_0x1DF in t32_1.o
+# GLOB32-NEXT: sym3_0x1DF in t32_2.o
+# GLOB32-NEXT: sym4_0x1DF in t32_2.o
+
+# GLOB64:      sym1_0x1F7 in t64_1.o
+# GLOB64-NEXT: sym2_0x1F7 in t64_1.o
+# GLOB64-NEXT: sym3_0x1F7 in t64_2.o
+# GLOB64-NEXT: sym4_0x1F7 in t64_2.o
+
+## Test invalid -X option and OBJECT_MODE enviornment var.
+# RUN: not env OBJECT_MODE= llvm-ranlib t_X32.a 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefixes=INVALID-OBJECT-MODE %s
+# RUN: not env OBJECT_MODE="" llvm-ranlib t_X32.a 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefixes=INVALID-OBJECT-MODE %s
+# RUN: not env OBJECT_MODE=31 llvm-ranlib t_X64.a 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefixes=INVALID-OBJECT-MODE %s
+# RUN: not llvm-ranlib -X t_X64.a 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefixes=INVALID-X-OPTION %s
+# RUN: not llvm-ranlib -X31 t_X64.a 2>&1 | FileCheck --implicit-check-not="error:"  --check-prefixes=INVALID-X-OPTION %s
+
+# INVALID-OBJECT-MODE: error: the OBJECT_MODE environment variable has an invalid value. OBJECT_MODE must be 32, 64, 32_64, or any
+# INVALID-X-OPTION: error: the specified object mode is not valid. Specify -X32, -X64, -X32_64, or -Xany
+
+--- !XCOFF
+FileHeader:
+  MagicNumber:       [[FLAG]]
+Sections:
+  - Name:            .data
+    Flags:           [ STYP_DATA ]
+Symbols:
+  - Name:            sym1_[[FLAG]]
+    Section:         .data
+    Type:            0x4000
+    StorageClass:    C_EXT
+    AuxEntries:
+     - Type:                   AUX_CSECT
+       SymbolAlignmentAndType: 0x09
+       StorageMappingClass:    XMC_RW
+  - Name:            sym2_[[FLAG]]
+    Section:         .data
+    Type:            0x4000
+    StorageClass:    C_EXT
+    AuxEntries:
+     - Type:                   AUX_CSECT
+       SymbolAlignmentAndType: 0x09
+       StorageMappingClass:    XMC_RW
+
+--- !XCOFF
+FileHeader:
+  MagicNumber:       [[FLAG]]
+Sections:
+  - Name:            .text
+    Flags:           [ STYP_DATA ]
+Symbols:
+  - Name:            sym3_[[FLAG]]
+    Section:         .text
+    Type:            0x4000
+    StorageClass:    C_EXT
+    AuxEntries:
+     - Type:                   AUX_CSECT
+       SymbolAlignmentAndType: 0x09
+       StorageMappingClass:    XMC_PR
+  - Name:            sym4_[[FLAG]]
+    Section:         .text
+    Type:            0x4000
+    StorageClass:    C_EXT
+    AuxEntries:
+     - Type:                   AUX_CSECT
+       SymbolAlignmentAndType: 0x09
+       StorageMappingClass:    XMC_PR

diff  --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp
index d21650d146a9e6..9889ad9de627d5 100644
--- a/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -69,7 +69,9 @@ static void printRanLibHelp(StringRef ToolName) {
          << "  -v --version          - Display the version of this program\n"
          << "  -D                    - Use zero for timestamps and uids/gids "
             "(default)\n"
-         << "  -U                    - Use actual timestamps and uids/gids\n";
+         << "  -U                    - Use actual timestamps and uids/gids\n"
+         << "  -X{32|64|32_64|any}   - Specify which archive symbol tables "
+            "should be generated if they do not already exist (AIX OS only)\n";
 }
 
 static void printArHelp(StringRef ToolName) {
@@ -225,7 +227,8 @@ static bool DisplayMemberOffsets = false; ///< 'O' modifier
 static bool CompareFullPath = false;      ///< 'P' modifier
 static bool OnlyUpdate = false;           ///< 'u' modifier
 static bool Verbose = false;              ///< 'v' modifier
-static bool Symtab = true;                ///< 's' modifier
+static SymtabWritingMode Symtab =
+    SymtabWritingMode::NormalSymtab;      ///< 's' modifier
 static bool Deterministic = true;         ///< 'D' and 'U' modifiers
 static bool Thin = false;                 ///< 'T' modifier
 static bool AddLibrary = false;           ///< 'L' modifier
@@ -371,11 +374,11 @@ static ArchiveOperation parseCommandLine() {
       CompareFullPath = true;
       break;
     case 's':
-      Symtab = true;
+      Symtab = SymtabWritingMode::NormalSymtab;
       MaybeJustCreateSymTab = true;
       break;
     case 'S':
-      Symtab = false;
+      Symtab = SymtabWritingMode::NoSymtab;
       break;
     case 'u':
       OnlyUpdate = true;
@@ -1074,9 +1077,31 @@ static void createSymbolTable(object::Archive *OldArchive) {
   // In summary, we only need to update the symbol table if we have none.
   // This is actually very common because of broken build systems that think
   // they have to run ranlib.
-  if (OldArchive->hasSymbolTable())
-    return;
+  if (OldArchive->hasSymbolTable()) {
+    if (OldArchive->kind() != object::Archive::K_AIXBIG)
+      return;
 
+    // For archives in the Big Archive format, the bit mode option specifies
+    // which symbol table to generate. The presence of a symbol table that does
+    // not match the specified bit mode does not prevent creation of the symbol
+    // table that has been requested.
+    if (OldArchive->kind() == object::Archive::K_AIXBIG) {
+      BigArchive *BigArc = dyn_cast<BigArchive>(OldArchive);
+      if (BigArc->has32BitGlobalSymtab() &&
+          Symtab == SymtabWritingMode::BigArchive32)
+        return;
+
+      if (BigArc->has64BitGlobalSymtab() &&
+          Symtab == SymtabWritingMode::BigArchive64)
+        return;
+
+      if (BigArc->has32BitGlobalSymtab() && BigArc->has64BitGlobalSymtab() &&
+          Symtab == SymtabWritingMode::NormalSymtab)
+        return;
+
+      Symtab = SymtabWritingMode::NormalSymtab;
+    }
+  }
   if (OldArchive->isThin())
     Thin = true;
   performWriteOperation(CreateSymTab, OldArchive, nullptr, nullptr);
@@ -1389,6 +1414,8 @@ static int ar_main(int argc, char **argv) {
 
 static int ranlib_main(int argc, char **argv) {
   std::vector<StringRef> Archives;
+  bool HasAIXXOption = false;
+
   for (int i = 1; i < argc; ++i) {
     StringRef arg(argv[i]);
     if (handleGenericOption(arg)) {
@@ -1406,6 +1433,28 @@ static int ranlib_main(int argc, char **argv) {
         } else if (arg.front() == 'v') {
           cl::PrintVersionMessage();
           return 0;
+        } else if (arg.front() == 'X') {
+          if (object::Archive::getDefaultKindForHost() ==
+              object::Archive::K_AIXBIG) {
+            HasAIXXOption = true;
+            arg.consume_front("X");
+            const char *Xarg = arg.data();
+            if (Xarg[0] == '\0') {
+              if (argv[i + 1][0] != '-')
+                BitMode = getBitMode(argv[++i]);
+              else
+                BitMode = BitModeTy::Unknown;
+            } else
+              BitMode = getBitMode(arg.data());
+
+            if (BitMode == BitModeTy::Unknown)
+              fail("the specified object mode is not valid. Specify -X32, "
+                   "-X64, -X32_64, or -Xany");
+          } else {
+            fail(Twine("-") + Twine(arg) +
+                 " option not supported on non AIX OS");
+          }
+          break;
         } else {
           // TODO: GNU ranlib also supports a -t flag
           fail("Invalid option: '-" + arg + "'");
@@ -1417,6 +1466,31 @@ static int ranlib_main(int argc, char **argv) {
     }
   }
 
+  if (object::Archive::getDefaultKindForHost() == object::Archive::K_AIXBIG) {
+    // If not specify -X option, get BitMode from enviorment variable
+    // "OBJECT_MODE" for AIX OS if specify.
+    if (!HasAIXXOption) {
+      if (char *EnvObjectMode = getenv("OBJECT_MODE")) {
+        BitMode = getBitMode(EnvObjectMode);
+        if (BitMode == BitModeTy::Unknown)
+          fail("the OBJECT_MODE environment variable has an invalid value. "
+               "OBJECT_MODE must be 32, 64, 32_64, or any");
+      }
+    }
+
+    switch (BitMode) {
+    case BitModeTy::Bit32:
+      Symtab = SymtabWritingMode::BigArchive32;
+      break;
+    case BitModeTy::Bit64:
+      Symtab = SymtabWritingMode::BigArchive64;
+      break;
+    default:
+      Symtab = SymtabWritingMode::NormalSymtab;
+      break;
+    }
+  }
+
   for (StringRef Archive : Archives) {
     ArchiveName = Archive.str();
     performOperation(CreateSymTab);

diff  --git a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
index 5e0ba139dd6bbf..9680cfa13cc5c2 100644
--- a/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
+++ b/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
@@ -594,18 +594,17 @@ static Error createStaticLibrary(LLVMContext &LLVMCtx, const Config &C) {
 
   if (NewMembers.size() == 1)
     return writeArchive(OutputFile, NewMembers.begin()->second.getMembers(),
-                        /*WriteSymtab=*/true,
+                        SymtabWritingMode::NormalSymtab,
                         /*Kind=*/object::Archive::K_DARWIN, C.Deterministic,
                         /*Thin=*/false);
 
   SmallVector<OwningBinary<Archive>, 2> OutputBinaries;
   for (const std::pair<const uint64_t, NewArchiveMemberList> &M : NewMembers) {
     Expected<std::unique_ptr<MemoryBuffer>> OutputBufferOrErr =
-        writeArchiveToBuffer(M.second.getMembers(),
-                             /*WriteSymtab=*/true,
-                             /*Kind=*/object::Archive::K_DARWIN,
-                             C.Deterministic,
-                             /*Thin=*/false);
+        writeArchiveToBuffer(
+            M.second.getMembers(), SymtabWritingMode::NormalSymtab,
+            /*Kind=*/object::Archive::K_DARWIN, C.Deterministic,
+            /*Thin=*/false);
     if (!OutputBufferOrErr)
       return OutputBufferOrErr.takeError();
     std::unique_ptr<MemoryBuffer> &OutputBuffer = OutputBufferOrErr.get();


        


More information about the cfe-commits mailing list