xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Object/MachOUniversalWriter.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/ADT/ArrayRef.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/BinaryFormat/MachO.h"
21 #include "llvm/Support/Compiler.h"
22 #include "llvm/Support/Error.h"
23 #include <cstdint>
24 #include <string>
25 
26 namespace llvm {
27 class LLVMContext;
28 
29 namespace object {
30 class Archive;
31 class Binary;
32 class IRObjectFile;
33 class MachOObjectFile;
34 
35 class Slice {
36   const Binary *B;
37   uint32_t CPUType;
38   uint32_t CPUSubType;
39   std::string ArchName;
40 
41   // P2Alignment field stores slice alignment values from universal
42   // binaries. This is also needed to order the slices so the total
43   // file size can be calculated before creating the output buffer.
44   uint32_t P2Alignment;
45 
46   Slice(const IRObjectFile &IRO, uint32_t CPUType, uint32_t CPUSubType,
47         std::string ArchName, uint32_t Align);
48 
49 public:
50   LLVM_ABI explicit Slice(const MachOObjectFile &O);
51 
52   LLVM_ABI Slice(const MachOObjectFile &O, uint32_t Align);
53 
54   /// This constructor takes pre-specified \param CPUType , \param CPUSubType ,
55   /// \param ArchName , \param Align instead of inferring them from the archive
56   /// members.
57   LLVM_ABI Slice(const Archive &A, uint32_t CPUType, uint32_t CPUSubType,
58                  std::string ArchName, uint32_t Align);
59 
60   LLVM_ABI static Expected<Slice> create(const Archive &A,
61                                          LLVMContext *LLVMCtx = nullptr);
62 
63   LLVM_ABI static Expected<Slice> create(const IRObjectFile &IRO,
64                                          uint32_t Align);
65 
setP2Alignment(uint32_t Align)66   void setP2Alignment(uint32_t Align) { P2Alignment = Align; }
67 
getBinary()68   const Binary *getBinary() const { return B; }
69 
getCPUType()70   uint32_t getCPUType() const { return CPUType; }
71 
getCPUSubType()72   uint32_t getCPUSubType() const { return CPUSubType; }
73 
getP2Alignment()74   uint32_t getP2Alignment() const { return P2Alignment; }
75 
getCPUID()76   uint64_t getCPUID() const {
77     return static_cast<uint64_t>(CPUType) << 32 | CPUSubType;
78   }
79 
getArchString()80   std::string getArchString() const {
81     if (!ArchName.empty())
82       return ArchName;
83     return ("unknown(" + Twine(CPUType) + "," +
84             Twine(CPUSubType & ~MachO::CPU_SUBTYPE_MASK) + ")")
85         .str();
86   }
87 
88   friend bool operator<(const Slice &Lhs, const Slice &Rhs) {
89     if (Lhs.CPUType == Rhs.CPUType)
90       return Lhs.CPUSubType < Rhs.CPUSubType;
91     // force arm64-family to follow after all other slices for
92     // compatibility with cctools lipo
93     if (Lhs.CPUType == MachO::CPU_TYPE_ARM64)
94       return false;
95     if (Rhs.CPUType == MachO::CPU_TYPE_ARM64)
96       return true;
97     // Sort by alignment to minimize file size
98     return Lhs.P2Alignment < Rhs.P2Alignment;
99   }
100 };
101 
102 enum class FatHeaderType { FatHeader, Fat64Header };
103 
104 LLVM_ABI Error
105 writeUniversalBinary(ArrayRef<Slice> Slices, StringRef OutputFileName,
106                      FatHeaderType FatHeader = FatHeaderType::FatHeader);
107 
108 LLVM_ABI Error writeUniversalBinaryToStream(
109     ArrayRef<Slice> Slices, raw_ostream &Out,
110     FatHeaderType FatHeader = FatHeaderType::FatHeader);
111 
112 } // end namespace object
113 
114 } // end namespace llvm
115 
116 #endif // LLVM_OBJECT_MACHOUNIVERSALWRITER_H
117