[llvm] fe3b621 - [AIX] support write operation of big archive.

via llvm-commits llvm-commits at lists.llvm.org
Fri May 13 07:40:37 PDT 2022


Author: zhijian
Date: 2022-05-13T10:40:15-04:00
New Revision: fe3b621f05e706fb04dec121c136b6de82a9e277

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

LOG: [AIX] support write operation of big archive.

SUMMARY

1. Enable supporting the write operation of big archive.
2. the first commit come from https://reviews.llvm.org/D104367
3. refactor the first commit and implement writing symbol table.
4. fixed the bugs and add more test cases in the second commit.

Reviewers: James Henderson
Differential Revision: https://reviews.llvm.org/D123949

Added: 
    

Modified: 
    llvm/include/llvm/Object/Archive.h
    llvm/lib/Object/ArchiveWriter.cpp
    llvm/test/Object/ar-create.test
    llvm/test/Object/archive-extract-dir.test
    llvm/test/Object/archive-malformed-object.test
    llvm/test/Object/archive-replace-pos.test
    llvm/test/Object/archive-unknown-filetype.test
    llvm/test/Object/archive-update.test
    llvm/test/Object/directory.ll
    llvm/test/tools/llvm-ar/count.test
    llvm/test/tools/llvm-ar/create.test
    llvm/test/tools/llvm-ar/dash-before-letter.test
    llvm/test/tools/llvm-ar/default-xcoff.test
    llvm/test/tools/llvm-ar/display-empty.test
    llvm/test/tools/llvm-ar/double-hyphen.test
    llvm/test/tools/llvm-ar/error-opening-permission.test
    llvm/test/tools/llvm-ar/extract.test
    llvm/test/tools/llvm-ar/flatten-thin-archive.test
    llvm/test/tools/llvm-ar/full-path-option.test
    llvm/test/tools/llvm-ar/insert-after.test
    llvm/test/tools/llvm-ar/insert-before.test
    llvm/test/tools/llvm-ar/move-after.test
    llvm/test/tools/llvm-ar/move-before.test
    llvm/test/tools/llvm-ar/mri-delete.test
    llvm/test/tools/llvm-ar/mri-nonascii.test
    llvm/test/tools/llvm-ar/non-windows-name-case.test
    llvm/test/tools/llvm-ar/plugin.test
    llvm/test/tools/llvm-ar/print.test
    llvm/test/tools/llvm-ar/read-only-archive.test
    llvm/test/tools/llvm-ar/response-utf8.test
    llvm/test/tools/llvm-ar/response.test
    llvm/test/tools/llvm-libtool-darwin/archive-flattening.test
    llvm/test/tools/llvm-link/archive.ll
    llvm/test/tools/llvm-link/archivell.ll
    llvm/test/tools/llvm-lipo/create-archive-input.test
    llvm/test/tools/llvm-nm/option-X.test
    llvm/test/tools/llvm-objcopy/MachO/universal-object.test
    llvm/test/tools/llvm-readobj/basic.test
    llvm/test/tools/llvm-size/archive.test
    llvm/tools/llvm-ar/llvm-ar.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Object/Archive.h b/llvm/include/llvm/Object/Archive.h
