[llvm] r373132 - [llvm-lipo] Add support for -arch

Alexander Shaposhnikov via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 27 15:33:18 PDT 2019


Author: alexshap
Date: Fri Sep 27 15:33:18 2019
New Revision: 373132

URL: http://llvm.org/viewvc/llvm-project?rev=373132&view=rev
Log:
[llvm-lipo] Add support for -arch 

Add support for -arch.

Differential revision: https://reviews.llvm.org/D68116

Test plan: make check-all

Added:
    llvm/trunk/test/tools/llvm-lipo/create-arch.test
Modified:
    llvm/trunk/test/tools/llvm-lipo/replace-invalid-input.test
    llvm/trunk/tools/llvm-lipo/LipoOpts.td
    llvm/trunk/tools/llvm-lipo/llvm-lipo.cpp

Added: llvm/trunk/test/tools/llvm-lipo/create-arch.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-lipo/create-arch.test?rev=373132&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-lipo/create-arch.test (added)
+++ llvm/trunk/test/tools/llvm-lipo/create-arch.test Fri Sep 27 15:33:18 2019
@@ -0,0 +1,17 @@
+# RUN: yaml2obj %p/Inputs/i386-slice.yaml > %t-i386.o
+# RUN: yaml2obj %p/Inputs/x86_64-slice.yaml > %t-x86_64.o
+
+# RUN: llvm-lipo %t-i386.o %t-x86_64.o -create -output %t-universal.o
+# RUN: llvm-lipo %t-i386.o -arch x86_64 %t-x86_64.o -create -output %t-universal-1.o
+# RUN: cmp %t-universal.o %t-universal-1.o
+# RUN: llvm-lipo -arch i386 %t-i386.o -arch x86_64 %t-x86_64.o -create -output %t-universal-2.o
+# RUN: cmp %t-universal.o %t-universal-2.o
+#
+# RUN: not llvm-lipo -arch armv7 %t-i386.o -arch x86_64 %t-x86_64.o -create -output /dev/null 2>&1 | FileCheck --check-prefix=ARCH_NOT_MATCHED %s
+# ARCH_NOT_MATCHED: error: specified architecture: armv7 for file: {{.*}} does not match the file's architecture (i386)
+#
+# # RUN: not llvm-lipo -arch i3866 %t-32.o -create -o /dev/null 2>&1 | FileCheck --check-prefix=INVALID_ARCH %s
+# INVALID_ARCH: error: Invalid architecture: i3866
+#
+# RUN: not llvm-lipo -arch i386 %t-33.o -create -o /dev/null 2>&1 | FileCheck --check-prefix=INVALID_FILE %s
+# INVALID_FILE: {{[nN]}}o such file or directory

Modified: llvm/trunk/test/tools/llvm-lipo/replace-invalid-input.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-lipo/replace-invalid-input.test?rev=373132&r1=373131&r2=373132&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-lipo/replace-invalid-input.test (original)
+++ llvm/trunk/test/tools/llvm-lipo/replace-invalid-input.test Fri Sep 27 15:33:18 2019
@@ -5,20 +5,20 @@
 # RUN: not llvm-lipo %t-universal.o -replace %t-32.o 2>&1 | FileCheck --check-prefix=MISSING_ARG %s
 # MISSING_ARG: error: replace is missing an argument: expects -replace arch_type file_name
 
-# RUN: not llvm-lipo %t-universal.o -replace %t-32.o i386 2>&1 | FileCheck --check-prefix=OUTPUT_FILE %s
+# RUN: not llvm-lipo %t-universal.o -replace i386 %t-32.o 2>&1 | FileCheck --check-prefix=OUTPUT_FILE %s
 # OUTPUT_FILE: error: replace expects a single output file to be specified
 
-# RUN: not llvm-lipo %t-universal.o %t-universal.o -replace %t-32.o i386 -o %t.o 2>&1 | FileCheck --check-prefix=INPUT_ARGS %s
+# RUN: not llvm-lipo %t-universal.o %t-universal.o -replace i386 %t-32.o -o %t.o 2>&1 | FileCheck --check-prefix=INPUT_ARGS %s
 # INPUT_ARGS: error: replace expects a single input file
 
-# RUN: not llvm-lipo %t-universal.o -replace %t-32.o i386 -o %t.o 2>&1 | FileCheck --check-prefix=INVALID_FILE %s
-# INVALID_FILE: error: 'i386': {{[nN]}}o such file or directory
+# RUN: not llvm-lipo %t-universal.o -replace i386 %t-33.o  -o %t.o 2>&1 | FileCheck --check-prefix=INVALID_FILE %s
+# INVALID_FILE: {{[nN]}}o such file or directory
 
 # RUN: not llvm-lipo %t-universal.o -replace i3866 %t-32.o -o %t.o 2>&1 | FileCheck --check-prefix=INVALID_ARCH %s
 # INVALID_ARCH: error: Invalid architecture: i3866
 
 # RUN: not llvm-lipo %t-universal.o -replace arm64 %t-32.o -o %t.o 2>&1 | FileCheck --check-prefix=ARCH_NOT_MATCHED %s
