1 //===- MachOUniversalWriter.h - MachO universal binary writer----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Declares the Slice class and writeUniversalBinary function for writing a
10 // MachO universal binary file.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_OBJECT_MACHOUNIVERSALWRITER_H
15 #define LLVM_OBJECT_MACHOUNIVERSALWRITER_H
16 
17 #include "llvm/Object/Archive.h"
18 #include "llvm/Object/Binary.h"
19 #include "llvm/Object/MachO.h"
20 
21 namespace llvm {
22 class LLVMContext;
23 
24 namespace object {
25 class IRObjectFile;
26 
27 class Slice {
28   const Binary *B;
29   uint32_t CPUType;
30   uint32_t CPUSubType;
31   std::string ArchName;
32 
33   // P2Alignment field stores slice alignment values from universal
34   // binaries. This is also needed to order the slices so the total
35   // file size can be calculated before creating the output buffer.
36   uint32_t P2Alignment;
37 
38   Slice(const IRObjectFile &IRO, uint32_t CPUType, uint32_t CPUSubType,
39         std::string ArchName, uint32_t Align);
40 
41 public:
42   explicit Slice(const MachOObjectFile &O);
43 
44   Slice(const MachOObjectFile &O, uint32_t Align);
45 
46   /// This constructor takes pre-specified \param CPUType , \param CPUSubType ,
47   /// \param ArchName , \param Align instead of inferring them from the archive
48   /// members.
49   Slice(const Archive &A, uint32_t CPUType, uint32_t CPUSubType,
50         std::string ArchName, uint32_t Align);
51 
52   static Expected<Slice> create(const Archive &A,
53                                 LLVMContext *LLVMCtx = nullptr);
54 
55   static Expected<Slice> create(const IRObjectFile &IRO, uint32_t Align);
56 
setP2Alignment(uint32_t Align)57   void setP2Alignment(uint32_t Align) { P2Alignment = Align; }
58 
getBinary()59   const Binary *getBinary() const { return B; }
60 
getCPUType()61   uint32_t getCPUType() const { return CPUType; }
62 
getCPUSubType()63   uint32_t getCPUSubType() const { return CPUSubType; }
64 
getP2Alignment()65   uint32_t getP2Alignment() const { return P2Alignment; }
66 
getCPUID()67   uint64_t getCPUID() const {
68     return static_cast<uint64_t>(CPUType) << 32 | CPUSubType;
69   }
70 
getArchString()71   std::string getArchString() const {
72     if (!ArchName.empty())
73       return ArchName;
74     return ("unknown(" + Twine(CPUType) + "," +
75             Twine(CPUSubType & ~MachO::CPU_SUBTYPE_MASK) + ")")
76         .str();
77   }
78 
79   friend bool operator<(const Slice &Lhs, const Slice &Rhs) {
80     if (Lhs.CPUType == Rhs.CPUType)
81       return Lhs.CPUSubType < Rhs.CPUSubType;
82     // force arm64-family to follow after all other slices for
83     // compatibility with cctools lipo
84     if (Lhs.CPUType == MachO::CPU_TYPE_ARM64)
85       return false;
86     if (Rhs.CPUType == MachO::CPU_TYPE_ARM64)
87       return true;
88     // Sort by alignment to minimize file size
89     return Lhs.P2Alignment < Rhs.P2Alignment;
90   }
91 };
92 
93 Error writeUniversalBinary(ArrayRef<Slice> Slices, StringRef OutputFileName);
94 
95 Error writeUniversalBinaryToStream(ArrayRef<Slice> Slices, raw_ostream &Out);
96 
97 } // end namespace object
98 
99 } // end namespace llvm
100 
101 #endif // LLVM_OBJECT_MACHOUNIVERSALWRITER_H
102