[llvm-libtool-darwin] Support universal outputs
Add support for producing universal binaries containing archives when
`llvm-libtool-darwin` is given inputs of multiple architectures.
Reviewed by jhenderson, smeenai
Differential Revision: https://reviews.llvm.org/D85334
diff --git a/llvm/test/tools/llvm-libtool-darwin/universal-output.test b/llvm/test/tools/llvm-libtool-darwin/universal-output.test
new file mode 100644
index 0000000..515c3e4
--- /dev/null
+++ b/llvm/test/tools/llvm-libtool-darwin/universal-output.test
@@ -0,0 +1,116 @@
+## This test checks that a correct universal binary is produced when
+## llvm-libtool-darwin is given inputs for multiple architectures.
+
+## Check that the subtypes of cputype CPU_TYPE_ARM are stored in a fat file:
+# RUN: yaml2obj %s -o %t.armv6 -DTYPE=0xC -DSUBTYPE=0x6 -DSTRING=_armv6
+# RUN: yaml2obj %s -o %t.armv7 -DTYPE=0xC -DSUBTYPE=0x9 -DSTRING=_armv7
+
+# RUN: llvm-libtool-darwin -static -o %t.lib %t.armv6 %t.armv7
+
+## Check that architectures are present in the universal output:
+# RUN: llvm-lipo -info %t.lib | \
+# RUN: FileCheck %s --check-prefix=ARCHS -DFILE=%t.lib
+
+# ARCHS: Architectures in the fat file: [[FILE]] are: armv6 armv7
+
+## Check that the files with the same architecture are combined in an archive:
+# RUN: llvm-libtool-darwin -static -o %t.lib %t.armv6 %t.armv6 %t.armv7
+# RUN: llvm-lipo -info %t.lib | \
+# RUN: FileCheck %s --check-prefix=ARCHS -DFILE=%t.lib
+# RUN: llvm-objdump --all-headers %t.lib | \
+# RUN: FileCheck %s --check-prefix=UNIVERSAL-MEMBERS -DFILE=%t.lib -DPREFIX=%basename_t.tmp --implicit-check-not=Archive
+
+# UNIVERSAL-MEMBERS: Archive : [[FILE]] (architecture armv6)
+# UNIVERSAL-MEMBERS-NEXT: __.SYMDEF
+# UNIVERSAL-MEMBERS-NEXT: [[PREFIX]].armv6
+# UNIVERSAL-MEMBERS-NEXT: [[PREFIX]].armv6
+# UNIVERSAL-MEMBERS: Archive : [[FILE]] (architecture armv7)
+# UNIVERSAL-MEMBERS-NEXT: __.SYMDEF
+# UNIVERSAL-MEMBERS-NEXT: [[PREFIX]].armv7
+
+## Check that the files extracted from a universal output are archives:
+# RUN: llvm-libtool-darwin -static -o %t.lib %t.armv6 %t.armv7
+# RUN: llvm-lipo %t.lib -thin armv7 -output %t-extracted-v7.a
+# RUN: llvm-ar t %t-extracted-v7.a | \
+# RUN: FileCheck %s --check-prefix=EXTRACT --implicit-check-not={{.}} -DPREFIX=%basename_t.tmp
+# RUN: llvm-nm --print-armap %t-extracted-v7.a | \
+# RUN: FileCheck %s --check-prefix=EXTRACT-SYMBOLS -DPREFIX=%basename_t.tmp --match-full-lines
+
+# EXTRACT: [[PREFIX]].armv7
+
+# EXTRACT-SYMBOLS: Archive map
+# EXTRACT-SYMBOLS-NEXT: _armv7 in [[PREFIX]].armv7
+# EXTRACT-SYMBOLS-EMPTY:
+
+## Check that the subtypes of cputype CPU_TYPE_X86_64 are stored in a fat file:
+# RUN: yaml2obj %s -o %t.x86_64 -DTYPE=0x01000007 -DSUBTYPE=0x3 -DSTRING=_x86_64
+# RUN: yaml2obj %s -o %t.x86_64_h -DTYPE=0x01000007 -DSUBTYPE=0x8 -DSTRING=_x86_64_h
+# RUN: llvm-libtool-darwin -static -o %t.lib %t.x86_64 %t.x86_64_h
+# RUN: llvm-lipo -info %t.lib | \
+# RUN: FileCheck %s --check-prefix=ARCHS-X86 -DFILE=%t.lib
+
+# ARCHS-X86: Architectures in the fat file: [[FILE]] are: x86_64 x86_64h
+
+## Check that the subtypes of cputype CPU_TYPE_ARM64 are stored in a fat file:
+## Testing it using llvm-objdump as, currently, there is no support for arm64e
+## under llvm/lib/Object/MachOObjectFile.cpp.
+# RUN: yaml2obj %s -o %t.arm64 -DTYPE=0x0100000C -DSUBTYPE=0x0 -DSTRING=_arm64all
+# RUN: yaml2obj %s -o %t.arm64e -DTYPE=0x0100000C -DSUBTYPE=0x2 -DSTRING=_arm64e
+# RUN: llvm-libtool-darwin -static -o %t.lib %t.arm64 %t.arm64e
+# RUN: llvm-objdump --all-headers %t.lib | \
+# RUN: FileCheck %s --check-prefix=UNIVERSAL-MEMBERS-ARM64 -DFILE=%t.lib -DPREFIX=%basename_t.tmp --implicit-check-not=Archive
+
+# UNIVERSAL-MEMBERS-ARM64: Archive : [[FILE]] (architecture arm64)
+# UNIVERSAL-MEMBERS-ARM64-NEXT: __.SYMDEF
+# UNIVERSAL-MEMBERS-ARM64-NEXT: [[PREFIX]].arm64
+# UNIVERSAL-MEMBERS-ARM64: Archive : [[FILE]]
+# UNIVERSAL-MEMBERS-ARM64-NEXT: __.SYMDEF
+# UNIVERSAL-MEMBERS-ARM64-NEXT: [[PREFIX]].arm64e
+
+## Check that different cputypes are stored together in a fat file:
+# RUN: yaml2obj %s -o %t.ppc -DTYPE=0x12 -DSUBTYPE=0x0 -DSTRING=_ppcall
+# RUN: llvm-libtool-darwin -static -o %t.lib %t.armv6 %t.ppc
+# RUN: llvm-lipo -info %t.lib | \
+# RUN: FileCheck %s --check-prefix=ARCHS-CPU -DFILE=%t.lib
+
+# ARCHS-CPU: Architectures in the fat file: [[FILE]] are: ppc armv6
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACE
+ cputype: [[TYPE]]
+ cpusubtype: [[SUBTYPE]]
+ filetype: 0x00000001
+ ncmds: 2
+ sizeofcmds: 148
+ flags: 0x00002000
+LoadCommands:
+ - cmd: LC_SEGMENT
+ cmdsize: 124
+ segname: ''
+ vmaddr: 0
+ vmsize: 10
+ fileoff: 280
+ filesize: 10
+ maxprot: 7
+ initprot: 7
+ nsects: 1
+ flags: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 292
+ nsyms: 1
+ stroff: 304
+ strsize: 8
+LinkEditData:
+ NameList:
+ - n_strx: 1
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 8
+ n_value: 0
+ StringTable:
+ - ''
+ - [[STRING]]
+ - ''
+...