-# ARCH_NOT_MATCHED: error: specified architecture: arm64 for replacement file: {{.*}} does not match the file's architecture
+# ARCH_NOT_MATCHED: error: specified architecture: arm64 for file: {{.*}} does not match the file's architecture (i386)
 
 # RUN: not llvm-lipo %t-universal.o -replace arm64 %t-arm64.o -o %t.o 2>&1 | FileCheck --check-prefix=ARCH_NOT_IN_INPUT %s
 # ARCH_NOT_IN_INPUT: error: -replace arm64 <file_name> specified but fat file: {{.*}} does not contain that architecture

Modified: llvm/trunk/tools/llvm-lipo/LipoOpts.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-lipo/LipoOpts.td?rev=373132&r1=373131&r2=373132&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-lipo/LipoOpts.td (original)
+++ llvm/trunk/tools/llvm-lipo/LipoOpts.td Fri Sep 27 15:33:18 2019
@@ -12,6 +12,10 @@ def segalign
                "architecture when creating a universal binary file. The "
                "alignment is a hexadecimal number that is a power of 2.">;
 
+def arch
+    : MultiArg<["-", "--"], "arch", 2>,
+      HelpText<"Specifies the architecture and the corresponding input file">;
+
 def action_group : OptionGroup<"action group">;
 
 def verify_arch

Modified: llvm/trunk/tools/llvm-lipo/llvm-lipo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-lipo/llvm-lipo.cpp?rev=373132&r1=373131&r2=373132&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-lipo/llvm-lipo.cpp (original)
+++ llvm/trunk/tools/llvm-lipo/llvm-lipo.cpp Fri Sep 27 15:33:18 2019
@@ -86,15 +86,15 @@ enum class LipoAction {
   ReplaceArch,
 };
 
