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