]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/passes/objc.cpp
ld64-241.9.tar.gz
[apple/ld64.git] / src / ld / passes / objc.cpp
index cf6f1d4095bfb140e1d41acb1689bececef1ea16..2bbf54a61ead25d474a8c83fcf25e5b671d59b61 100644 (file)
@@ -54,6 +54,7 @@ struct objc_image_info  {
 #define OBJC_IMAGE_REQUIRES_GC                 (1<<2)
 #define OBJC_IMAGE_OPTIMIZED_BY_DYLD   (1<<3)
 #define OBJC_IMAGE_SUPPORTS_COMPACTION (1<<4)
+#define OBJC_IMAGE_IS_SIMULATED                        (1<<5)
 
 
 
@@ -64,11 +65,9 @@ template <typename A>
 class ObjCImageInfoAtom : public ld::Atom {
 public:
                                                                                        ObjCImageInfoAtom(ld::File::ObjcConstraint objcConstraint, 
-                                                                                                                       bool compaction, bool abi2);
+                                                                                                                       bool compaction, bool abi2, uint8_t swiftVersion);
 
        virtual const ld::File*                                 file() const                                    { return NULL; }
-       virtual bool                                                    translationUnitSource(const char** dir, const char**) const 
-                                                                                                                                                       { return false; }
        virtual const char*                                             name() const                                    { return "objc image info"; }
        virtual uint64_t                                                size() const                                    { return sizeof(objc_image_info); }
        virtual uint64_t                                                objectAddress() const                   { return 0; }
@@ -90,7 +89,7 @@ template <typename A> ld::Section ObjCImageInfoAtom<A>::_s_sectionABI2("__DATA",
 
 template <typename A>
 ObjCImageInfoAtom<A>::ObjCImageInfoAtom(ld::File::ObjcConstraint objcConstraint, bool compaction, 
-                                                                               bool abi2)
+                                                                               bool abi2, uint8_t swiftVersion)
        : ld::Atom(abi2 ? _s_sectionABI2 : _s_sectionABI1, ld::Atom::definitionRegular, ld::Atom::combineNever,
                                                        ld::Atom::scopeLinkageUnit, ld::Atom::typeUnclassified, 
                                                        symbolTableNotIn, false, false, false, ld::Atom::Alignment(2))
@@ -113,8 +112,14 @@ ObjCImageInfoAtom<A>::ObjCImageInfoAtom(ld::File::ObjcConstraint objcConstraint,
                        if ( compaction ) 
                                value |= OBJC_IMAGE_SUPPORTS_COMPACTION;
                        break;
+               case ld::File::objcConstraintRetainReleaseForSimulator:
+                               value |= OBJC_IMAGE_IS_SIMULATED;
+                       break;
        }
 
+       // provide swift language version in final binary for runtime to inspect
+       value |= (swiftVersion << 8);
+
        _content.version = 0;
        A::P::E::set32(_content.flags, value);
 }
@@ -132,8 +137,6 @@ public:
                                                                                                                        std::set<const ld::Atom*>& deadAtoms);
 
        virtual const ld::File*                                 file() const                                    { return _file; }
-       virtual bool                                                    translationUnitSource(const char** dir, const char**) const 
-                                                                                                                                                       { return false; }
        virtual const char*                                             name() const                                    { return "objc merged method list"; }
        virtual uint64_t                                                size() const                                    { return _methodCount*3*sizeof(pint_t) + 8; }
        virtual uint64_t                                                objectAddress() const                   { return 0; }
@@ -171,8 +174,6 @@ public:
                                                                                                                        std::set<const ld::Atom*>& deadAtoms);
 
        virtual const ld::File*                                 file() const                                    { return _file; }
-       virtual bool                                                    translationUnitSource(const char** dir, const char**) const 
-                                                                                                                                                       { return false; }
        virtual const char*                                             name() const                                    { return "objc merged protocol list"; }
        virtual uint64_t                                                size() const                                    { return (_protocolCount+1)*sizeof(pint_t); }
        virtual uint64_t                                                objectAddress() const                   { return 0; }
@@ -210,8 +211,6 @@ public:
                                                                                                                        std::set<const ld::Atom*>& deadAtoms);
 
        virtual const ld::File*                                 file() const                                    { return _file; }
-       virtual bool                                                    translationUnitSource(const char** dir, const char**) const 
-                                                                                                                                                       { return false; }
        virtual const char*                                             name() const                                    { return "objc merged property list"; }
        virtual uint64_t                                                size() const                                    { return _propertyCount*2*sizeof(pint_t) + 8; }
        virtual uint64_t                                                objectAddress() const                   { return 0; }
@@ -252,8 +251,6 @@ public:
 
        // overrides of ld::Atom
        virtual const ld::File*                         file() const            { return _atom->file(); }
-       virtual bool                                            translationUnitSource(const char** dir, const char** nm) const
-                                                                                                                       { return _atom->translationUnitSource(dir, nm); }
        virtual const char*                                     name() const            { return _atom->name(); }
        virtual uint64_t                                        size() const            { return _atom->size(); }
        virtual uint64_t                                        objectAddress() const { return _atom->objectAddress(); }