-struct Replacement {
-  StringRef ArchType;
+struct InputFile {
+  Optional<StringRef> ArchType;
   StringRef FileName;
 };
 
 struct Config {
-  SmallVector<std::string, 1> InputFiles;
+  SmallVector<InputFile, 1> InputFiles;
   SmallVector<std::string, 1> VerifyArchList;
-  SmallVector<Replacement, 1> Replacements;
+  SmallVector<InputFile, 1> ReplacementFiles;
   StringMap<const uint32_t> SegmentAlignments;
   std::string ThinArchType;
   std::string OutputFile;
@@ -301,7 +301,15 @@ static Config parseLipoOptions(ArrayRef<
     reportError("unknown argument '" + Arg->getAsString(InputArgs) + "'");
 
   for (auto Arg : InputArgs.filtered(LIPO_INPUT))
-    C.InputFiles.push_back(Arg->getValue());
+    C.InputFiles.push_back({None, Arg->getValue()});
+  for (auto Arg : InputArgs.filtered(LIPO_arch)) {
+    validateArchitectureName(Arg->getValue(0));
+    if (!Arg->getValue(1))
+      reportError(
+          "arch is missing an argument: expects -arch arch_type file_name");
+    C.InputFiles.push_back({StringRef(Arg->getValue(0)), Arg->getValue(1)});
+  }
+
   if (C.InputFiles.empty())
     reportError("at least one input file should be specified");
 
@@ -402,8 +410,9 @@ static Config parseLipoOptions(ArrayRef<
         reportError(
             "replace is missing an argument: expects -replace arch_type "
             "file_name");
-      C.Replacements.push_back(
-          Replacement{Action->getValue(0), Action->getValue(1)});
+      validateArchitectureName(Action->getValue(0));
+      C.ReplacementFiles.push_back(
+          {StringRef(Action->getValue(0)), Action->getValue(1)});
     }
 
     if (C.OutputFile.empty())
@@ -419,16 +428,25 @@ static Config parseLipoOptions(ArrayRef<
 }
 
 static SmallVector<OwningBinary<Binary>, 1>
-readInputBinaries(ArrayRef<std::string> InputFiles) {
+readInputBinaries(ArrayRef<InputFile> InputFiles) {
   SmallVector<OwningBinary<Binary>, 1> InputBinaries;
-  for (StringRef InputFile : InputFiles) {
-    Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(InputFile);
+  for (const InputFile &IF : InputFiles) {
+    Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(IF.FileName);
     if (!BinaryOrErr)
-      reportError(InputFile, BinaryOrErr.takeError());
-    if (!BinaryOrErr->getBinary()->isArchive() &&
-        !BinaryOrErr->getBinary()->isMachO() &&
-        !BinaryOrErr->getBinary()->isMachOUniversalBinary())
-      reportError("File " + InputFile + " has unsupported binary format");
+      reportError(IF.FileName, BinaryOrErr.takeError());
+    const Binary *B = BinaryOrErr->getBinary();
+    if (!B->isArchive() && !B->isMachO() && !B->isMachOUniversalBinary())
+      reportError("File " + IF.FileName + " has unsupported binary format");
+    if (IF.ArchType && (B->isMachO() || B->isArchive())) {
+      const auto ArchType =
+          B->isMachO() ? Slice(cast<MachOObjectFile>(B)).getArchString()
+                       : Slice(cast<Archive>(B)).getArchString();
+      if (Triple(*IF.ArchType).getArch() != Triple(ArchType).getArch())
+        reportError("specified architecture: " + *IF.ArchType +
+                    " for file: " + B->getFileName() +
+                    " does not match the file's architecture (" + ArchType +
+                    ")");
+    }
     InputBinaries.push_back(std::move(*BinaryOrErr));
   }
   return InputBinaries;
@@ -716,32 +734,20 @@ static void createUniversalBinary(ArrayR
 
 static StringMap<Slice>
 buildReplacementSlices(ArrayRef<OwningBinary<Binary>> ReplacementBinaries,
-                       const StringMap<const uint32_t> &Alignments,
-                       ArrayRef<Replacement> Replacements) {
-  assert(ReplacementBinaries.size() == Replacements.size() &&
-         "Number of replacment binaries does not match the number of "
-         "replacements");
+                       const StringMap<const uint32_t> &Alignments) {
   StringMap<Slice> Slices;
   // populates StringMap of slices to replace with; error checks for mismatched
   // replace flag args, fat files, and duplicate arch_types
-  for (size_t Index = 0, Size = Replacements.size(); Index < Size; ++Index) {
-    StringRef ReplacementArch = Replacements[Index].ArchType;
-    const Binary *ReplacementBinary = ReplacementBinaries[Index].getBinary();
-    validateArchitectureName(ReplacementArch);
-
+  for (const auto &OB : ReplacementBinaries) {
+    const Binary *ReplacementBinary = OB.getBinary();
     auto O = dyn_cast<MachOObjectFile>(ReplacementBinary);
     if (!O)
       reportError("replacement file: " + ReplacementBinary->getFileName() +
                   " is a fat file (must be a thin file)");
-
-    if (O->getArch() != Triple(ReplacementArch).getArch())
-      reportError("specified architecture: " + ReplacementArch +
-                  " for replacement file: " + ReplacementBinary->getFileName() +
-                  " does not match the file's architecture");
-
-    auto Entry = Slices.try_emplace(ReplacementArch, Slice(O));
+    Slice S(O);
+    auto Entry = Slices.try_emplace(S.getArchString(), S);
     if (!Entry.second)
-      reportError("-replace " + ReplacementArch +
+      reportError("-replace " + S.getArchString() +
                   " <file_name> specified multiple times: " +
                   Entry.first->second.getBinary()->getFileName() + ", " +
                   O->getFileName());
@@ -756,7 +762,7 @@ LLVM_ATTRIBUTE_NORETURN
 static void replaceSlices(ArrayRef<OwningBinary<Binary>> InputBinaries,
                           const StringMap<const uint32_t> &Alignments,
                           StringRef OutputFileName,
-                          ArrayRef<Replacement> Replacements) {
+                          ArrayRef<InputFile> ReplacementFiles) {
   assert(InputBinaries.size() == 1 && "Incorrect number of input binaries");
   assert(!OutputFileName.empty() && "Replace expects a single output file");
 
@@ -765,14 +771,11 @@ static void replaceSlices(ArrayRef<Ownin
                 InputBinaries.front().getBinary()->getFileName() +
                 " must be a fat file when the -replace option is specified");
 
-  SmallVector<std::string, 1> ReplacementFiles;
-  for (const auto &R : Replacements)
-    ReplacementFiles.push_back(R.FileName);
   SmallVector<OwningBinary<Binary>, 1> ReplacementBinaries =
       readInputBinaries(ReplacementFiles);
 
   StringMap<Slice> ReplacementSlices =
-      buildReplacementSlices(ReplacementBinaries, Alignments, Replacements);
+      buildReplacementSlices(ReplacementBinaries, Alignments);
   SmallVector<std::unique_ptr<MachOObjectFile>, 2> ExtractedObjects;
   SmallVector<Slice, 2> Slices =
       buildSlices(InputBinaries, Alignments, ExtractedObjects);
@@ -820,7 +823,7 @@ int main(int argc, char **argv) {
     break;
   case LipoAction::ReplaceArch:
     replaceSlices(InputBinaries, C.SegmentAlignments, C.OutputFile,
-                  C.Replacements);
+                  C.ReplacementFiles);
     break;
   }
   return EXIT_SUCCESS;




More information about the llvm-commits mailing list