1 //===- lib/ReaderWriter/MachO/ObjCPass.cpp -------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 //===----------------------------------------------------------------------===// 11 12 #include "ArchHandler.h" 13 #include "File.h" 14 #include "MachOPasses.h" 15 #include "lld/Core/DefinedAtom.h" 16 #include "lld/Core/File.h" 17 #include "lld/Core/LLVM.h" 18 #include "lld/Core/Reference.h" 19 #include "lld/Core/Simple.h" 20 #include "lld/ReaderWriter/MachOLinkingContext.h" 21 #include "llvm/ADT/DenseMap.h" 22 #include "llvm/ADT/STLExtras.h" 23 24 namespace lld { 25 namespace mach_o { 26 27 /// 28 /// ObjC Image Info Atom created by the ObjC pass. 29 /// 30 class ObjCImageInfoAtom : public SimpleDefinedAtom { 31 public: 32 ObjCImageInfoAtom(const File &file, 33 MachOLinkingContext::ObjCConstraint objCConstraint, 34 uint32_t swiftVersion) 35 : SimpleDefinedAtom(file) { 36 37 Data.info.version = 0; 38 39 switch (objCConstraint) { 40 case MachOLinkingContext::objc_unknown: 41 llvm_unreachable("Shouldn't run the objc pass without a constraint"); 42 case MachOLinkingContext::objc_supports_gc: 43 case MachOLinkingContext::objc_gc_only: 44 llvm_unreachable("GC is not supported"); 45 case MachOLinkingContext::objc_retainReleaseForSimulator: 46 // The retain/release for simulator flag is already the correct 47 // encoded value for the data so just set it here. 48 Data.info.flags = (uint32_t)objCConstraint; 49 break; 50 case MachOLinkingContext::objc_retainRelease: 51 // We don't need to encode this flag, so just leave the flags as 0. 52 Data.info.flags = 0; 53 break; 54 } 55 56 Data.info.flags |= (swiftVersion << 8); 57 } 58 59 ~ObjCImageInfoAtom() override = default; 60 61 ContentType contentType() const override { 62 return DefinedAtom::typeObjCImageInfo; 63 } 64 65 Alignment alignment() const override { 66 return 4; 67 } 68 69 uint64_t size() const override { 70 return 8; 71 } 72 73 ContentPermissions permissions() const override { 74 return DefinedAtom::permR__; 75 } 76 77 ArrayRef<uint8_t> rawContent() const override { 78 return llvm::makeArrayRef(Data.bytes, size()); 79 } 80 81 private: 82 83 struct objc_image_info { 84 uint32_t version; 85 uint32_t flags; 86 }; 87 88 union { 89 objc_image_info info; 90 uint8_t bytes[8]; 91 } Data; 92 }; 93 94 class ObjCPass : public Pass { 95 public: 96 ObjCPass(const MachOLinkingContext &context) 97 : _ctx(context), 98 _file(*_ctx.make_file<MachOFile>("<mach-o objc pass>")) { 99 _file.setOrdinal(_ctx.getNextOrdinalAndIncrement()); 100 } 101 102 llvm::Error perform(SimpleFile &mergedFile) override { 103 // Add the image info. 104 mergedFile.addAtom(*getImageInfo()); 105 106 return llvm::Error(); 107 } 108 109 private: 110 111 const DefinedAtom* getImageInfo() { 112 return new (_file.allocator()) ObjCImageInfoAtom(_file, 113 _ctx.objcConstraint(), 114 _ctx.swiftVersion()); 115 } 116 117 const MachOLinkingContext &_ctx; 118 MachOFile &_file; 119 }; 120 121 122 123 void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx) { 124 pm.add(llvm::make_unique<ObjCPass>(ctx)); 125 } 126 127 } // end namespace mach_o 128 } // end namespace lld 129