index 22477bcd7549..a6e336b8e9b1 100644
--- a/llvm/include/llvm/Object/Archive.h
+++ b/llvm/include/llvm/Object/Archive.h
@@ -391,6 +391,7 @@ class Archive : public Binary {
 };
 
 class BigArchive : public Archive {
+public:
   /// Fixed-Length Header.
   struct FixLenHdr {
     char Magic[sizeof(BigArchiveMagic) - 1]; ///< Big archive magic string.

diff  --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp
index f9c2ca193799..0ac11224a48c 100644
--- a/llvm/lib/Object/ArchiveWriter.cpp
+++ b/llvm/lib/Object/ArchiveWriter.cpp
@@ -25,6 +25,7 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SmallVectorMemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
@@ -127,16 +128,20 @@ static bool isDarwin(object::Archive::Kind Kind) {
          Kind == object::Archive::K_DARWIN64;
 }
 
+static bool isAIXBigArchive(object::Archive::Kind Kind) {
+  return Kind == object::Archive::K_AIXBIG;
+}
+
 static bool isBSDLike(object::Archive::Kind Kind) {
   switch (Kind) {
   case object::Archive::K_GNU:
   case object::Archive::K_GNU64:
+  case object::Archive::K_AIXBIG:
     return false;
   case object::Archive::K_BSD:
   case object::Archive::K_DARWIN:
   case object::Archive::K_DARWIN64:
     return true;
-  case object::Archive::K_AIXBIG:
   case object::Archive::K_COFF:
     break;
   }
@@ -189,6 +194,31 @@ printBSDMemberHeader(raw_ostream &Out, uint64_t Pos, StringRef Name,
     Out.write(uint8_t(0));
 }
 
+static void
+printBigArchiveMemberHeader(raw_ostream &Out, StringRef Name,
+                            const sys::TimePoint<std::chrono::seconds> &ModTime,
+                            unsigned UID, unsigned GID, unsigned Perms,
+                            uint64_t Size, unsigned PrevOffset,
+                            unsigned NextOffset) {
+  unsigned NameLen = Name.size();
+
+  printWithSpacePadding(Out, Size, 20);           // File member size
+  printWithSpacePadding(Out, NextOffset, 20);     // Next member header offset
+  printWithSpacePadding(Out, PrevOffset, 20); // Previous member header offset
+  printWithSpacePadding(Out, sys::toTimeT(ModTime), 12); // File member date
+  // The big archive format has 12 chars for uid and gid.
+  printWithSpacePadding(Out, UID % 1000000000000, 12);   // UID
+  printWithSpacePadding(Out, GID % 1000000000000, 12);   // GID
+  printWithSpacePadding(Out, format("%o", Perms), 12);   // Permission
+  printWithSpacePadding(Out, NameLen, 4);                // Name length
+  if (NameLen) {
+    printWithSpacePadding(Out, Name, NameLen); // Name
+    if (NameLen % 2)
+      Out.write(uint8_t(0)); // Null byte padding
+  }
+  Out << "`\n"; // Terminator
+}
+
 static bool useStringTable(bool Thin, StringRef Name) {
   return Thin || Name.size() >= 16 || Name.contains('/');
 }
@@ -199,8 +229,8 @@ static bool is64BitKind(object::Archive::Kind Kind) {
   case object::Archive::K_BSD:
   case object::Archive::K_DARWIN:
   case object::Archive::K_COFF:
-  case object::Archive::K_AIXBIG:
     return false;
+  case object::Archive::K_AIXBIG:
   case object::Archive::K_DARWIN64:
   case object::Archive::K_GNU64:
     return true;
@@ -304,7 +334,11 @@ static uint64_t computeSymbolTableSize(object::Archive::Kind Kind,
   // least 4-byte aligned for 32-bit content.  Opt for the larger encoding
   // uniformly.
   // We do this for all bsd formats because it simplifies aligning members.
-  uint32_t Pad = offsetToAlignment(Size, Align(isBSDLike(Kind) ? 8 : 2));
+  // For the big archive format, the symbol table is the last member, so there
+  // is no need to align.
+  uint32_t Pad = isAIXBigArchive(Kind)
+                     ? 0
+                     : offsetToAlignment(Size, Align(isBSDLike(Kind) ? 8 : 2));
   Size += Pad;
   if (Padding)
     *Padding = Pad;
@@ -312,11 +346,15 @@ static uint64_t computeSymbolTableSize(object::Archive::Kind Kind,
 }
 
 static void writeSymbolTableHeader(raw_ostream &Out, object::Archive::Kind Kind,
-                                   bool Deterministic, uint64_t Size) {
+                                   bool Deterministic, uint64_t Size,
+                                   uint64_t PrevMemberOffset = 0) {
   if (isBSDLike(Kind)) {
     const char *Name = is64BitKind(Kind) ? "__.SYMDEF_64" : "__.SYMDEF";
     printBSDMemberHeader(Out, Out.tell(), Name, now(Deterministic), 0, 0, 0,
                          Size);
+  } else if (isAIXBigArchive(Kind)) {
+    printBigArchiveMemberHeader(Out, "", now(Deterministic), 0, 0,
+                                0, Size, PrevMemberOffset, 0);
   } else {
     const char *Name = is64BitKind(Kind) ? "/SYM64" : "";
     printGNUSmallMemberHeader(Out, Name, now(Deterministic), 0, 0, 0, Size);
@@ -325,7 +363,8 @@ static void writeSymbolTableHeader(raw_ostream &Out, object::Archive::Kind Kind,
 
 static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
                              bool Deterministic, ArrayRef<MemberData> Members,
-                             StringRef StringTable) {
+                             StringRef StringTable,
+                             uint64_t PrevMemberOffset = 0) {
   // We don't write a symbol table on an archive with no members -- except on
   // Darwin, where the linker will abort unless the archive has a symbol table.
   if (StringTable.empty() && !isDarwin(Kind))
@@ -338,9 +377,10 @@ static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
   uint64_t OffsetSize = is64BitKind(Kind) ? 8 : 4;
   uint32_t Pad;
   uint64_t Size = computeSymbolTableSize(Kind, NumSyms, OffsetSize, StringTable, &Pad);
-  writeSymbolTableHeader(Out, Kind, Deterministic, Size);
+  writeSymbolTableHeader(Out, Kind, Deterministic, Size, PrevMemberOffset);
 
-  uint64_t Pos = Out.tell() + Size;
+  uint64_t Pos = isAIXBigArchive(Kind) ? sizeof(object::BigArchive::FixLenHdr)
+                                       : Out.tell() + Size;
 
   if (isBSDLike(Kind))
     printNBits(Out, Kind, NumSyms * 2 * OffsetSize);
@@ -409,9 +449,8 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
                   bool NeedSymbols, ArrayRef<NewArchiveMember> NewMembers) {
   static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
 
-  // This ignores the symbol table, but we only need the value mod 8 and the
-  // symbol table is aligned to be a multiple of 8 bytes
-  uint64_t Pos = 0;
+  uint64_t Pos =
+      isAIXBigArchive(Kind) ? sizeof(object::BigArchive::FixLenHdr) : 0;
 
   std::vector<MemberData> Ret;
   bool HasObject = false;
@@ -471,6 +510,9 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
       Entry.second = Entry.second > 1 ? 1 : 0;
   }
 
+  // The big archive format needs to know the offset of the previous member
+  // header.
+  unsigned PrevOffset = 0;
   for (const NewArchiveMember &M : NewMembers) {
     std::string Header;
     raw_string_ostream Out(Header);
@@ -503,8 +545,16 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
           std::move(StringMsg), object::object_error::parse_failed);
     }
 
-    printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M,
-                      ModTime, Size);
+    if (isAIXBigArchive(Kind)) {
+      unsigned NextOffset = Pos + sizeof(object::BigArMemHdrType) +
+                            alignTo(M.MemberName.size(), 2) + alignTo(Size, 2);
+      printBigArchiveMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
+                                  M.Perms, Size, PrevOffset, NextOffset);
+      PrevOffset = Pos;
+    } else {
+      printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M,
+                        ModTime, Size);
+    }
     Out.flush();
 
     std::vector<unsigned> Symbols;
@@ -588,22 +638,25 @@ static Error writeArchiveToStream(raw_ostream &Out,
     return E;
   std::vector<MemberData> &Data = *DataOrErr;
 
-  if (!StringTableBuf.empty())
+  if (!StringTableBuf.empty() && !isAIXBigArchive(Kind))
     Data.insert(Data.begin(), computeStringTable(StringTableBuf));
 
   // We would like to detect if we need to switch to a 64-bit symbol table.
-  if (WriteSymtab) {
-    uint64_t MaxOffset = 8; // For the file signature.
-    uint64_t LastOffset = MaxOffset;
-    uint64_t NumSyms = 0;
-    for (const auto &M : Data) {
-      // Record the start of the member's offset
-      LastOffset = MaxOffset;
-      // Account for the size of each part associated with the member.
-      MaxOffset += M.Header.size() + M.Data.size() + M.Padding.size();
-      NumSyms += M.Symbols.size();
-    }
+  uint64_t LastMemberEndOffset =
+      isAIXBigArchive(Kind) ? sizeof(object::BigArchive::FixLenHdr) : 8;
+  uint64_t LastMemberHeaderOffset = LastMemberEndOffset;
+  uint64_t NumSyms = 0;
+  for (const auto &M : Data) {
+    // Record the start of the member's offset
+    LastMemberHeaderOffset = LastMemberEndOffset;
+    // Account for the size of each part associated with the member.
+    LastMemberEndOffset += M.Header.size() + M.Data.size() + M.Padding.size();
+    NumSyms += M.Symbols.size();
+  }
 
+  // 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 && !isAIXBigArchive(Kind)) {
     // We assume 32-bit offsets to see if 32-bit symbols are possible or not.
     uint64_t SymtabSize = computeSymbolTableSize(Kind, NumSyms, 4, SymNamesBuf);
     auto computeSymbolTableHeaderSize =
@@ -613,7 +666,7 @@ static Error writeArchiveToStream(raw_ostream &Out,
           writeSymbolTableHeader(Tmp, Kind, Deterministic, SymtabSize);
           return TmpBuf.size();
         };
-    LastOffset += computeSymbolTableHeaderSize() + SymtabSize;
+    LastMemberHeaderOffset += computeSymbolTableHeaderSize() + SymtabSize;
 
     // The SYM64 format is used when an archive's member offsets are larger than
     // 32-bits can hold. The need for this shift in format is detected by
@@ -627,10 +680,10 @@ static Error writeArchiveToStream(raw_ostream &Out,
     if (Sym64Env)
       StringRef(Sym64Env).getAsInteger(10, Sym64Threshold);
 
-    // If LastOffset isn't going to fit in a 32-bit varible we need to switch
-    // to 64-bit. Note that the file can be larger than 4GB as long as the last
-    // member starts before the 4GB offset.
-    if (LastOffset >= Sym64Threshold) {
+    // If LastMemberHeaderOffset isn't going to fit in a 32-bit varible we need
+    // to switch to 64-bit. Note that the file can be larger than 4GB as long as
+    // the last member starts before the 4GB offset.
+    if (LastMemberHeaderOffset >= Sym64Threshold) {
       if (Kind == object::Archive::K_DARWIN)
         Kind = object::Archive::K_DARWIN64;
       else
@@ -640,15 +693,92 @@ static Error writeArchiveToStream(raw_ostream &Out,
 
   if (Thin)
     Out << "!<thin>\n";
+  else if (isAIXBigArchive(Kind))
+    Out << "<bigaf>\n";
   else
     Out << "!<arch>\n";
 
-  if (WriteSymtab)
-    writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf);
+  if (!isAIXBigArchive(Kind)) {
+    if (WriteSymtab)
+      writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf);
+    for (const MemberData &M : Data)
+      Out << M.Header << M.Data << M.Padding;
+  } else {
+    // For the big archive (AIX) format, compute a table of member names and
+    // offsets, used in the member table.
+    uint64_t MemberTableNameStrTblSize = 0;
+    std::vector<size_t> MemberOffsets;
+    std::vector<StringRef> MemberNames;
+    // Loop across object to find offset and names.
+    uint64_t MemberEndOffset = sizeof(object::BigArchive::FixLenHdr);
+    for (size_t I = 0, Size = NewMembers.size(); I != Size; ++I) {
+      const NewArchiveMember &Member = NewMembers[I];
+      MemberTableNameStrTblSize += Member.MemberName.size() + 1;
+      MemberOffsets.push_back(MemberEndOffset);
+      MemberNames.push_back(Member.MemberName);
+      // File member name ended with "`\n". The length is included in
+      // BigArMemHdrType.
+      MemberEndOffset += sizeof(object::BigArMemHdrType) +
+                             alignTo(Data[I].Data.size(), 2) +
+                             alignTo(Member.MemberName.size(), 2);
+    }
 
-  for (const MemberData &M : Data)
-    Out << M.Header << M.Data << M.Padding;
+    // AIX member table size.
+    unsigned MemberTableSize = 20 + // Number of members field
+                               20 * MemberOffsets.size() +
+                               MemberTableNameStrTblSize;
+
+    unsigned GlobalSymbolOffset =
+        (WriteSymtab && NumSyms > 0)
+            ? LastMemberEndOffset +
+                  alignTo(sizeof(object::BigArMemHdrType) + MemberTableSize, 2)
+            : 0;
+
+    // Fixed Sized Header.
+    printWithSpacePadding(Out, NewMembers.size() ? LastMemberEndOffset : 0,
+                          20); // Offset to member table
+    // If there are no file members in the archive, there will be no global
+    // symbol table.
+    printWithSpacePadding(Out, NewMembers.size() ? GlobalSymbolOffset : 0, 20);
+    printWithSpacePadding(
+        Out, 0,
+        20); // Offset to 64 bits global symbol table - Not supported yet
+    printWithSpacePadding(
+        Out, NewMembers.size() ? sizeof(object::BigArchive::FixLenHdr) : 0,
+        20); // Offset to first archive member
+    printWithSpacePadding(Out, NewMembers.size() ? LastMemberHeaderOffset : 0,
+                          20); // Offset to last archive member
+    printWithSpacePadding(
+        Out, 0,
+        20); // Offset to first member of free list - Not supported yet
+
+    for (const MemberData &M : Data) {
+      Out << M.Header << M.Data;
+      if (M.Data.size() % 2)
+        Out << '\0';
+    }
 
+    if (NewMembers.size()) {
+      // Member table.
+      printBigArchiveMemberHeader(Out, "", sys::toTimePoint(0), 0, 0, 0,
+                                  MemberTableSize, LastMemberHeaderOffset,
+                                  GlobalSymbolOffset);
+      printWithSpacePadding(Out, MemberOffsets.size(), 20); // Number of members
+      for (uint64_t MemberOffset : MemberOffsets)
+        printWithSpacePadding(Out, MemberOffset,
+                              20); // Offset to member file header.
+      for (StringRef MemberName : MemberNames)
+        Out << MemberName << '\0'; // Member file name, null byte padding.
+
+      if (MemberTableNameStrTblSize % 2)
+        Out << '\0'; // Name table must be tail padded to an even number of
+                     // bytes.
+
+      if (WriteSymtab && NumSyms > 0)
+        writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf,
+                         LastMemberEndOffset);
+    }
+  }
   Out.flush();
   return Error::success();
 }

diff  --git a/llvm/test/Object/ar-create.test b/llvm/test/Object/ar-create.test
index e43603416bb7..07c9ba437359 100644
--- a/llvm/test/Object/ar-create.test
+++ b/llvm/test/Object/ar-create.test
@@ -1,4 +1,3 @@
-XFAIL: system-aix
 Test which operations create an archive and which don't.
 
 RUN: touch %t

diff  --git a/llvm/test/Object/archive-extract-dir.test b/llvm/test/Object/archive-extract-dir.test
index e3e6ab4bcf6b..67d6781ee092 100644
--- a/llvm/test/Object/archive-extract-dir.test
+++ b/llvm/test/Object/archive-extract-dir.test
@@ -1,5 +1,3 @@
-XFAIL: system-aix
-
 RUN: mkdir -p %t
 RUN: cd %t
 RUN: rm -rf foo

diff  --git a/llvm/test/Object/archive-malformed-object.test b/llvm/test/Object/archive-malformed-object.test
index bb03ba0e7f75..7d502c3f301d 100644
--- a/llvm/test/Object/archive-malformed-object.test
+++ b/llvm/test/Object/archive-malformed-object.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## Show that the archive library emits error messages when adding malformed
 ## objects.
 

diff  --git a/llvm/test/Object/archive-replace-pos.test b/llvm/test/Object/archive-replace-pos.test
index 05469709789c..0acead69a1e2 100644
--- a/llvm/test/Object/archive-replace-pos.test
+++ b/llvm/test/Object/archive-replace-pos.test
@@ -1,5 +1,3 @@
-XFAIL: system-aix
-
 Test adding a member to a particular position
 
 RUN: touch %t.foo

diff  --git a/llvm/test/Object/archive-unknown-filetype.test b/llvm/test/Object/archive-unknown-filetype.test
index 88b7c36f8804..5647501c51fc 100644
--- a/llvm/test/Object/archive-unknown-filetype.test
+++ b/llvm/test/Object/archive-unknown-filetype.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## Show that the archive library does not emit an error or add any symbols to
 ## the archive symbol table, when it encounters an unknown file type, but still
 ## adds the file to the archive.

diff  --git a/llvm/test/Object/archive-update.test b/llvm/test/Object/archive-update.test
index 4af48cada71e..e152da5705c1 100644
--- a/llvm/test/Object/archive-update.test
+++ b/llvm/test/Object/archive-update.test
@@ -1,5 +1,3 @@
-XFAIL: system-aix
-
 Test the 'u' option of llvm-ar
 
 RUN: rm -rf %t && mkdir -p %t && cd %t

diff  --git a/llvm/test/Object/directory.ll b/llvm/test/Object/directory.ll
index f76d3b9ec1f8..b9da6b7ffb7a 100644
--- a/llvm/test/Object/directory.ll
+++ b/llvm/test/Object/directory.ll
@@ -1,5 +1,3 @@
-; XFAIL: system-aix
-
 ;RUN: rm -rf %t && mkdir -p %t
 ;RUN: not llvm-ar r %t/test.a . 2>&1 | FileCheck -DMSG=%errc_EISDIR %s
 ;CHECK: .: [[MSG]]

diff  --git a/llvm/test/tools/llvm-ar/count.test b/llvm/test/tools/llvm-ar/count.test
index 57c575e64740..fa6141ff13f3 100644
--- a/llvm/test/tools/llvm-ar/count.test
+++ b/llvm/test/tools/llvm-ar/count.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 # Test the 'N' count parameter.
 
 # Get a temp clean cwd to extract into.

diff  --git a/llvm/test/tools/llvm-ar/create.test b/llvm/test/tools/llvm-ar/create.test
index 0b40e05fe4be..a29b93ec5d6d 100644
--- a/llvm/test/tools/llvm-ar/create.test
+++ b/llvm/test/tools/llvm-ar/create.test
@@ -1,4 +1,3 @@
-XFAIL: system-aix
 ## Test the creation warning and supression of that warning.
 
 RUN: touch %t1.txt

diff  --git a/llvm/test/tools/llvm-ar/dash-before-letter.test b/llvm/test/tools/llvm-ar/dash-before-letter.test
index cfe2c6b3f523..43930b121736 100644
--- a/llvm/test/tools/llvm-ar/dash-before-letter.test
+++ b/llvm/test/tools/llvm-ar/dash-before-letter.test
@@ -1,4 +1,3 @@
-XFAIL: system-aix
 # Test the use of dash before key letters.
 
 RUN: touch %t1.txt

diff  --git a/llvm/test/tools/llvm-ar/default-xcoff.test b/llvm/test/tools/llvm-ar/default-xcoff.test
index bfffc3e3bb1e..9ccad825ddb3 100644
--- a/llvm/test/tools/llvm-ar/default-xcoff.test
+++ b/llvm/test/tools/llvm-ar/default-xcoff.test
@@ -1,10 +1,7 @@
-; REQUIRES: system-aix
-;; Test llvm-ar does not support Big AIX archive write operation.
-
+;; Test llvm-ar uses the big archive format for XCOFF object files by default. 
 ; RUN: yaml2obj %S/Inputs/xcoff.yaml -o %t.obj
 ; RUN: rm -f %t.ar
-; RUN: not llvm-ar cr %t.ar %t.obj 2>&1 | FileCheck %s
-; RUN: echo "test big archive" > %t.txt
-; RUN: not llvm-ar cr %t.ar %t.txt 2>&1 | FileCheck %s
+; RUN: llvm-ar cr %t.ar %t.obj
+; RUN: FileCheck %s --input-file=%t.ar
 
-; CHECK: big archive writer operation on AIX not yet supported
+; CHECK:  bigaf

diff  --git a/llvm/test/tools/llvm-ar/display-empty.test b/llvm/test/tools/llvm-ar/display-empty.test
index 77a9c8e9d1d2..ba04e0eaae7c 100644
--- a/llvm/test/tools/llvm-ar/display-empty.test
+++ b/llvm/test/tools/llvm-ar/display-empty.test
@@ -1,10 +1,9 @@
-# XFAIL: system-aix
 ## Test Display of empty archives.
 
 # RUN: rm -rf %t && mkdir -p %t
 
 ## Display empty archive:
-# RUN: llvm-ar cr %t/empty.a
+# RUN: llvm-ar cr --format=gnu %t/empty.a
 # RUN: llvm-ar tv %t/empty.a 2>&1 | count 0
 
 ## Display empty thin archive:

diff  --git a/llvm/test/tools/llvm-ar/double-hyphen.test b/llvm/test/tools/llvm-ar/double-hyphen.test
index e79165240cf3..edea626ce7f5 100644
--- a/llvm/test/tools/llvm-ar/double-hyphen.test
+++ b/llvm/test/tools/llvm-ar/double-hyphen.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## Test the use of "--" on the commandline
 
 # RUN: echo contents > %t.txt

diff  --git a/llvm/test/tools/llvm-ar/error-opening-permission.test b/llvm/test/tools/llvm-ar/error-opening-permission.test
index c5da135c39cf..4107bdfc044f 100644
--- a/llvm/test/tools/llvm-ar/error-opening-permission.test
+++ b/llvm/test/tools/llvm-ar/error-opening-permission.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## Unsupported on windows as marking files "unreadable"
 ## is non-trivial on windows.
 # UNSUPPORTED: system-windows

diff  --git a/llvm/test/tools/llvm-ar/extract.test b/llvm/test/tools/llvm-ar/extract.test
index 3f36c5af246b..d680e3e84838 100644
--- a/llvm/test/tools/llvm-ar/extract.test
+++ b/llvm/test/tools/llvm-ar/extract.test
@@ -1,10 +1,10 @@
 ## Test extract operation.
-# XFAIL: system-darwin,system-aix
+# XFAIL: system-darwin
 
 # RUN: rm -rf %t && mkdir -p %t/extracted/
 
 ## Extracting from an empty archive should not warn or error:
-# RUN: llvm-ar cr %t/empty.a
+# RUN: llvm-ar cr --format=gnu %t/empty.a
 # RUN: llvm-ar xv %t/empty.a 2>&1 | count 0
 
 # RUN: echo filea > %t/a.txt

diff  --git a/llvm/test/tools/llvm-ar/flatten-thin-archive.test b/llvm/test/tools/llvm-ar/flatten-thin-archive.test
index 865d9f199289..c9416fab8092 100644
--- a/llvm/test/tools/llvm-ar/flatten-thin-archive.test
+++ b/llvm/test/tools/llvm-ar/flatten-thin-archive.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## This test creates a thin archive that contains a thin archive, a regular
 ## archive, and a file.
 ##

diff  --git a/llvm/test/tools/llvm-ar/full-path-option.test b/llvm/test/tools/llvm-ar/full-path-option.test
index f24f1a8cafd2..3f1a6d91e90b 100644
--- a/llvm/test/tools/llvm-ar/full-path-option.test
+++ b/llvm/test/tools/llvm-ar/full-path-option.test
@@ -1,4 +1,3 @@
-XFAIL: system-aix
 # Note: many of these tests depend on relative paths, so we have to cd to a
 # test directory first.
 RUN: mkdir -p %t && cd %t
@@ -28,7 +27,7 @@ DISPLAY-NOT-FOUND: 'a/foo.txt' was not found
 
 # Deleting will fail with P because the members exist as foo.txt, not a/foo.txt.
 RUN: rm -f del1.a
-RUN: llvm-ar rcS del1.a foo.txt
+RUN: llvm-ar rcS --format=gnu del1.a foo.txt
 RUN: llvm-ar dP del1.a a/foo.txt
 RUN: llvm-ar t del1.a a/foo.txt | FileCheck %s --check-prefix=DISPLAY-FOUND --match-full-lines
 RUN: llvm-ar d del1.a a/foo.txt

diff  --git a/llvm/test/tools/llvm-ar/insert-after.test b/llvm/test/tools/llvm-ar/insert-after.test
index e3540270393c..a3f51a6d4d79 100644
--- a/llvm/test/tools/llvm-ar/insert-after.test
+++ b/llvm/test/tools/llvm-ar/insert-after.test
@@ -1,4 +1,3 @@
-XFAIL: system-aix
 ## Test inserting files after a file.
 
 RUN: touch %t1.txt

diff  --git a/llvm/test/tools/llvm-ar/insert-before.test b/llvm/test/tools/llvm-ar/insert-before.test
index ffb52b156c38..f2a6bdd4e170 100644
--- a/llvm/test/tools/llvm-ar/insert-before.test
+++ b/llvm/test/tools/llvm-ar/insert-before.test
@@ -1,4 +1,3 @@
-XFAIL: system-aix
 ## Test inserting files before a file.
 
 RUN: touch %t1.txt

diff  --git a/llvm/test/tools/llvm-ar/move-after.test b/llvm/test/tools/llvm-ar/move-after.test
index da385db4f4a7..8bd83216c689 100644
--- a/llvm/test/tools/llvm-ar/move-after.test
+++ b/llvm/test/tools/llvm-ar/move-after.test
@@ -1,4 +1,3 @@
-XFAIL: system-aix
 ## Test moving files after a file.
 
 RUN: touch %t1.txt

diff  --git a/llvm/test/tools/llvm-ar/move-before.test b/llvm/test/tools/llvm-ar/move-before.test
index 972fc9f33f1f..bab8592f8f97 100644
--- a/llvm/test/tools/llvm-ar/move-before.test
+++ b/llvm/test/tools/llvm-ar/move-before.test
@@ -1,4 +1,3 @@
-XFAIL: system-aix
 ## Test moving files after a file.
 
 RUN: touch %t1.txt

diff  --git a/llvm/test/tools/llvm-ar/mri-delete.test b/llvm/test/tools/llvm-ar/mri-delete.test
index 55e68862a3b8..bb829ce13c72 100644
--- a/llvm/test/tools/llvm-ar/mri-delete.test
+++ b/llvm/test/tools/llvm-ar/mri-delete.test
@@ -1,4 +1,3 @@
-XFAIL: system-aix
 RUN: yaml2obj %S/Inputs/elf.yaml -o %t.o
 RUN: rm -f %t.ar
 

diff  --git a/llvm/test/tools/llvm-ar/mri-nonascii.test b/llvm/test/tools/llvm-ar/mri-nonascii.test
index 28b27eb38220..2a6888747564 100644
--- a/llvm/test/tools/llvm-ar/mri-nonascii.test
+++ b/llvm/test/tools/llvm-ar/mri-nonascii.test
@@ -1,4 +1,3 @@
-XFAIL: system-aix
 # Test non-ascii archive members
 
 RUN: rm -rf %t && mkdir -p %t/extracted

diff  --git a/llvm/test/tools/llvm-ar/non-windows-name-case.test b/llvm/test/tools/llvm-ar/non-windows-name-case.test
index fbc17e142dd6..37c53022603d 100644
--- a/llvm/test/tools/llvm-ar/non-windows-name-case.test
+++ b/llvm/test/tools/llvm-ar/non-windows-name-case.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## Test that on windows, members are case insensitive.
 # UNSUPPORTED: system-windows
 

diff  --git a/llvm/test/tools/llvm-ar/plugin.test b/llvm/test/tools/llvm-ar/plugin.test
index 24b7cf59afa5..0dda3d98dde2 100644
--- a/llvm/test/tools/llvm-ar/plugin.test
+++ b/llvm/test/tools/llvm-ar/plugin.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## Test that --plugin is ignored.
 
 # RUN: rm -f %t.a

diff  --git a/llvm/test/tools/llvm-ar/print.test b/llvm/test/tools/llvm-ar/print.test
index 1f7eb434bd63..a27cab4a227e 100644
--- a/llvm/test/tools/llvm-ar/print.test
+++ b/llvm/test/tools/llvm-ar/print.test
@@ -1,5 +1,5 @@
 ## Test Print output
-# XFAIL: system-darwin,system-aix
+# XFAIL: system-darwin
 
 # RUN: rm -rf %t && mkdir -p %t
 # RUN: echo file1 > %t/1.txt
@@ -9,7 +9,7 @@
 # RUN: llvm-ar -rc %t/archive.a %t/1.txt %t/2.txt %t/3.txt
 
 ## Print empty archive:
-# RUN: llvm-ar cr %t/empty.a
+# RUN: llvm-ar --format=gnu  cr %t/empty.a
 # RUN: llvm-ar p %t/empty.a 2>&1 | count 0
 # RUN: llvm-ar pv %t/empty.a 2>&1 | count 0
 

diff  --git a/llvm/test/tools/llvm-ar/read-only-archive.test b/llvm/test/tools/llvm-ar/read-only-archive.test
index b2599ec1819c..0365f6ad054d 100644
--- a/llvm/test/tools/llvm-ar/read-only-archive.test
+++ b/llvm/test/tools/llvm-ar/read-only-archive.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## Test that read-only archives cannot be edited
 
 # RUN: rm -rf %t && mkdir -p %t

diff  --git a/llvm/test/tools/llvm-ar/response-utf8.test b/llvm/test/tools/llvm-ar/response-utf8.test
index 1b7ac1c79f27..b3e405f85490 100644
--- a/llvm/test/tools/llvm-ar/response-utf8.test
+++ b/llvm/test/tools/llvm-ar/response-utf8.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## Check that response files can cope with non-ascii characters.
 
 # RUN: echo 'contents' > %t-£.txt

diff  --git a/llvm/test/tools/llvm-ar/response.test b/llvm/test/tools/llvm-ar/response.test
index 118ef9884d91..02d9e8eec092 100644
--- a/llvm/test/tools/llvm-ar/response.test
+++ b/llvm/test/tools/llvm-ar/response.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## llvm-ar should be able to consume response files.
 
 # RUN: echo 'contents' > %t.txt

diff  --git a/llvm/test/tools/llvm-libtool-darwin/archive-flattening.test b/llvm/test/tools/llvm-libtool-darwin/archive-flattening.test
index 2d009fcfd677..3b133cdffba1 100644
--- a/llvm/test/tools/llvm-libtool-darwin/archive-flattening.test
+++ b/llvm/test/tools/llvm-libtool-darwin/archive-flattening.test
@@ -1,4 +1,3 @@
-# XFAIL: system-aix
 ## This test checks that an archive is flattened correctly.
 
 # RUN: yaml2obj %S/Inputs/input1.yaml -o %t-input1.o

diff  --git a/llvm/test/tools/llvm-link/archive.ll b/llvm/test/tools/llvm-link/archive.ll
index eb78cc1ee6b7..acf9f346e5ca 100644
--- a/llvm/test/tools/llvm-link/archive.ll
+++ b/llvm/test/tools/llvm-link/archive.ll
@@ -1,7 +1,7 @@
 # RUN: llvm-as %S/Inputs/f.ll -o %t.f.bc
 # RUN: llvm-as %S/Inputs/g.ll -o %t.g.bc
-# RUN: llvm-ar cr --format=gnu %t.fg.a %t.f.bc %t.g.bc
-# RUN: llvm-ar cr --format=gnu  %t.empty.lib
+# RUN: llvm-ar cr %t.fg.a %t.f.bc %t.g.bc
+# RUN: llvm-ar cr --format=gnu %t.empty.lib
 # RUN: llvm-link %S/Inputs/h.ll %t.fg.a %t.empty.lib -o %t.linked.bc
 
 # RUN: llvm-nm %t.linked.bc | FileCheck %s

diff  --git a/llvm/test/tools/llvm-link/archivell.ll b/llvm/test/tools/llvm-link/archivell.ll
index 5614b0b56195..e8e40a2a572e 100644
--- a/llvm/test/tools/llvm-link/archivell.ll
+++ b/llvm/test/tools/llvm-link/archivell.ll
@@ -1,4 +1,5 @@
-# RUN: llvm-ar --format=gnu cr %t.fg.a %S/Inputs/f.ll %S/Inputs/g.ll
+# XFAIL: system-aix
+# RUN: llvm-ar cr %t.fg.a %S/Inputs/f.ll %S/Inputs/g.ll
 # RUN: not llvm-link %S/Inputs/h.ll %t.fg.a -o %t.linked.bc 2>&1 | FileCheck %s
 
 # RUN: rm -f %t.fg.a

diff  --git a/llvm/test/tools/llvm-lipo/create-archive-input.test b/llvm/test/tools/llvm-lipo/create-archive-input.test
index cc3812fed40b..a1c73217e2ee 100644
--- a/llvm/test/tools/llvm-lipo/create-archive-input.test
+++ b/llvm/test/tools/llvm-lipo/create-archive-input.test
@@ -4,16 +4,16 @@
 # RUN: llvm-as %p/Inputs/armv7-ios.ll -o %t-ir-armv7.o
 # RUN: llvm-as %p/Inputs/x64-osx.ll -o %t-ir-x86_64.o
 
-# RUN: llvm-ar --format=gnu cr %t.empty.a
+# RUN: llvm-ar cr --format=gnu %t.empty.a
 # RUN: not llvm-lipo %t.empty.a -create -output /dev/null 2>&1 | FileCheck --check-prefix=EMPTY-ARCHIVE %s
 
-# RUN: llvm-ar --format=gnu cr %t.
diff erent_architectures.a %t-i386.o %t-x86_64.o
+# RUN: llvm-ar cr %t.
diff erent_architectures.a %t-i386.o %t-x86_64.o
 # RUN: not llvm-lipo %t.
diff erent_architectures.a -create -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-DIFFERENT-ARCHS %s
 
-# RUN: llvm-ar --format=gnu cr %t.contains_fat_binary.a %t-universal.o 
+# RUN: llvm-ar cr %t.contains_fat_binary.a %t-universal.o 
 # RUN: not llvm-lipo %t.contains_fat_binary.a -create -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-FAT-BINARY %s
 
-# RUN: llvm-ar --format=gnu cr %t-i386-lib.a %t-i386.o
+# RUN: llvm-ar cr %t-i386-lib.a %t-i386.o
 # RUN: llvm-lipo %t-i386-lib.a %t-x86_64.o -create -output %t-i386-x86_64-universal.o
 # RUN: llvm-lipo %t-i386-x86_64-universal.o -info | FileCheck --check-prefix=INFO-i386-x86_64 %s
 # RUN: llvm-lipo %t-i386-x86_64-universal.o -thin i386 -output %t-extracted-i386-lib.a
@@ -21,18 +21,18 @@
 # RUN: llvm-lipo %t-i386-x86_64-universal.o -thin x86_64 -output %t-extracted-x86_64.o
 # RUN: cmp %t-extracted-x86_64.o %t-x86_64.o
 
-# RUN: llvm-ar --format=gnu cr %t-ir-armv7-lib.a %t-ir-armv7.o
+# RUN: llvm-ar cr %t-ir-armv7-lib.a %t-ir-armv7.o
 # RUN: llvm-lipo %t-ir-armv7-lib.a %t-ir-x86_64.o -create -output %t-ir-armv7-x86_64-universal.o
 # RUN: llvm-lipo %t-ir-armv7-x86_64-universal.o -thin armv7 -output %t-ir-extracted-armv7-lib.a
 # RUN: cmp %t-ir-extracted-armv7-lib.a %t-ir-armv7-lib.a
 # RUN: llvm-lipo %t-ir-armv7-x86_64-universal.o -thin x86_64 -output %t-ir-extracted-x86_64.o
 # RUN: cmp %t-ir-extracted-x86_64.o %t-ir-x86_64.o
 
-# RUN: llvm-ar --format=gnu cr %t.
diff erent_types0.a %t-i386.o %t-ir-x86_64.o
+# RUN: llvm-ar cr %t.
diff erent_types0.a %t-i386.o %t-ir-x86_64.o
 # RUN: not llvm-lipo -create %t.
diff erent_types0.a -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-MACHO-AND-IR %s
-# RUN: llvm-ar --format=gnu cr %t.
diff erent_types1.a %t-ir-x86_64.o %t-i386.o 
+# RUN: llvm-ar cr %t.
diff erent_types1.a %t-ir-x86_64.o %t-i386.o 
 # RUN: not llvm-lipo -create %t.
diff erent_types1.a -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-IR-AND-MACHO %s
-# RUN: llvm-ar --format=gnu cr %t.
diff erent_architectures_ir.a %t-ir-x86_64.o %t-ir-armv7.o
+# RUN: llvm-ar cr %t.
diff erent_architectures_ir.a %t-ir-x86_64.o %t-ir-armv7.o
 # RUN: not llvm-lipo -create %t.
diff erent_architectures_ir.a -output /dev/null 2>&1 | FileCheck --check-prefix=ARCHIVE-WITH-DIFFERENT-ARCHS %s
 
 # EMPTY-ARCHIVE: empty archive

diff  --git a/llvm/test/tools/llvm-nm/option-X.test b/llvm/test/tools/llvm-nm/option-X.test
index 169d77e204ae..caa21f9d7961 100644
--- a/llvm/test/tools/llvm-nm/option-X.test
+++ b/llvm/test/tools/llvm-nm/option-X.test
@@ -56,7 +56,7 @@ Symbols:
 # RUN: yaml2obj --docnum=2 -DFLAG=0x1DF %s -o %t_xcoff32.o
 # RUN: yaml2obj --docnum=2 -DFLAG=0x1F7 %s -o %t_xcoff64.o
 # RUN: rm -f %t.a
-# RUN: llvm-ar --format=gnu -q -c %t.a %t_xcoff32.o %t_xcoff64.o
+# RUN: llvm-ar -q -c %t.a %t_xcoff32.o %t_xcoff64.o
 
 # RUN: llvm-nm --format=just-symbols -X32 %t_xcoff32.o | \
 # RUN:   FileCheck --check-prefixes=XCOFF32 %s --implicit-check-not={{.}}

diff  --git a/llvm/test/tools/llvm-objcopy/MachO/universal-object.test b/llvm/test/tools/llvm-objcopy/MachO/universal-object.test
index d9cdf785bc5d..a6146fd56483 100644
--- a/llvm/test/tools/llvm-objcopy/MachO/universal-object.test
+++ b/llvm/test/tools/llvm-objcopy/MachO/universal-object.test
@@ -14,7 +14,7 @@
 
 ## Case 2: copy a universal object file containing an archive.
 # RUN: rm -f %t.archive.i386
-# RUN: llvm-ar --format=gnu cr %t.archive.i386 %t.i386
+# RUN: llvm-ar cr %t.archive.i386 %t.i386
 # RUN: llvm-lipo %t.archive.i386 %t.x86_64 -create -output %t.universal.containing.archive
 # RUN: llvm-objcopy %t.universal.containing.archive %t.universal.containing.archive.copy
 # RUN: llvm-lipo %t.universal.containing.archive.copy -archs | FileCheck --check-prefix=VERIFY_ARCHS %s
@@ -24,7 +24,7 @@
 # RUN: cmp %t.x86_64 %t.archive.x86_64.copy
 
 ## Case 3: copy an archive containing a universal object.
-# RUN: llvm-ar --format=gnu cr %t.archive.containing.universal %t.universal
+# RUN: llvm-ar cr %t.archive.containing.universal %t.universal
 # RUN: llvm-objcopy %t.archive.containing.universal %t.archive.containing.universal.copy
 
 ## Case 4: try to copy a universal object file contaning a bitcode slice.
@@ -34,7 +34,7 @@
 # RUN:  | FileCheck --check-prefix=UNSUPPORTED_UNIVERSAL_OBJECT %s
 
 ## Case 5: try to copy an archive containing an unsupported universal object.
-# RUN: llvm-ar --format=gnu cr %t.archive.universal.bitcode %t.universal.containing.bitcode
+# RUN: llvm-ar cr %t.archive.universal.bitcode %t.universal.containing.bitcode
 # RUN: not llvm-objcopy %t.archive.universal.bitcode %t.archive.universal.bitcode.copy 2>&1 \
 # RUN:  | FileCheck --check-prefix=UNSUPPORTED_UNIVERSAL_OBJECT %s
 

diff  --git a/llvm/test/tools/llvm-readobj/basic.test b/llvm/test/tools/llvm-readobj/basic.test
index 0db336f2596c..73912373d7d2 100644
--- a/llvm/test/tools/llvm-readobj/basic.test
+++ b/llvm/test/tools/llvm-readobj/basic.test
@@ -16,7 +16,7 @@ EMPTY: '{{.*}}.empty': The file was not recognized as a valid object file
 
 # Test that unrecognised files in archives are ignored.
 RUN: rm -f %t.a
-RUN: llvm-ar --format=gnu rc %t.a %t.empty
+RUN: llvm-ar rc %t.a %t.empty
 RUN: llvm-readobj --all %t.a 2>&1 | FileCheck --check-prefix=NO-OUTPUT --allow-empty %s
 NO-OUTPUT-NOT: {{.}}
 

diff  --git a/llvm/test/tools/llvm-size/archive.test b/llvm/test/tools/llvm-size/archive.test
index 621c53ba33db..b404e0eabcdc 100644
--- a/llvm/test/tools/llvm-size/archive.test
+++ b/llvm/test/tools/llvm-size/archive.test
@@ -5,21 +5,21 @@
 
 ## Case 1: Empty archive. No output expected.
 # RUN: rm -f %t1.a
-# RUN: llvm-ar --format=gnu rc %t1.a
+# RUN: llvm-ar rc --format=gnu %t1.a
 
 # RUN: llvm-size -B %t1.a | count 0
 # RUN: llvm-size -A %t1.a | count 0
 
 ## Case 2: Single member.
 # RUN: rm -f %t2.a
-# RUN: llvm-ar --format=gnu rc %t2.a %t1
+# RUN: llvm-ar rc %t2.a %t1
 
 # RUN: llvm-size -B %t2.a | FileCheck %s -DARCHIVE=%t2.a --check-prefix=BERKELEY-1
 # RUN: llvm-size -A %t2.a | FileCheck %s -DARCHIVE=%t2.a --check-prefix=SYSV-1
 
 ## Case 3: Multiple members.
 # RUN: rm -f %t3.a
-# RUN: llvm-ar --format=gnu rc %t3.a %t1 %t2
+# RUN: llvm-ar rc %t3.a %t1 %t2
 
 # RUN: llvm-size -B %t3.a | FileCheck %s -DARCHIVE=%t3.a --check-prefixes=BERKELEY-1,BERKELEY-2
 # RUN: llvm-size -A %t3.a | FileCheck %s -DARCHIVE=%t3.a --check-prefixes=SYSV-1,SYSV-2

diff  --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp
index 81ac003e7314..3f6be7100bce 100644
--- a/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -82,6 +82,7 @@ static void printArHelp(StringRef ToolName) {
     =gnu                -   gnu
     =darwin             -   darwin
     =bsd                -   bsd
+    =aix                -   aix (big archive)
   --plugin=<string>     - ignored for compatibility
   -h --help             - display this help and exit
   --rsp-quoting         - quoting style for response files
@@ -187,7 +188,7 @@ static SmallVector<const char *, 256> PositionalArgs;
 static bool MRI;
 
 namespace {
-enum Format { Default, GNU, BSD, DARWIN, Unknown };
+enum Format { Default, GNU, BSD, DARWIN, BIGARCHIVE, Unknown };
 }
 
 static Format FormatType = Default;
@@ -950,8 +951,6 @@ static void performWriteOperation(ArchiveOperation Operation,
     else
       Kind = !NewMembers.empty() ? getKindFromMember(NewMembers.front())
                                  : getDefaultForHost();
-    if (Kind == object::Archive::K_AIXBIG)
-      fail("big archive writer operation on AIX not yet supported");
     break;
   case GNU:
     Kind = object::Archive::K_GNU;
@@ -966,6 +965,11 @@ static void performWriteOperation(ArchiveOperation Operation,
       fail("only the gnu format has a thin mode");
     Kind = object::Archive::K_DARWIN;
     break;
+  case BIGARCHIVE:
+    if (Thin)
+      fail("only the gnu format has a thin mode");
+    Kind = object::Archive::K_AIXBIG;
+    break;
   case Unknown:
     llvm_unreachable("");
   }
@@ -1237,6 +1241,7 @@ static int ar_main(int argc, char **argv) {
                        .Case("gnu", GNU)
                        .Case("darwin", DARWIN)
                        .Case("bsd", BSD)
+                       .Case("bigarchive", BIGARCHIVE)
                        .Default(Unknown);
       if (FormatType == Unknown)
         fail(std::string("Invalid format ") + Match);


        


More information about the llvm-commits mailing list