structclass_ro_t { uint32_t flags; uint32_t instanceStart; uint32_t instanceSize; #ifdef __LP64__ uint32_t reserved; #endif union { constuint8_t * ivarLayout; Class nonMetaclass; }; explicit_atomic<constchar *> name; // With ptrauth, this is signed if it points to a small list, but // may be unsigned if it points to a big list. void *baseMethodList;//方法列表的获取方法 protocol_list_t * baseProtocols; constivar_list_t * ivars;//成员变量列表 constuint8_t * weakIvarLayout; property_list_t *baseProperties;//属性列表
// This field exists only when RO_HAS_SWIFT_INITIALIZER is set. _objc_swiftMetadataInitializer __ptrauth_objc_method_list_imp _swiftMetadataInitializer_NEVER_USE[0]; _objc_swiftMetadataInitializer swiftMetadataInitializer()const{ if (flags & RO_HAS_SWIFT_INITIALIZER) { return _swiftMetadataInitializer_NEVER_USE[0]; } else { return nil; } } constchar *getName()const{ return name.load(std::memory_order_acquire); } staticconstuint16_t methodListPointerDiscriminator = 0xC310; #if 0 // FIXME: enable this when we get a non-empty definition of __ptrauth_objc_method_list_pointer from ptrauth.h. static_assert(std::is_same< void * __ptrauth_objc_method_list_pointer *, void * __ptrauth(ptrauth_key_method_list_pointer, 1, methodListPointerDiscriminator) *>::value, "Method list pointer signing discriminator must match ptrauth.h"); #endif method_list_t *baseMethods()const{ #if __has_feature(ptrauth_calls) method_list_t *ptr = ptrauth_strip((method_list_t *)baseMethodList, ptrauth_key_method_list_pointer); if (ptr == nullptr) returnnullptr; // Don't auth if the class_ro and the method list are both in the shared cache. // This is secure since they'll be read-only, and this allows the shared cache // to cut down on the number of signed pointers it has. bool roInSharedCache = objc::inSharedCache((uintptr_t)this); bool listInSharedCache = objc::inSharedCache((uintptr_t)ptr); if (roInSharedCache && listInSharedCache) return ptr;
// Auth all other small lists. if (ptr->isSmallList()) ptr = ptrauth_auth_data((method_list_t *)baseMethodList, ptrauth_key_method_list_pointer, ptrauth_blend_discriminator(&baseMethodList, methodListPointerDiscriminator)); return ptr; #else return (method_list_t *)baseMethodList; #endif } ///省略代码 };
void CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, const ObjCPropertyImplDecl *propImpl, llvm::Constant *AtomicHelperFn) { //省略代码 switch (strategy.getKind()) { case PropertyImplStrategy::Native: { // We don't need to do anything for a zero-size struct. if (strategy.getIvarSize().isZero()) return;
// Currently, all atomic accesses have to be through integer // types, so there's no point in trying to pick a prettier type. llvm::Type *bitcastType = llvm::Type::getIntNTy(getLLVMContext(), getContext().toBits(strategy.getIvarSize()));
// Cast both arguments to the chosen operation type. argAddr = Builder.CreateElementBitCast(argAddr, bitcastType); ivarAddr = Builder.CreateElementBitCast(ivarAddr, bitcastType);
// This bitcast load is likely to cause some nasty IR. llvm::Value *load = Builder.CreateLoad(argAddr);
// Perform an atomic store. There are no memory ordering requirements. llvm::StoreInst *store = Builder.CreateStore(load, ivarAddr); store->setAtomic(llvm::AtomicOrdering::Unordered); return; }
case PropertyImplStrategy::GetSetProperty: case PropertyImplStrategy::SetPropertyAndExpressionGet: {
llvm::FunctionCallee setOptimizedPropertyFn = nullptr; llvm::FunctionCallee setPropertyFn = nullptr; if (UseOptimizedSetter(CGM)) { // 10.8 and iOS 6.0 code and GC is off setOptimizedPropertyFn = CGM.getObjCRuntime().GetOptimizedPropertySetFunction( strategy.isAtomic(), strategy.isCopy()); if (!setOptimizedPropertyFn) { CGM.ErrorUnsupported(propImpl, "Obj-C optimized setter - NYI"); return; } } else { setPropertyFn = CGM.getObjCRuntime().GetPropertySetFunction(); if (!setPropertyFn) { CGM.ErrorUnsupported(propImpl, "Obj-C setter requiring atomic copy"); return; } } }
// If we have a copy property, we always have to use getProperty/setProperty. // TODO: we could actually use setProperty and an expression for non-atomics. if (IsCopy) { Kind = GetSetProperty; return; }