@@ -368,7 +365,7 @@ void ObjCData<A>::setPointerInContent(ld::Internal& state, const ld::Atom* conte
 template <typename A>
 class Category : public ObjCData<A> {
 public:
-       static const ld::Atom*  getClass(ld::Internal& state, const ld::Atom* contentAtom);
+       static const ld::Atom*  getClass(ld::Internal& state, const ld::Atom* contentAtom, bool& hasAddend);
        static const ld::Atom*  getInstanceMethods(ld::Internal& state, const ld::Atom* contentAtom);
        static const ld::Atom*  getClassMethods(ld::Internal& state, const ld::Atom* contentAtom);
        static const ld::Atom*  getProtocols(ld::Internal& state, const ld::Atom* contentAtom);
@@ -380,9 +377,9 @@ private:
 
 
 template <typename A>
-const ld::Atom*        Category<A>::getClass(ld::Internal& state, const ld::Atom* contentAtom)
+const ld::Atom*        Category<A>::getClass(ld::Internal& state, const ld::Atom* contentAtom, bool& hasAddend)
 {
-       return ObjCData<A>::getPointerInContent(state, contentAtom, sizeof(pint_t)); // category_t.cls
+       return ObjCData<A>::getPointerInContent(state, contentAtom, sizeof(pint_t), &hasAddend); // category_t.cls
 }
 
 template <typename A>
@@ -844,10 +841,17 @@ void OptimizeCategories<A>::doit(const Options& opts, ld::Internal& state)
                                // ignore categories also in __objc_nlcatlist
                                if ( nlcatListAtoms.count(categoryAtom) != 0 )
                                        continue;
-                               const ld::Atom* categoryOnClassAtom = Category<A>::getClass(state, categoryAtom); 
+                               const ld::Atom* categoryOnClassAtom = Category<A>::getClass(state, categoryAtom, hasAddend); 
                                assert(categoryOnClassAtom != NULL);
+                               // only look at classes defined in this image
                                if ( categoryOnClassAtom->definition() != ld::Atom::definitionProxy ) {
-                                       // only look at classes defined in this image
+                                       // <rdar://problem/16107696> for now, back off optimization on new style classes
+                                       if ( hasAddend != 0 )
+                                               continue;
+                                       // <rdar://problem/17249777> don't apply categories to swift classes
+                                       if ( categoryOnClassAtom->hasFixupsOfKind(ld::Fixup::kindNoneGroupSubordinate) )
+                                               continue;
+
                                        CatMap::iterator pos = classToCategories.find(categoryOnClassAtom);
                                        if ( pos == classToCategories.end() ) {
                                                classToCategories[categoryOnClassAtom] = new std::vector<const ld::Atom*>();
@@ -1177,19 +1181,27 @@ void doPass(const Options& opts, ld::Internal& state)
 #if SUPPORT_ARCH_x86_64
                        case CPU_TYPE_X86_64:
                                state.addAtom(*new ObjCImageInfoAtom<x86_64>(state.objcObjectConstraint, compaction, 
-                                                               true));
+                                                         true, state.swiftVersion));
                                break;
 #endif
 #if SUPPORT_ARCH_i386
                        case CPU_TYPE_I386:
                                state.addAtom(*new ObjCImageInfoAtom<x86>(state.objcObjectConstraint, compaction, 
-                                                       opts.objCABIVersion2POverride() ? true : false));
+                                                         opts.objCABIVersion2POverride() ? true : false, state.swiftVersion));
                                break;
 #endif
+#if SUPPORT_ARCH_arm_any
                        case CPU_TYPE_ARM:
                                state.addAtom(*new ObjCImageInfoAtom<arm>(state.objcObjectConstraint, compaction, 
-                                                       true));
+                                                         true, state.swiftVersion));
                                break;
+#endif
+#if SUPPORT_ARCH_arm64
+                       case CPU_TYPE_ARM64:
+                               state.addAtom(*new ObjCImageInfoAtom<arm64>(state.objcObjectConstraint, compaction, 
+                                                         true, state.swiftVersion));
+                               break;
+#endif
                        default:
                                assert(0 && "unknown objc arch");
                }       
@@ -1205,16 +1217,19 @@ void doPass(const Options& opts, ld::Internal& state)
 #endif
 #if SUPPORT_ARCH_i386
                        case CPU_TYPE_I386:
-                               // disable optimization until fully tested
                                if ( opts.objCABIVersion2POverride() )
                     OptimizeCategories<x86>::doit(opts, state);
                                break;
 #endif
 #if SUPPORT_ARCH_arm_any
                        case CPU_TYPE_ARM:
-                               // disable optimization until fully tested
                                OptimizeCategories<arm>::doit(opts, state);
                                break;
+#endif
+#if SUPPORT_ARCH_arm64
+                       case CPU_TYPE_ARM64:
+                               // disabled until tested
+                               break;
 #endif
                        default:
                                assert(0 && "unknown objc arch");