1193326Sed//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===// 2193326Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193326Sed// 7193326Sed//===----------------------------------------------------------------------===// 8193326Sed// 9221345Sdim// This provides Objective-C code generation targeting the Apple runtime. 10193326Sed// 11193326Sed//===----------------------------------------------------------------------===// 12193326Sed 13249423Sdim#include "CGBlocks.h" 14249423Sdim#include "CGCleanup.h" 15314564Sdim#include "CGObjCRuntime.h" 16206084Srdivacky#include "CGRecordLayout.h" 17249423Sdim#include "CodeGenFunction.h" 18193326Sed#include "CodeGenModule.h" 19193326Sed#include "clang/AST/ASTContext.h" 20360784Sdim#include "clang/AST/Attr.h" 21193326Sed#include "clang/AST/Decl.h" 22193326Sed#include "clang/AST/DeclObjC.h" 23193326Sed#include "clang/AST/RecordLayout.h" 24193326Sed#include "clang/AST/StmtObjC.h" 25344779Sdim#include "clang/Basic/CodeGenOptions.h" 26193326Sed#include "clang/Basic/LangOptions.h" 27261991Sdim#include "clang/CodeGen/CGFunctionInfo.h" 28360784Sdim#include "clang/CodeGen/ConstantInitBuilder.h" 29314564Sdim#include "llvm/ADT/CachedHashString.h" 30193326Sed#include "llvm/ADT/DenseSet.h" 31198092Srdivacky#include "llvm/ADT/SetVector.h" 32249423Sdim#include "llvm/ADT/SmallPtrSet.h" 33198092Srdivacky#include "llvm/ADT/SmallString.h" 34249423Sdim#include "llvm/IR/DataLayout.h" 35249423Sdim#include "llvm/IR/InlineAsm.h" 36249423Sdim#include "llvm/IR/IntrinsicInst.h" 37249423Sdim#include "llvm/IR/LLVMContext.h" 38249423Sdim#include "llvm/IR/Module.h" 39344779Sdim#include "llvm/Support/ScopedPrinter.h" 40198092Srdivacky#include "llvm/Support/raw_ostream.h" 41198092Srdivacky#include <cstdio> 42193326Sed 43193326Sedusing namespace clang; 44193326Sedusing namespace CodeGen; 45193326Sed 46193326Sednamespace { 47193326Sed 48198092Srdivacky// FIXME: We should find a nicer way to make the labels for metadata, string 49198092Srdivacky// concatenation is lame. 50193326Sed 51193326Sedclass ObjCCommonTypesHelper { 52198092Srdivackyprotected: 53198092Srdivacky llvm::LLVMContext &VMContext; 54198092Srdivacky 55193326Sedprivate: 56223017Sdim // The types of these functions don't really matter because we 57223017Sdim // should always bitcast before calling them. 58223017Sdim 59223017Sdim /// id objc_msgSend (id, SEL, ...) 60341825Sdim /// 61223017Sdim /// The default messenger, used for sends whose ABI is unchanged from 62223017Sdim /// the all-integer/pointer case. 63353358Sdim llvm::FunctionCallee getMessageSendFn() const { 64224145Sdim // Add the non-lazy-bind attribute, since objc_msgSend is likely to 65224145Sdim // be called a lot. 66224145Sdim llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; 67321369Sdim return CGM.CreateRuntimeFunction( 68321369Sdim llvm::FunctionType::get(ObjectPtrTy, params, true), "objc_msgSend", 69321369Sdim llvm::AttributeList::get(CGM.getLLVMContext(), 70321369Sdim llvm::AttributeList::FunctionIndex, 71321369Sdim llvm::Attribute::NonLazyBind)); 72193326Sed } 73198092Srdivacky 74223017Sdim /// void objc_msgSend_stret (id, SEL, ...) 75223017Sdim /// 76223017Sdim /// The messenger used when the return value is an aggregate returned 77223017Sdim /// by indirect reference in the first argument, and therefore the 78223017Sdim /// self and selector parameters are shifted over by one. 79353358Sdim llvm::FunctionCallee getMessageSendStretFn() const { 80224145Sdim llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; 81223017Sdim return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, 82223017Sdim params, true), 83223017Sdim "objc_msgSend_stret"); 84193326Sed } 85198092Srdivacky 86223017Sdim /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...) 87223017Sdim /// 88223017Sdim /// The messenger used when the return value is returned on the x87 89223017Sdim /// floating-point stack; without a special entrypoint, the nil case 90223017Sdim /// would be unbalanced. 91353358Sdim llvm::FunctionCallee getMessageSendFpretFn() const { 92224145Sdim llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; 93234353Sdim return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy, 94234353Sdim params, true), 95223017Sdim "objc_msgSend_fpret"); 96193326Sed } 97198092Srdivacky 98234353Sdim /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...) 99234353Sdim /// 100234353Sdim /// The messenger used when the return value is returned in two values on the 101234353Sdim /// x87 floating point stack; without a special entrypoint, the nil case 102234353Sdim /// would be unbalanced. Only used on 64-bit X86. 103353358Sdim llvm::FunctionCallee getMessageSendFp2retFn() const { 104234353Sdim llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; 105234353Sdim llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext); 106321369Sdim llvm::Type *resultType = 107321369Sdim llvm::StructType::get(longDoubleType, longDoubleType); 108234353Sdim 109234353Sdim return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType, 110234353Sdim params, true), 111234353Sdim "objc_msgSend_fp2ret"); 112234353Sdim } 113234353Sdim 114223017Sdim /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...) 115223017Sdim /// 116223017Sdim /// The messenger used for super calls, which have different dispatch 117223017Sdim /// semantics. The class passed is the superclass of the current 118223017Sdim /// class. 119353358Sdim llvm::FunctionCallee getMessageSendSuperFn() const { 120224145Sdim llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy }; 121193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 122223017Sdim params, true), 123223017Sdim "objc_msgSendSuper"); 124193326Sed } 125198092Srdivacky 126223017Sdim /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...) 127223017Sdim /// 128223017Sdim /// A slightly different messenger used for super calls. The class 129223017Sdim /// passed is the current class. 130353358Sdim llvm::FunctionCallee getMessageSendSuperFn2() const { 131224145Sdim llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy }; 132193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 133223017Sdim params, true), 134223017Sdim "objc_msgSendSuper2"); 135193326Sed } 136198092Srdivacky 137223017Sdim /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super, 138223017Sdim /// SEL op, ...) 139223017Sdim /// 140223017Sdim /// The messenger used for super calls which return an aggregate indirectly. 141353358Sdim llvm::FunctionCallee getMessageSendSuperStretFn() const { 142224145Sdim llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy }; 143198092Srdivacky return CGM.CreateRuntimeFunction( 144223017Sdim llvm::FunctionType::get(CGM.VoidTy, params, true), 145198092Srdivacky "objc_msgSendSuper_stret"); 146193326Sed } 147198092Srdivacky 148223017Sdim /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super, 149223017Sdim /// SEL op, ...) 150223017Sdim /// 151223017Sdim /// objc_msgSendSuper_stret with the super2 semantics. 152353358Sdim llvm::FunctionCallee getMessageSendSuperStretFn2() const { 153224145Sdim llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy }; 154198092Srdivacky return CGM.CreateRuntimeFunction( 155223017Sdim llvm::FunctionType::get(CGM.VoidTy, params, true), 156198092Srdivacky "objc_msgSendSuper2_stret"); 157193326Sed } 158198092Srdivacky 159353358Sdim llvm::FunctionCallee getMessageSendSuperFpretFn() const { 160193326Sed // There is no objc_msgSendSuper_fpret? How can that work? 161193326Sed return getMessageSendSuperFn(); 162193326Sed } 163198092Srdivacky 164353358Sdim llvm::FunctionCallee getMessageSendSuperFpretFn2() const { 165193326Sed // There is no objc_msgSendSuper_fpret? How can that work? 166193326Sed return getMessageSendSuperFn2(); 167193326Sed } 168198092Srdivacky 169193326Sedprotected: 170193326Sed CodeGen::CodeGenModule &CGM; 171198092Srdivacky 172193326Sedpublic: 173314564Sdim llvm::IntegerType *ShortTy, *IntTy, *LongTy; 174314564Sdim llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy; 175276479Sdim llvm::Type *IvarOffsetVarTy; 176198092Srdivacky 177193326Sed /// ObjectPtrTy - LLVM type for object handles (typeof(id)) 178314564Sdim llvm::PointerType *ObjectPtrTy; 179198092Srdivacky 180193326Sed /// PtrObjectPtrTy - LLVM type for id * 181314564Sdim llvm::PointerType *PtrObjectPtrTy; 182198092Srdivacky 183193326Sed /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL)) 184314564Sdim llvm::PointerType *SelectorPtrTy; 185341825Sdim 186234353Sdimprivate: 187193326Sed /// ProtocolPtrTy - LLVM type for external protocol handles 188193326Sed /// (typeof(Protocol)) 189224145Sdim llvm::Type *ExternalProtocolPtrTy; 190341825Sdim 191234353Sdimpublic: 192234353Sdim llvm::Type *getExternalProtocolPtrTy() { 193234353Sdim if (!ExternalProtocolPtrTy) { 194234353Sdim // FIXME: It would be nice to unify this with the opaque type, so that the 195234353Sdim // IR comes out a bit cleaner. 196234353Sdim CodeGen::CodeGenTypes &Types = CGM.getTypes(); 197234353Sdim ASTContext &Ctx = CGM.getContext(); 198234353Sdim llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType()); 199234353Sdim ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T); 200234353Sdim } 201341825Sdim 202234353Sdim return ExternalProtocolPtrTy; 203234353Sdim } 204341825Sdim 205193326Sed // SuperCTy - clang type for struct objc_super. 206193326Sed QualType SuperCTy; 207193326Sed // SuperPtrCTy - clang type for struct objc_super *. 208193326Sed QualType SuperPtrCTy; 209198092Srdivacky 210193326Sed /// SuperTy - LLVM type for struct objc_super. 211224145Sdim llvm::StructType *SuperTy; 212193326Sed /// SuperPtrTy - LLVM type for struct objc_super *. 213314564Sdim llvm::PointerType *SuperPtrTy; 214198092Srdivacky 215193326Sed /// PropertyTy - LLVM type for struct objc_property (struct _prop_t 216193326Sed /// in GCC parlance). 217224145Sdim llvm::StructType *PropertyTy; 218198092Srdivacky 219193326Sed /// PropertyListTy - LLVM type for struct objc_property_list 220193326Sed /// (_prop_list_t in GCC parlance). 221224145Sdim llvm::StructType *PropertyListTy; 222193326Sed /// PropertyListPtrTy - LLVM type for struct objc_property_list*. 223314564Sdim llvm::PointerType *PropertyListPtrTy; 224198092Srdivacky 225193326Sed // MethodTy - LLVM type for struct objc_method. 226224145Sdim llvm::StructType *MethodTy; 227198092Srdivacky 228193326Sed /// CacheTy - LLVM type for struct objc_cache. 229224145Sdim llvm::Type *CacheTy; 230193326Sed /// CachePtrTy - LLVM type for struct objc_cache *. 231314564Sdim llvm::PointerType *CachePtrTy; 232341825Sdim 233353358Sdim llvm::FunctionCallee getGetPropertyFn() { 234193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 235193326Sed ASTContext &Ctx = CGM.getContext(); 236193326Sed // id objc_getProperty (id, SEL, ptrdiff_t, bool) 237204643Srdivacky CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); 238204643Srdivacky CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); 239309124Sdim CanQualType Params[] = { 240309124Sdim IdType, SelType, 241309124Sdim Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), Ctx.BoolTy}; 242226633Sdim llvm::FunctionType *FTy = 243309124Sdim Types.GetFunctionType( 244309124Sdim Types.arrangeBuiltinFunctionDeclaration(IdType, Params)); 245193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_getProperty"); 246193326Sed } 247198092Srdivacky 248353358Sdim llvm::FunctionCallee getSetPropertyFn() { 249193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 250193326Sed ASTContext &Ctx = CGM.getContext(); 251193326Sed // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) 252204643Srdivacky CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); 253204643Srdivacky CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); 254309124Sdim CanQualType Params[] = { 255309124Sdim IdType, 256309124Sdim SelType, 257309124Sdim Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), 258309124Sdim IdType, 259309124Sdim Ctx.BoolTy, 260309124Sdim Ctx.BoolTy}; 261226633Sdim llvm::FunctionType *FTy = 262309124Sdim Types.GetFunctionType( 263309124Sdim Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); 264193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_setProperty"); 265193326Sed } 266198092Srdivacky 267353358Sdim llvm::FunctionCallee getOptimizedSetPropertyFn(bool atomic, bool copy) { 268234353Sdim CodeGen::CodeGenTypes &Types = CGM.getTypes(); 269234353Sdim ASTContext &Ctx = CGM.getContext(); 270341825Sdim // void objc_setProperty_atomic(id self, SEL _cmd, 271234353Sdim // id newValue, ptrdiff_t offset); 272341825Sdim // void objc_setProperty_nonatomic(id self, SEL _cmd, 273234353Sdim // id newValue, ptrdiff_t offset); 274341825Sdim // void objc_setProperty_atomic_copy(id self, SEL _cmd, 275234353Sdim // id newValue, ptrdiff_t offset); 276341825Sdim // void objc_setProperty_nonatomic_copy(id self, SEL _cmd, 277234353Sdim // id newValue, ptrdiff_t offset); 278341825Sdim 279234353Sdim SmallVector<CanQualType,4> Params; 280234353Sdim CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); 281234353Sdim CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); 282234353Sdim Params.push_back(IdType); 283234353Sdim Params.push_back(SelType); 284234353Sdim Params.push_back(IdType); 285234353Sdim Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified()); 286234353Sdim llvm::FunctionType *FTy = 287309124Sdim Types.GetFunctionType( 288309124Sdim Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); 289234353Sdim const char *name; 290234353Sdim if (atomic && copy) 291234353Sdim name = "objc_setProperty_atomic_copy"; 292234353Sdim else if (atomic && !copy) 293234353Sdim name = "objc_setProperty_atomic"; 294234353Sdim else if (!atomic && copy) 295234353Sdim name = "objc_setProperty_nonatomic_copy"; 296234353Sdim else 297234353Sdim name = "objc_setProperty_nonatomic"; 298341825Sdim 299234353Sdim return CGM.CreateRuntimeFunction(FTy, name); 300234353Sdim } 301341825Sdim 302353358Sdim llvm::FunctionCallee getCopyStructFn() { 303207619Srdivacky CodeGen::CodeGenTypes &Types = CGM.getTypes(); 304207619Srdivacky ASTContext &Ctx = CGM.getContext(); 305207619Srdivacky // void objc_copyStruct (void *, const void *, size_t, bool, bool) 306226633Sdim SmallVector<CanQualType,5> Params; 307207619Srdivacky Params.push_back(Ctx.VoidPtrTy); 308207619Srdivacky Params.push_back(Ctx.VoidPtrTy); 309321369Sdim Params.push_back(Ctx.getSizeType()); 310207619Srdivacky Params.push_back(Ctx.BoolTy); 311207619Srdivacky Params.push_back(Ctx.BoolTy); 312226633Sdim llvm::FunctionType *FTy = 313309124Sdim Types.GetFunctionType( 314309124Sdim Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); 315207619Srdivacky return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct"); 316207619Srdivacky } 317341825Sdim 318234353Sdim /// This routine declares and returns address of: 319234353Sdim /// void objc_copyCppObjectAtomic( 320341825Sdim /// void *dest, const void *src, 321234353Sdim /// void (*copyHelper) (void *dest, const void *source)); 322353358Sdim llvm::FunctionCallee getCppAtomicObjectFunction() { 323234353Sdim CodeGen::CodeGenTypes &Types = CGM.getTypes(); 324234353Sdim ASTContext &Ctx = CGM.getContext(); 325234353Sdim /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper); 326234353Sdim SmallVector<CanQualType,3> Params; 327234353Sdim Params.push_back(Ctx.VoidPtrTy); 328234353Sdim Params.push_back(Ctx.VoidPtrTy); 329234353Sdim Params.push_back(Ctx.VoidPtrTy); 330234353Sdim llvm::FunctionType *FTy = 331309124Sdim Types.GetFunctionType( 332309124Sdim Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); 333234353Sdim return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic"); 334234353Sdim } 335341825Sdim 336353358Sdim llvm::FunctionCallee getEnumerationMutationFn() { 337198092Srdivacky CodeGen::CodeGenTypes &Types = CGM.getTypes(); 338198092Srdivacky ASTContext &Ctx = CGM.getContext(); 339193326Sed // void objc_enumerationMutation (id) 340226633Sdim SmallVector<CanQualType,1> Params; 341204643Srdivacky Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType())); 342226633Sdim llvm::FunctionType *FTy = 343309124Sdim Types.GetFunctionType( 344309124Sdim Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); 345193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); 346193326Sed } 347198092Srdivacky 348353358Sdim llvm::FunctionCallee getLookUpClassFn() { 349309124Sdim CodeGen::CodeGenTypes &Types = CGM.getTypes(); 350309124Sdim ASTContext &Ctx = CGM.getContext(); 351309124Sdim // Class objc_lookUpClass (const char *) 352309124Sdim SmallVector<CanQualType,1> Params; 353309124Sdim Params.push_back( 354309124Sdim Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst()))); 355309124Sdim llvm::FunctionType *FTy = 356309124Sdim Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration( 357309124Sdim Ctx.getCanonicalType(Ctx.getObjCClassType()), 358309124Sdim Params)); 359309124Sdim return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass"); 360309124Sdim } 361309124Sdim 362193326Sed /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function. 363353358Sdim llvm::FunctionCallee getGcReadWeakFn() { 364193326Sed // id objc_read_weak (id *) 365224145Sdim llvm::Type *args[] = { ObjectPtrTy->getPointerTo() }; 366198092Srdivacky llvm::FunctionType *FTy = 367223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 368193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); 369198092Srdivacky } 370198092Srdivacky 371193326Sed /// GcAssignWeakFn -- LLVM objc_assign_weak function. 372353358Sdim llvm::FunctionCallee getGcAssignWeakFn() { 373193326Sed // id objc_assign_weak (id, id *) 374224145Sdim llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; 375193326Sed llvm::FunctionType *FTy = 376223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 377193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); 378193326Sed } 379198092Srdivacky 380193326Sed /// GcAssignGlobalFn -- LLVM objc_assign_global function. 381353358Sdim llvm::FunctionCallee getGcAssignGlobalFn() { 382193326Sed // id objc_assign_global(id, id *) 383224145Sdim llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; 384198092Srdivacky llvm::FunctionType *FTy = 385223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 386193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); 387193326Sed } 388198092Srdivacky 389212904Sdim /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function. 390353358Sdim llvm::FunctionCallee getGcAssignThreadLocalFn() { 391212904Sdim // id objc_assign_threadlocal(id src, id * dest) 392224145Sdim llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; 393212904Sdim llvm::FunctionType *FTy = 394223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 395212904Sdim return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal"); 396212904Sdim } 397341825Sdim 398193326Sed /// GcAssignIvarFn -- LLVM objc_assign_ivar function. 399353358Sdim llvm::FunctionCallee getGcAssignIvarFn() { 400198092Srdivacky // id objc_assign_ivar(id, id *, ptrdiff_t) 401224145Sdim llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(), 402224145Sdim CGM.PtrDiffTy }; 403198092Srdivacky llvm::FunctionType *FTy = 404223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 405193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); 406193326Sed } 407198092Srdivacky 408198092Srdivacky /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function. 409353358Sdim llvm::FunctionCallee GcMemmoveCollectableFn() { 410198092Srdivacky // void *objc_memmove_collectable(void *dst, const void *src, size_t size) 411224145Sdim llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy }; 412223017Sdim llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false); 413198092Srdivacky return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); 414198092Srdivacky } 415198092Srdivacky 416193326Sed /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function. 417353358Sdim llvm::FunctionCallee getGcAssignStrongCastFn() { 418212904Sdim // id objc_assign_strongCast(id, id *) 419224145Sdim llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; 420198092Srdivacky llvm::FunctionType *FTy = 421223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 422193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); 423193326Sed } 424193326Sed 425193326Sed /// ExceptionThrowFn - LLVM objc_exception_throw function. 426353358Sdim llvm::FunctionCallee getExceptionThrowFn() { 427193326Sed // void objc_exception_throw(id) 428224145Sdim llvm::Type *args[] = { ObjectPtrTy }; 429193326Sed llvm::FunctionType *FTy = 430223017Sdim llvm::FunctionType::get(CGM.VoidTy, args, false); 431193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); 432193326Sed } 433198092Srdivacky 434210299Sed /// ExceptionRethrowFn - LLVM objc_exception_rethrow function. 435353358Sdim llvm::FunctionCallee getExceptionRethrowFn() { 436210299Sed // void objc_exception_rethrow(void) 437223017Sdim llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false); 438210299Sed return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow"); 439210299Sed } 440341825Sdim 441193326Sed /// SyncEnterFn - LLVM object_sync_enter function. 442353358Sdim llvm::FunctionCallee getSyncEnterFn() { 443243830Sdim // int objc_sync_enter (id) 444224145Sdim llvm::Type *args[] = { ObjectPtrTy }; 445193326Sed llvm::FunctionType *FTy = 446243830Sdim llvm::FunctionType::get(CGM.IntTy, args, false); 447193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); 448193326Sed } 449198092Srdivacky 450193326Sed /// SyncExitFn - LLVM object_sync_exit function. 451353358Sdim llvm::FunctionCallee getSyncExitFn() { 452243830Sdim // int objc_sync_exit (id) 453224145Sdim llvm::Type *args[] = { ObjectPtrTy }; 454193326Sed llvm::FunctionType *FTy = 455243830Sdim llvm::FunctionType::get(CGM.IntTy, args, false); 456193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); 457193326Sed } 458198092Srdivacky 459353358Sdim llvm::FunctionCallee getSendFn(bool IsSuper) const { 460193326Sed return IsSuper ? getMessageSendSuperFn() : getMessageSendFn(); 461193326Sed } 462198092Srdivacky 463353358Sdim llvm::FunctionCallee getSendFn2(bool IsSuper) const { 464193326Sed return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn(); 465193326Sed } 466198092Srdivacky 467353358Sdim llvm::FunctionCallee getSendStretFn(bool IsSuper) const { 468193326Sed return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn(); 469193326Sed } 470198092Srdivacky 471353358Sdim llvm::FunctionCallee getSendStretFn2(bool IsSuper) const { 472193326Sed return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn(); 473193326Sed } 474198092Srdivacky 475353358Sdim llvm::FunctionCallee getSendFpretFn(bool IsSuper) const { 476193326Sed return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn(); 477193326Sed } 478198092Srdivacky 479353358Sdim llvm::FunctionCallee getSendFpretFn2(bool IsSuper) const { 480193326Sed return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn(); 481193326Sed } 482198092Srdivacky 483353358Sdim llvm::FunctionCallee getSendFp2retFn(bool IsSuper) const { 484234353Sdim return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn(); 485234353Sdim } 486234353Sdim 487353358Sdim llvm::FunctionCallee getSendFp2RetFn2(bool IsSuper) const { 488234353Sdim return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn(); 489234353Sdim } 490234353Sdim 491193326Sed ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm); 492193326Sed}; 493193326Sed 494193326Sed/// ObjCTypesHelper - Helper class that encapsulates lazy 495193326Sed/// construction of varies types used during ObjC generation. 496193326Sedclass ObjCTypesHelper : public ObjCCommonTypesHelper { 497193326Sedpublic: 498193326Sed /// SymtabTy - LLVM type for struct objc_symtab. 499224145Sdim llvm::StructType *SymtabTy; 500193326Sed /// SymtabPtrTy - LLVM type for struct objc_symtab *. 501314564Sdim llvm::PointerType *SymtabPtrTy; 502193326Sed /// ModuleTy - LLVM type for struct objc_module. 503224145Sdim llvm::StructType *ModuleTy; 504193326Sed 505193326Sed /// ProtocolTy - LLVM type for struct objc_protocol. 506224145Sdim llvm::StructType *ProtocolTy; 507193326Sed /// ProtocolPtrTy - LLVM type for struct objc_protocol *. 508314564Sdim llvm::PointerType *ProtocolPtrTy; 509193326Sed /// ProtocolExtensionTy - LLVM type for struct 510193326Sed /// objc_protocol_extension. 511224145Sdim llvm::StructType *ProtocolExtensionTy; 512193326Sed /// ProtocolExtensionTy - LLVM type for struct 513193326Sed /// objc_protocol_extension *. 514314564Sdim llvm::PointerType *ProtocolExtensionPtrTy; 515193326Sed /// MethodDescriptionTy - LLVM type for struct 516193326Sed /// objc_method_description. 517224145Sdim llvm::StructType *MethodDescriptionTy; 518193326Sed /// MethodDescriptionListTy - LLVM type for struct 519193326Sed /// objc_method_description_list. 520224145Sdim llvm::StructType *MethodDescriptionListTy; 521193326Sed /// MethodDescriptionListPtrTy - LLVM type for struct 522193326Sed /// objc_method_description_list *. 523314564Sdim llvm::PointerType *MethodDescriptionListPtrTy; 524193326Sed /// ProtocolListTy - LLVM type for struct objc_property_list. 525224145Sdim llvm::StructType *ProtocolListTy; 526193326Sed /// ProtocolListPtrTy - LLVM type for struct objc_property_list*. 527314564Sdim llvm::PointerType *ProtocolListPtrTy; 528193326Sed /// CategoryTy - LLVM type for struct objc_category. 529224145Sdim llvm::StructType *CategoryTy; 530193326Sed /// ClassTy - LLVM type for struct objc_class. 531224145Sdim llvm::StructType *ClassTy; 532193326Sed /// ClassPtrTy - LLVM type for struct objc_class *. 533314564Sdim llvm::PointerType *ClassPtrTy; 534193326Sed /// ClassExtensionTy - LLVM type for struct objc_class_ext. 535224145Sdim llvm::StructType *ClassExtensionTy; 536193326Sed /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *. 537314564Sdim llvm::PointerType *ClassExtensionPtrTy; 538193326Sed // IvarTy - LLVM type for struct objc_ivar. 539224145Sdim llvm::StructType *IvarTy; 540193326Sed /// IvarListTy - LLVM type for struct objc_ivar_list. 541314564Sdim llvm::StructType *IvarListTy; 542193326Sed /// IvarListPtrTy - LLVM type for struct objc_ivar_list *. 543314564Sdim llvm::PointerType *IvarListPtrTy; 544193326Sed /// MethodListTy - LLVM type for struct objc_method_list. 545314564Sdim llvm::StructType *MethodListTy; 546193326Sed /// MethodListPtrTy - LLVM type for struct objc_method_list *. 547314564Sdim llvm::PointerType *MethodListPtrTy; 548198092Srdivacky 549193326Sed /// ExceptionDataTy - LLVM type for struct _objc_exception_data. 550314564Sdim llvm::StructType *ExceptionDataTy; 551341825Sdim 552193326Sed /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function. 553353358Sdim llvm::FunctionCallee getExceptionTryEnterFn() { 554224145Sdim llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; 555198092Srdivacky return CGM.CreateRuntimeFunction( 556223017Sdim llvm::FunctionType::get(CGM.VoidTy, params, false), 557198092Srdivacky "objc_exception_try_enter"); 558193326Sed } 559193326Sed 560193326Sed /// ExceptionTryExitFn - LLVM objc_exception_try_exit function. 561353358Sdim llvm::FunctionCallee getExceptionTryExitFn() { 562224145Sdim llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; 563198092Srdivacky return CGM.CreateRuntimeFunction( 564223017Sdim llvm::FunctionType::get(CGM.VoidTy, params, false), 565198092Srdivacky "objc_exception_try_exit"); 566193326Sed } 567193326Sed 568193326Sed /// ExceptionExtractFn - LLVM objc_exception_extract function. 569353358Sdim llvm::FunctionCallee getExceptionExtractFn() { 570224145Sdim llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; 571193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 572223017Sdim params, false), 573193326Sed "objc_exception_extract"); 574193326Sed } 575198092Srdivacky 576193326Sed /// ExceptionMatchFn - LLVM objc_exception_match function. 577353358Sdim llvm::FunctionCallee getExceptionMatchFn() { 578224145Sdim llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy }; 579198092Srdivacky return CGM.CreateRuntimeFunction( 580223017Sdim llvm::FunctionType::get(CGM.Int32Ty, params, false), 581198092Srdivacky "objc_exception_match"); 582193326Sed } 583198092Srdivacky 584193326Sed /// SetJmpFn - LLVM _setjmp function. 585353358Sdim llvm::FunctionCallee getSetJmpFn() { 586223017Sdim // This is specifically the prototype for x86. 587224145Sdim llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() }; 588321369Sdim return CGM.CreateRuntimeFunction( 589321369Sdim llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp", 590321369Sdim llvm::AttributeList::get(CGM.getLLVMContext(), 591321369Sdim llvm::AttributeList::FunctionIndex, 592321369Sdim llvm::Attribute::NonLazyBind)); 593193326Sed } 594198092Srdivacky 595193326Sedpublic: 596193326Sed ObjCTypesHelper(CodeGen::CodeGenModule &cgm); 597193326Sed}; 598193326Sed 599193326Sed/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's 600193326Sed/// modern abi 601193326Sedclass ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper { 602193326Sedpublic: 603193326Sed // MethodListnfABITy - LLVM for struct _method_list_t 604224145Sdim llvm::StructType *MethodListnfABITy; 605198092Srdivacky 606193326Sed // MethodListnfABIPtrTy - LLVM for struct _method_list_t* 607314564Sdim llvm::PointerType *MethodListnfABIPtrTy; 608198092Srdivacky 609193326Sed // ProtocolnfABITy = LLVM for struct _protocol_t 610224145Sdim llvm::StructType *ProtocolnfABITy; 611198092Srdivacky 612193326Sed // ProtocolnfABIPtrTy = LLVM for struct _protocol_t* 613314564Sdim llvm::PointerType *ProtocolnfABIPtrTy; 614193326Sed 615193326Sed // ProtocolListnfABITy - LLVM for struct _objc_protocol_list 616224145Sdim llvm::StructType *ProtocolListnfABITy; 617198092Srdivacky 618193326Sed // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list* 619314564Sdim llvm::PointerType *ProtocolListnfABIPtrTy; 620198092Srdivacky 621193326Sed // ClassnfABITy - LLVM for struct _class_t 622224145Sdim llvm::StructType *ClassnfABITy; 623198092Srdivacky 624193326Sed // ClassnfABIPtrTy - LLVM for struct _class_t* 625314564Sdim llvm::PointerType *ClassnfABIPtrTy; 626198092Srdivacky 627193326Sed // IvarnfABITy - LLVM for struct _ivar_t 628224145Sdim llvm::StructType *IvarnfABITy; 629198092Srdivacky 630193326Sed // IvarListnfABITy - LLVM for struct _ivar_list_t 631224145Sdim llvm::StructType *IvarListnfABITy; 632198092Srdivacky 633193326Sed // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t* 634314564Sdim llvm::PointerType *IvarListnfABIPtrTy; 635198092Srdivacky 636193326Sed // ClassRonfABITy - LLVM for struct _class_ro_t 637224145Sdim llvm::StructType *ClassRonfABITy; 638198092Srdivacky 639193326Sed // ImpnfABITy - LLVM for id (*)(id, SEL, ...) 640314564Sdim llvm::PointerType *ImpnfABITy; 641198092Srdivacky 642193326Sed // CategorynfABITy - LLVM for struct _category_t 643224145Sdim llvm::StructType *CategorynfABITy; 644198092Srdivacky 645193326Sed // New types for nonfragile abi messaging. 646198092Srdivacky 647193326Sed // MessageRefTy - LLVM for: 648193326Sed // struct _message_ref_t { 649193326Sed // IMP messenger; 650193326Sed // SEL name; 651193326Sed // }; 652224145Sdim llvm::StructType *MessageRefTy; 653193326Sed // MessageRefCTy - clang type for struct _message_ref_t 654193326Sed QualType MessageRefCTy; 655198092Srdivacky 656193326Sed // MessageRefPtrTy - LLVM for struct _message_ref_t* 657224145Sdim llvm::Type *MessageRefPtrTy; 658193326Sed // MessageRefCPtrTy - clang type for struct _message_ref_t* 659193326Sed QualType MessageRefCPtrTy; 660198092Srdivacky 661193326Sed // SuperMessageRefTy - LLVM for: 662193326Sed // struct _super_message_ref_t { 663193326Sed // SUPER_IMP messenger; 664193326Sed // SEL name; 665193326Sed // }; 666224145Sdim llvm::StructType *SuperMessageRefTy; 667198092Srdivacky 668193326Sed // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* 669314564Sdim llvm::PointerType *SuperMessageRefPtrTy; 670193326Sed 671353358Sdim llvm::FunctionCallee getMessageSendFixupFn() { 672193326Sed // id objc_msgSend_fixup(id, struct message_ref_t*, ...) 673224145Sdim llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; 674193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 675223017Sdim params, true), 676193326Sed "objc_msgSend_fixup"); 677193326Sed } 678198092Srdivacky 679353358Sdim llvm::FunctionCallee getMessageSendFpretFixupFn() { 680193326Sed // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...) 681224145Sdim llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; 682193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 683223017Sdim params, true), 684193326Sed "objc_msgSend_fpret_fixup"); 685193326Sed } 686198092Srdivacky 687353358Sdim llvm::FunctionCallee getMessageSendStretFixupFn() { 688193326Sed // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...) 689224145Sdim llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; 690193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 691223017Sdim params, true), 692193326Sed "objc_msgSend_stret_fixup"); 693193326Sed } 694198092Srdivacky 695353358Sdim llvm::FunctionCallee getMessageSendSuper2FixupFn() { 696198092Srdivacky // id objc_msgSendSuper2_fixup (struct objc_super *, 697193326Sed // struct _super_message_ref_t*, ...) 698224145Sdim llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy }; 699193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 700223017Sdim params, true), 701193326Sed "objc_msgSendSuper2_fixup"); 702193326Sed } 703198092Srdivacky 704353358Sdim llvm::FunctionCallee getMessageSendSuper2StretFixupFn() { 705198092Srdivacky // id objc_msgSendSuper2_stret_fixup(struct objc_super *, 706193326Sed // struct _super_message_ref_t*, ...) 707224145Sdim llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy }; 708193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 709223017Sdim params, true), 710193326Sed "objc_msgSendSuper2_stret_fixup"); 711193326Sed } 712198092Srdivacky 713353358Sdim llvm::FunctionCallee getObjCEndCatchFn() { 714223017Sdim return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false), 715193326Sed "objc_end_catch"); 716193326Sed } 717198092Srdivacky 718353358Sdim llvm::FunctionCallee getObjCBeginCatchFn() { 719224145Sdim llvm::Type *params[] = { Int8PtrTy }; 720193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy, 721223017Sdim params, false), 722193326Sed "objc_begin_catch"); 723193326Sed } 724193326Sed 725353358Sdim /// Class objc_loadClassref (void *) 726353358Sdim /// 727353358Sdim /// Loads from a classref. For Objective-C stub classes, this invokes the 728353358Sdim /// initialization callback stored inside the stub. For all other classes 729353358Sdim /// this simply dereferences the pointer. 730353358Sdim llvm::FunctionCallee getLoadClassrefFn() const { 731353358Sdim // Add the non-lazy-bind attribute, since objc_loadClassref is likely to 732353358Sdim // be called a lot. 733353358Sdim // 734353358Sdim // Also it is safe to make it readnone, since we never load or store the 735353358Sdim // classref except by calling this function. 736353358Sdim llvm::Type *params[] = { Int8PtrPtrTy }; 737353358Sdim llvm::FunctionCallee F = CGM.CreateRuntimeFunction( 738353358Sdim llvm::FunctionType::get(ClassnfABIPtrTy, params, false), 739353358Sdim "objc_loadClassref", 740353358Sdim llvm::AttributeList::get(CGM.getLLVMContext(), 741353358Sdim llvm::AttributeList::FunctionIndex, 742353358Sdim {llvm::Attribute::NonLazyBind, 743353358Sdim llvm::Attribute::ReadNone, 744353358Sdim llvm::Attribute::NoUnwind})); 745353358Sdim if (!CGM.getTriple().isOSBinFormatCOFF()) 746353358Sdim cast<llvm::Function>(F.getCallee())->setLinkage( 747353358Sdim llvm::Function::ExternalWeakLinkage); 748353358Sdim 749353358Sdim return F; 750353358Sdim } 751353358Sdim 752224145Sdim llvm::StructType *EHTypeTy; 753224145Sdim llvm::Type *EHTypePtrTy; 754341825Sdim 755193326Sed ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm); 756193326Sed}; 757198092Srdivacky 758314564Sdimenum class ObjCLabelType { 759314564Sdim ClassName, 760314564Sdim MethodVarName, 761314564Sdim MethodVarType, 762314564Sdim PropertyName, 763314564Sdim}; 764314564Sdim 765193326Sedclass CGObjCCommonMac : public CodeGen::CGObjCRuntime { 766193326Sedpublic: 767193326Sed class SKIP_SCAN { 768193326Sed public: 769193326Sed unsigned skip; 770193326Sed unsigned scan; 771198092Srdivacky SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0) 772193326Sed : skip(_skip), scan(_scan) {} 773193326Sed }; 774198092Srdivacky 775243830Sdim /// opcode for captured block variables layout 'instructions'. 776243830Sdim /// In the following descriptions, 'I' is the value of the immediate field. 777243830Sdim /// (field following the opcode). 778243830Sdim /// 779243830Sdim enum BLOCK_LAYOUT_OPCODE { 780243830Sdim /// An operator which affects how the following layout should be 781243830Sdim /// interpreted. 782243830Sdim /// I == 0: Halt interpretation and treat everything else as 783243830Sdim /// a non-pointer. Note that this instruction is equal 784243830Sdim /// to '\0'. 785243830Sdim /// I != 0: Currently unused. 786243830Sdim BLOCK_LAYOUT_OPERATOR = 0, 787341825Sdim 788243830Sdim /// The next I+1 bytes do not contain a value of object pointer type. 789243830Sdim /// Note that this can leave the stream unaligned, meaning that 790243830Sdim /// subsequent word-size instructions do not begin at a multiple of 791243830Sdim /// the pointer size. 792243830Sdim BLOCK_LAYOUT_NON_OBJECT_BYTES = 1, 793341825Sdim 794243830Sdim /// The next I+1 words do not contain a value of object pointer type. 795243830Sdim /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for 796243830Sdim /// when the required skip quantity is a multiple of the pointer size. 797243830Sdim BLOCK_LAYOUT_NON_OBJECT_WORDS = 2, 798341825Sdim 799243830Sdim /// The next I+1 words are __strong pointers to Objective-C 800243830Sdim /// objects or blocks. 801243830Sdim BLOCK_LAYOUT_STRONG = 3, 802341825Sdim 803243830Sdim /// The next I+1 words are pointers to __block variables. 804243830Sdim BLOCK_LAYOUT_BYREF = 4, 805341825Sdim 806243830Sdim /// The next I+1 words are __weak pointers to Objective-C 807243830Sdim /// objects or blocks. 808243830Sdim BLOCK_LAYOUT_WEAK = 5, 809341825Sdim 810243830Sdim /// The next I+1 words are __unsafe_unretained pointers to 811243830Sdim /// Objective-C objects or blocks. 812243830Sdim BLOCK_LAYOUT_UNRETAINED = 6 813341825Sdim 814243830Sdim /// The next I+1 words are block or object pointers with some 815243830Sdim /// as-yet-unspecified ownership semantics. If we add more 816243830Sdim /// flavors of ownership semantics, values will be taken from 817243830Sdim /// this range. 818243830Sdim /// 819243830Sdim /// This is included so that older tools can at least continue 820243830Sdim /// processing the layout past such things. 821243830Sdim //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10, 822341825Sdim 823243830Sdim /// All other opcodes are reserved. Halt interpretation and 824243830Sdim /// treat everything else as opaque. 825243830Sdim }; 826341825Sdim 827243830Sdim class RUN_SKIP { 828243830Sdim public: 829243830Sdim enum BLOCK_LAYOUT_OPCODE opcode; 830243830Sdim CharUnits block_var_bytepos; 831243830Sdim CharUnits block_var_size; 832243830Sdim RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR, 833243830Sdim CharUnits BytePos = CharUnits::Zero(), 834243830Sdim CharUnits Size = CharUnits::Zero()) 835243830Sdim : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {} 836341825Sdim 837243830Sdim // Allow sorting based on byte pos. 838243830Sdim bool operator<(const RUN_SKIP &b) const { 839243830Sdim return block_var_bytepos < b.block_var_bytepos; 840243830Sdim } 841243830Sdim }; 842341825Sdim 843193326Sedprotected: 844198092Srdivacky llvm::LLVMContext &VMContext; 845193326Sed // FIXME! May not be needing this after all. 846193326Sed unsigned ObjCABI; 847198092Srdivacky 848243830Sdim // arc/mrr layout of captured block literal variables. 849243830Sdim SmallVector<RUN_SKIP, 16> RunSkipBlockVars; 850198092Srdivacky 851193326Sed /// LazySymbols - Symbols to generate a lazy reference for. See 852193326Sed /// DefinedSymbols and FinishModule(). 853198092Srdivacky llvm::SetVector<IdentifierInfo*> LazySymbols; 854198092Srdivacky 855193326Sed /// DefinedSymbols - External symbols which are defined by this 856193326Sed /// module. The symbols in this list and LazySymbols are used to add 857193326Sed /// special linker symbols which ensure that Objective-C modules are 858193326Sed /// linked properly. 859198092Srdivacky llvm::SetVector<IdentifierInfo*> DefinedSymbols; 860198092Srdivacky 861193326Sed /// ClassNames - uniqued class names. 862276479Sdim llvm::StringMap<llvm::GlobalVariable*> ClassNames; 863198092Srdivacky 864193326Sed /// MethodVarNames - uniqued method variable names. 865193326Sed llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames; 866198092Srdivacky 867210299Sed /// DefinedCategoryNames - list of category names in form Class_Category. 868314564Sdim llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames; 869210299Sed 870193326Sed /// MethodVarTypes - uniqued method type signatures. We have to use 871193326Sed /// a StringMap here because have no other unique reference. 872193326Sed llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes; 873198092Srdivacky 874193326Sed /// MethodDefinitions - map of methods which have been defined in 875193326Sed /// this translation unit. 876193326Sed llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions; 877198092Srdivacky 878360784Sdim /// DirectMethodDefinitions - map of direct methods which have been defined in 879360784Sdim /// this translation unit. 880360784Sdim llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> DirectMethodDefinitions; 881360784Sdim 882193326Sed /// PropertyNames - uniqued method variable names. 883193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames; 884198092Srdivacky 885193326Sed /// ClassReferences - uniqued class references. 886193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences; 887198092Srdivacky 888193326Sed /// SelectorReferences - uniqued selector references. 889193326Sed llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences; 890198092Srdivacky 891193326Sed /// Protocols - Protocols for which an objc_protocol structure has 892193326Sed /// been emitted. Forward declarations are handled by creating an 893193326Sed /// empty structure whose initializer is filled in when/if defined. 894193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols; 895198092Srdivacky 896193326Sed /// DefinedProtocols - Protocols which have actually been 897193326Sed /// defined. We should not need this, see FIXME in GenerateProtocol. 898193326Sed llvm::DenseSet<IdentifierInfo*> DefinedProtocols; 899198092Srdivacky 900193326Sed /// DefinedClasses - List of defined classes. 901249423Sdim SmallVector<llvm::GlobalValue*, 16> DefinedClasses; 902341825Sdim 903276479Sdim /// ImplementedClasses - List of @implemented classes. 904276479Sdim SmallVector<const ObjCInterfaceDecl*, 16> ImplementedClasses; 905193326Sed 906193326Sed /// DefinedNonLazyClasses - List of defined "non-lazy" classes. 907249423Sdim SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses; 908198092Srdivacky 909193326Sed /// DefinedCategories - List of defined categories. 910249423Sdim SmallVector<llvm::GlobalValue*, 16> DefinedCategories; 911198092Srdivacky 912353358Sdim /// DefinedStubCategories - List of defined categories on class stubs. 913353358Sdim SmallVector<llvm::GlobalValue*, 16> DefinedStubCategories; 914353358Sdim 915193326Sed /// DefinedNonLazyCategories - List of defined "non-lazy" categories. 916249423Sdim SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories; 917193326Sed 918314564Sdim /// Cached reference to the class for constant strings. This value has type 919314564Sdim /// int * but is actually an Obj-C class pointer. 920321369Sdim llvm::WeakTrackingVH ConstantStringClassRef; 921314564Sdim 922341825Sdim /// The LLVM type corresponding to NSConstantString. 923314564Sdim llvm::StructType *NSConstantStringType = nullptr; 924314564Sdim 925314564Sdim llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap; 926314564Sdim 927193326Sed /// GetNameForMethod - Return a name for the given method. 928193326Sed /// \param[out] NameOut - The return value. 929193326Sed void GetNameForMethod(const ObjCMethodDecl *OMD, 930193326Sed const ObjCContainerDecl *CD, 931360784Sdim SmallVectorImpl<char> &NameOut, 932360784Sdim bool ignoreCategoryNamespace = false); 933198092Srdivacky 934193326Sed /// GetMethodVarName - Return a unique constant for the given 935193326Sed /// selector's name. The return value has type char *. 936193326Sed llvm::Constant *GetMethodVarName(Selector Sel); 937193326Sed llvm::Constant *GetMethodVarName(IdentifierInfo *Ident); 938198092Srdivacky 939193326Sed /// GetMethodVarType - Return a unique constant for the given 940234353Sdim /// method's type encoding string. The return value has type char *. 941198092Srdivacky 942193326Sed // FIXME: This is a horrible name. 943234353Sdim llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D, 944234353Sdim bool Extended = false); 945193326Sed llvm::Constant *GetMethodVarType(const FieldDecl *D); 946198092Srdivacky 947193326Sed /// GetPropertyName - Return a unique constant for the given 948193326Sed /// name. The return value has type char *. 949193326Sed llvm::Constant *GetPropertyName(IdentifierInfo *Ident); 950198092Srdivacky 951193326Sed // FIXME: This can be dropped once string functions are unified. 952193326Sed llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD, 953193326Sed const Decl *Container); 954198092Srdivacky 955193326Sed /// GetClassName - Return a unique constant for the given selector's 956276479Sdim /// runtime name (which may change via use of objc_runtime_name attribute on 957276479Sdim /// class or protocol definition. The return value has type char *. 958276479Sdim llvm::Constant *GetClassName(StringRef RuntimeName); 959198092Srdivacky 960212904Sdim llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD); 961212904Sdim 962193326Sed /// BuildIvarLayout - Builds ivar layout bitmap for the class 963193326Sed /// implementation for the __strong or __weak case. 964193326Sed /// 965296417Sdim /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there 966296417Sdim /// are any weak ivars defined directly in the class. Meaningless unless 967296417Sdim /// building a weak layout. Does not guarantee that the layout will 968296417Sdim /// actually have any entries, because the ivar might be under-aligned. 969193326Sed llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI, 970296417Sdim CharUnits beginOffset, 971296417Sdim CharUnits endOffset, 972296417Sdim bool forStrongLayout, 973296417Sdim bool hasMRCWeakIvars); 974198092Srdivacky 975296417Sdim llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI, 976296417Sdim CharUnits beginOffset, 977296417Sdim CharUnits endOffset) { 978296417Sdim return BuildIvarLayout(OI, beginOffset, endOffset, true, false); 979296417Sdim } 980296417Sdim 981296417Sdim llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI, 982296417Sdim CharUnits beginOffset, 983296417Sdim CharUnits endOffset, 984296417Sdim bool hasMRCWeakIvars) { 985296417Sdim return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars); 986296417Sdim } 987341825Sdim 988249423Sdim Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout); 989341825Sdim 990243830Sdim void UpdateRunSkipBlockVars(bool IsByref, 991243830Sdim Qualifiers::ObjCLifetime LifeTime, 992243830Sdim CharUnits FieldOffset, 993243830Sdim CharUnits FieldSize); 994341825Sdim 995243830Sdim void BuildRCBlockVarRecordLayout(const RecordType *RT, 996249423Sdim CharUnits BytePos, bool &HasUnion, 997249423Sdim bool ByrefLayout=false); 998341825Sdim 999243830Sdim void BuildRCRecordLayout(const llvm::StructLayout *RecLayout, 1000243830Sdim const RecordDecl *RD, 1001243830Sdim ArrayRef<const FieldDecl*> RecFields, 1002249423Sdim CharUnits BytePos, bool &HasUnion, 1003249423Sdim bool ByrefLayout); 1004341825Sdim 1005243830Sdim uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout); 1006341825Sdim 1007249423Sdim llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout); 1008341825Sdim 1009193326Sed /// GetIvarLayoutName - Returns a unique constant for the given 1010193326Sed /// ivar layout bitmap. 1011193326Sed llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident, 1012193326Sed const ObjCCommonTypesHelper &ObjCTypes); 1013198092Srdivacky 1014193326Sed /// EmitPropertyList - Emit the given property list. The return 1015193326Sed /// value has type PropertyListPtrTy. 1016226633Sdim llvm::Constant *EmitPropertyList(Twine Name, 1017198092Srdivacky const Decl *Container, 1018193326Sed const ObjCContainerDecl *OCD, 1019309124Sdim const ObjCCommonTypesHelper &ObjCTypes, 1020309124Sdim bool IsClassProperty); 1021198092Srdivacky 1022341825Sdim /// EmitProtocolMethodTypes - Generate the array of extended method type 1023234353Sdim /// strings. The return value has type Int8PtrPtrTy. 1024341825Sdim llvm::Constant *EmitProtocolMethodTypes(Twine Name, 1025234353Sdim ArrayRef<llvm::Constant*> MethodTypes, 1026234353Sdim const ObjCCommonTypesHelper &ObjCTypes); 1027234353Sdim 1028193326Sed /// GetProtocolRef - Return a reference to the internal protocol 1029193326Sed /// description, creating an empty one if it has not been 1030193326Sed /// defined. The return value has type ProtocolPtrTy. 1031193326Sed llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD); 1032193326Sed 1033309124Sdim /// Return a reference to the given Class using runtime calls rather than 1034309124Sdim /// by a symbol reference. 1035309124Sdim llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF, 1036309124Sdim const ObjCInterfaceDecl *ID, 1037309124Sdim ObjCCommonTypesHelper &ObjCTypes); 1038309124Sdim 1039321369Sdim std::string GetSectionName(StringRef Section, StringRef MachOAttributes); 1040321369Sdim 1041296417Sdimpublic: 1042193326Sed /// CreateMetadataVar - Create a global variable with internal 1043193326Sed /// linkage for use by the Objective-C runtime. 1044193326Sed /// 1045193326Sed /// This is a convenience wrapper which not only creates the 1046193326Sed /// variable, but also sets the section and alignment and adds the 1047198092Srdivacky /// global to the "llvm.used" list. 1048193326Sed /// 1049193326Sed /// \param Name - The variable name. 1050193326Sed /// \param Init - The variable initializer; this is also used to 1051314564Sdim /// define the type of the variable. 1052276479Sdim /// \param Section - The section the variable should go into, or empty. 1053193326Sed /// \param Align - The alignment for the variable, or 0. 1054193326Sed /// \param AddToUsed - Whether the variable should be added to 1055314564Sdim /// "llvm.used". 1056314564Sdim llvm::GlobalVariable *CreateMetadataVar(Twine Name, 1057314564Sdim ConstantStructBuilder &Init, 1058296417Sdim StringRef Section, CharUnits Align, 1059193326Sed bool AddToUsed); 1060314564Sdim llvm::GlobalVariable *CreateMetadataVar(Twine Name, 1061314564Sdim llvm::Constant *Init, 1062314564Sdim StringRef Section, CharUnits Align, 1063314564Sdim bool AddToUsed); 1064193326Sed 1065314564Sdim llvm::GlobalVariable *CreateCStringLiteral(StringRef Name, 1066314564Sdim ObjCLabelType LabelType, 1067314564Sdim bool ForceNonFragileABI = false, 1068314564Sdim bool NullTerminate = true); 1069314564Sdim 1070296417Sdimprotected: 1071223017Sdim CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, 1072223017Sdim ReturnValueSlot Return, 1073223017Sdim QualType ResultType, 1074360784Sdim Selector Sel, 1075223017Sdim llvm::Value *Arg0, 1076223017Sdim QualType Arg0Ty, 1077223017Sdim bool IsSuper, 1078223017Sdim const CallArgList &CallArgs, 1079223017Sdim const ObjCMethodDecl *OMD, 1080296417Sdim const ObjCInterfaceDecl *ClassReceiver, 1081223017Sdim const ObjCCommonTypesHelper &ObjCTypes); 1082193326Sed 1083207619Srdivacky /// EmitImageInfo - Emit the image info marker used to encode some module 1084207619Srdivacky /// level information. 1085207619Srdivacky void EmitImageInfo(); 1086207619Srdivacky 1087198092Srdivackypublic: 1088198092Srdivacky CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : 1089234353Sdim CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { } 1090195099Sed 1091296417Sdim bool isNonFragileABI() const { 1092296417Sdim return ObjCABI == 2; 1093296417Sdim } 1094198092Srdivacky 1095296417Sdim ConstantAddress GenerateConstantString(const StringLiteral *SL) override; 1096314564Sdim ConstantAddress GenerateConstantNSString(const StringLiteral *SL); 1097296417Sdim 1098276479Sdim llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, 1099276479Sdim const ObjCContainerDecl *CD=nullptr) override; 1100198092Srdivacky 1101360784Sdim llvm::Function *GenerateDirectMethod(const ObjCMethodDecl *OMD, 1102360784Sdim const ObjCContainerDecl *CD); 1103360784Sdim 1104360784Sdim void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn, 1105360784Sdim const ObjCMethodDecl *OMD, 1106360784Sdim const ObjCContainerDecl *CD) override; 1107360784Sdim 1108276479Sdim void GenerateProtocol(const ObjCProtocolDecl *PD) override; 1109276479Sdim 1110193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1111193326Sed /// declaration, emitting it if necessary. The return value has type 1112193326Sed /// ProtocolPtrTy. 1113193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0; 1114198092Srdivacky 1115193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1116193326Sed /// object for the given declaration, emitting it if needed. These 1117193326Sed /// forward references will be filled in with empty bodies if no 1118193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1119193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0; 1120314564Sdim 1121314564Sdim virtual llvm::Constant *getNSConstantStringClassRef() = 0; 1122314564Sdim 1123276479Sdim llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, 1124276479Sdim const CGBlockInfo &blockInfo) override; 1125276479Sdim llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, 1126276479Sdim const CGBlockInfo &blockInfo) override; 1127344779Sdim std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM, 1128344779Sdim const CGBlockInfo &blockInfo) override; 1129276479Sdim 1130276479Sdim llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM, 1131276479Sdim QualType T) override; 1132344779Sdim 1133344779Sdimprivate: 1134344779Sdim void fillRunSkipBlockVars(CodeGenModule &CGM, const CGBlockInfo &blockInfo); 1135193326Sed}; 1136198092Srdivacky 1137314564Sdimnamespace { 1138314564Sdim 1139314564Sdimenum class MethodListType { 1140314564Sdim CategoryInstanceMethods, 1141314564Sdim CategoryClassMethods, 1142314564Sdim InstanceMethods, 1143314564Sdim ClassMethods, 1144314564Sdim ProtocolInstanceMethods, 1145314564Sdim ProtocolClassMethods, 1146314564Sdim OptionalProtocolInstanceMethods, 1147314564Sdim OptionalProtocolClassMethods, 1148314564Sdim}; 1149314564Sdim 1150314564Sdim/// A convenience class for splitting the methods of a protocol into 1151314564Sdim/// the four interesting groups. 1152314564Sdimclass ProtocolMethodLists { 1153314564Sdimpublic: 1154314564Sdim enum Kind { 1155314564Sdim RequiredInstanceMethods, 1156314564Sdim RequiredClassMethods, 1157314564Sdim OptionalInstanceMethods, 1158314564Sdim OptionalClassMethods 1159314564Sdim }; 1160314564Sdim enum { 1161314564Sdim NumProtocolMethodLists = 4 1162314564Sdim }; 1163314564Sdim 1164314564Sdim static MethodListType getMethodListKind(Kind kind) { 1165314564Sdim switch (kind) { 1166314564Sdim case RequiredInstanceMethods: 1167314564Sdim return MethodListType::ProtocolInstanceMethods; 1168314564Sdim case RequiredClassMethods: 1169314564Sdim return MethodListType::ProtocolClassMethods; 1170314564Sdim case OptionalInstanceMethods: 1171314564Sdim return MethodListType::OptionalProtocolInstanceMethods; 1172314564Sdim case OptionalClassMethods: 1173314564Sdim return MethodListType::OptionalProtocolClassMethods; 1174314564Sdim } 1175314564Sdim llvm_unreachable("bad kind"); 1176314564Sdim } 1177314564Sdim 1178314564Sdim SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists]; 1179314564Sdim 1180314564Sdim static ProtocolMethodLists get(const ObjCProtocolDecl *PD) { 1181314564Sdim ProtocolMethodLists result; 1182314564Sdim 1183314564Sdim for (auto MD : PD->methods()) { 1184314564Sdim size_t index = (2 * size_t(MD->isOptional())) 1185314564Sdim + (size_t(MD->isClassMethod())); 1186314564Sdim result.Methods[index].push_back(MD); 1187314564Sdim } 1188314564Sdim 1189314564Sdim return result; 1190314564Sdim } 1191314564Sdim 1192314564Sdim template <class Self> 1193314564Sdim SmallVector<llvm::Constant*, 8> emitExtendedTypesArray(Self *self) const { 1194314564Sdim // In both ABIs, the method types list is parallel with the 1195314564Sdim // concatenation of the methods arrays in the following order: 1196314564Sdim // instance methods 1197314564Sdim // class methods 1198314564Sdim // optional instance methods 1199314564Sdim // optional class methods 1200314564Sdim SmallVector<llvm::Constant*, 8> result; 1201314564Sdim 1202314564Sdim // Methods is already in the correct order for both ABIs. 1203314564Sdim for (auto &list : Methods) { 1204314564Sdim for (auto MD : list) { 1205314564Sdim result.push_back(self->GetMethodVarType(MD, true)); 1206314564Sdim } 1207314564Sdim } 1208314564Sdim 1209314564Sdim return result; 1210314564Sdim } 1211314564Sdim 1212314564Sdim template <class Self> 1213314564Sdim llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD, 1214314564Sdim Kind kind) const { 1215314564Sdim return self->emitMethodList(PD->getObjCRuntimeNameAsString(), 1216314564Sdim getMethodListKind(kind), Methods[kind]); 1217314564Sdim } 1218314564Sdim}; 1219314564Sdim 1220314564Sdim} // end anonymous namespace 1221314564Sdim 1222193326Sedclass CGObjCMac : public CGObjCCommonMac { 1223193326Sedprivate: 1224314564Sdim friend ProtocolMethodLists; 1225314564Sdim 1226193326Sed ObjCTypesHelper ObjCTypes; 1227193326Sed 1228193326Sed /// EmitModuleInfo - Another marker encoding module level 1229198092Srdivacky /// information. 1230193326Sed void EmitModuleInfo(); 1231193326Sed 1232193326Sed /// EmitModuleSymols - Emit module symbols, the list of defined 1233193326Sed /// classes and categories. The result has type SymtabPtrTy. 1234193326Sed llvm::Constant *EmitModuleSymbols(); 1235193326Sed 1236193326Sed /// FinishModule - Write out global data structures at the end of 1237193326Sed /// processing a translation unit. 1238193326Sed void FinishModule(); 1239193326Sed 1240193326Sed /// EmitClassExtension - Generate the class extension structure used 1241193326Sed /// to store the weak ivar layout and properties. The return value 1242193326Sed /// has type ClassExtensionPtrTy. 1243296417Sdim llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID, 1244296417Sdim CharUnits instanceSize, 1245309124Sdim bool hasMRCWeakIvars, 1246314564Sdim bool isMetaclass); 1247193326Sed 1248193326Sed /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1249193326Sed /// for the given class. 1250249423Sdim llvm::Value *EmitClassRef(CodeGenFunction &CGF, 1251193326Sed const ObjCInterfaceDecl *ID); 1252341825Sdim 1253249423Sdim llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, 1254224145Sdim IdentifierInfo *II); 1255276479Sdim 1256276479Sdim llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override; 1257276479Sdim 1258199482Srdivacky /// EmitSuperClassRef - Emits reference to class's main metadata class. 1259199482Srdivacky llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID); 1260193326Sed 1261193326Sed /// EmitIvarList - Emit the ivar list for the given 1262193326Sed /// implementation. If ForClass is true the list of class ivars 1263193326Sed /// (i.e. metaclass ivars) is emitted, otherwise the list of 1264193326Sed /// interface ivars will be emitted. The return value has type 1265193326Sed /// IvarListPtrTy. 1266193326Sed llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID, 1267193326Sed bool ForClass); 1268198092Srdivacky 1269193326Sed /// EmitMetaClass - Emit a forward reference to the class structure 1270193326Sed /// for the metaclass of the given interface. The return value has 1271193326Sed /// type ClassPtrTy. 1272193326Sed llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID); 1273193326Sed 1274193326Sed /// EmitMetaClass - Emit a class structure for the metaclass of the 1275193326Sed /// given implementation. The return value has type ClassPtrTy. 1276193326Sed llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID, 1277193326Sed llvm::Constant *Protocols, 1278314564Sdim ArrayRef<const ObjCMethodDecl *> Methods); 1279198092Srdivacky 1280314564Sdim void emitMethodConstant(ConstantArrayBuilder &builder, 1281314564Sdim const ObjCMethodDecl *MD); 1282198092Srdivacky 1283314564Sdim void emitMethodDescriptionConstant(ConstantArrayBuilder &builder, 1284314564Sdim const ObjCMethodDecl *MD); 1285193326Sed 1286193326Sed /// EmitMethodList - Emit the method list for the given 1287193326Sed /// implementation. The return value has type MethodListPtrTy. 1288314564Sdim llvm::Constant *emitMethodList(Twine Name, MethodListType MLT, 1289314564Sdim ArrayRef<const ObjCMethodDecl *> Methods); 1290193326Sed 1291193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1292193326Sed /// declaration, emitting it if necessary. The return value has type 1293193326Sed /// ProtocolPtrTy. 1294276479Sdim llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override; 1295193326Sed 1296193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1297193326Sed /// object for the given declaration, emitting it if needed. These 1298193326Sed /// forward references will be filled in with empty bodies if no 1299193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1300276479Sdim llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override; 1301193326Sed 1302193326Sed /// EmitProtocolExtension - Generate the protocol extension 1303193326Sed /// structure used to store optional instance and class methods, and 1304193326Sed /// protocol properties. The return value has type 1305193326Sed /// ProtocolExtensionPtrTy. 1306193326Sed llvm::Constant * 1307193326Sed EmitProtocolExtension(const ObjCProtocolDecl *PD, 1308314564Sdim const ProtocolMethodLists &methodLists); 1309193326Sed 1310193326Sed /// EmitProtocolList - Generate the list of referenced 1311193326Sed /// protocols. The return value has type ProtocolListPtrTy. 1312226633Sdim llvm::Constant *EmitProtocolList(Twine Name, 1313193326Sed ObjCProtocolDecl::protocol_iterator begin, 1314193326Sed ObjCProtocolDecl::protocol_iterator end); 1315193326Sed 1316193326Sed /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, 1317193326Sed /// for the given selector. 1318296417Sdim llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); 1319360784Sdim Address EmitSelectorAddr(Selector Sel); 1320198092Srdivacky 1321198092Srdivackypublic: 1322193326Sed CGObjCMac(CodeGen::CodeGenModule &cgm); 1323193326Sed 1324314564Sdim llvm::Constant *getNSConstantStringClassRef() override; 1325314564Sdim 1326276479Sdim llvm::Function *ModuleInitFunction() override; 1327198092Srdivacky 1328276479Sdim CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1329276479Sdim ReturnValueSlot Return, 1330276479Sdim QualType ResultType, 1331276479Sdim Selector Sel, llvm::Value *Receiver, 1332276479Sdim const CallArgList &CallArgs, 1333276479Sdim const ObjCInterfaceDecl *Class, 1334276479Sdim const ObjCMethodDecl *Method) override; 1335193326Sed 1336276479Sdim CodeGen::RValue 1337193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1338276479Sdim ReturnValueSlot Return, QualType ResultType, 1339276479Sdim Selector Sel, const ObjCInterfaceDecl *Class, 1340276479Sdim bool isCategoryImpl, llvm::Value *Receiver, 1341276479Sdim bool IsClassMessage, const CallArgList &CallArgs, 1342276479Sdim const ObjCMethodDecl *Method) override; 1343198092Srdivacky 1344276479Sdim llvm::Value *GetClass(CodeGenFunction &CGF, 1345276479Sdim const ObjCInterfaceDecl *ID) override; 1346193326Sed 1347296417Sdim llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override; 1348296417Sdim Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override; 1349193326Sed 1350193326Sed /// The NeXT/Apple runtimes do not support typed selectors; just emit an 1351193326Sed /// untyped one. 1352276479Sdim llvm::Value *GetSelector(CodeGenFunction &CGF, 1353276479Sdim const ObjCMethodDecl *Method) override; 1354193326Sed 1355276479Sdim llvm::Constant *GetEHType(QualType T) override; 1356212904Sdim 1357276479Sdim void GenerateCategory(const ObjCCategoryImplDecl *CMD) override; 1358193326Sed 1359276479Sdim void GenerateClass(const ObjCImplementationDecl *ClassDecl) override; 1360193326Sed 1361276479Sdim void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {} 1362234353Sdim 1363276479Sdim llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, 1364276479Sdim const ObjCProtocolDecl *PD) override; 1365198092Srdivacky 1366353358Sdim llvm::FunctionCallee GetPropertyGetFunction() override; 1367353358Sdim llvm::FunctionCallee GetPropertySetFunction() override; 1368353358Sdim llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic, 1369353358Sdim bool copy) override; 1370353358Sdim llvm::FunctionCallee GetGetStructFunction() override; 1371353358Sdim llvm::FunctionCallee GetSetStructFunction() override; 1372353358Sdim llvm::FunctionCallee GetCppAtomicObjectGetFunction() override; 1373353358Sdim llvm::FunctionCallee GetCppAtomicObjectSetFunction() override; 1374353358Sdim llvm::FunctionCallee EnumerationMutationFunction() override; 1375198092Srdivacky 1376276479Sdim void EmitTryStmt(CodeGen::CodeGenFunction &CGF, 1377276479Sdim const ObjCAtTryStmt &S) override; 1378276479Sdim void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1379276479Sdim const ObjCAtSynchronizedStmt &S) override; 1380210299Sed void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S); 1381276479Sdim void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S, 1382276479Sdim bool ClearInsertionPoint=true) override; 1383276479Sdim llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1384296417Sdim Address AddrWeakObj) override; 1385276479Sdim void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1386296417Sdim llvm::Value *src, Address dst) override; 1387276479Sdim void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1388296417Sdim llvm::Value *src, Address dest, 1389276479Sdim bool threadlocal = false) override; 1390276479Sdim void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 1391296417Sdim llvm::Value *src, Address dest, 1392276479Sdim llvm::Value *ivarOffset) override; 1393276479Sdim void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 1394296417Sdim llvm::Value *src, Address dest) override; 1395276479Sdim void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 1396296417Sdim Address dest, Address src, 1397276479Sdim llvm::Value *size) override; 1398198092Srdivacky 1399276479Sdim LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, 1400276479Sdim llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, 1401276479Sdim unsigned CVRQualifiers) override; 1402276479Sdim llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 1403276479Sdim const ObjCInterfaceDecl *Interface, 1404276479Sdim const ObjCIvarDecl *Ivar) override; 1405193326Sed}; 1406198092Srdivacky 1407193326Sedclass CGObjCNonFragileABIMac : public CGObjCCommonMac { 1408193326Sedprivate: 1409314564Sdim friend ProtocolMethodLists; 1410193326Sed ObjCNonFragileABITypesHelper ObjCTypes; 1411193326Sed llvm::GlobalVariable* ObjCEmptyCacheVar; 1412314564Sdim llvm::Constant* ObjCEmptyVtableVar; 1413198092Srdivacky 1414193326Sed /// SuperClassReferences - uniqued super class references. 1415193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences; 1416198092Srdivacky 1417193326Sed /// MetaClassReferences - uniqued meta class references. 1418193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences; 1419193326Sed 1420193326Sed /// EHTypeReferences - uniqued class ehtype references. 1421193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences; 1422198092Srdivacky 1423223017Sdim /// VTableDispatchMethods - List of methods for which we generate 1424223017Sdim /// vtable-based message dispatch. 1425223017Sdim llvm::DenseSet<Selector> VTableDispatchMethods; 1426198092Srdivacky 1427199482Srdivacky /// DefinedMetaClasses - List of defined meta-classes. 1428199482Srdivacky std::vector<llvm::GlobalValue*> DefinedMetaClasses; 1429341825Sdim 1430223017Sdim /// isVTableDispatchedSelector - Returns true if SEL is a 1431223017Sdim /// vtable-based selector. 1432223017Sdim bool isVTableDispatchedSelector(Selector Sel); 1433198092Srdivacky 1434193326Sed /// FinishNonFragileABIModule - Write out global data structures at the end of 1435193326Sed /// processing a translation unit. 1436193326Sed void FinishNonFragileABIModule(); 1437193326Sed 1438193326Sed /// AddModuleClassList - Add the given list of class pointers to the 1439193326Sed /// module with the provided symbol and section names. 1440309124Sdim void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container, 1441309124Sdim StringRef SymbolName, StringRef SectionName); 1442193326Sed 1443198092Srdivacky llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags, 1444198092Srdivacky unsigned InstanceStart, 1445198092Srdivacky unsigned InstanceSize, 1446198092Srdivacky const ObjCImplementationDecl *ID); 1447314564Sdim llvm::GlobalVariable *BuildClassObject(const ObjCInterfaceDecl *CI, 1448314564Sdim bool isMetaclass, 1449314564Sdim llvm::Constant *IsAGV, 1450314564Sdim llvm::Constant *SuperClassGV, 1451314564Sdim llvm::Constant *ClassRoGV, 1452314564Sdim bool HiddenVisibility); 1453198092Srdivacky 1454314564Sdim void emitMethodConstant(ConstantArrayBuilder &builder, 1455314564Sdim const ObjCMethodDecl *MD, 1456314564Sdim bool forProtocol); 1457198092Srdivacky 1458314564Sdim /// Emit the method list for the given implementation. The return value 1459314564Sdim /// has type MethodListnfABITy. 1460314564Sdim llvm::Constant *emitMethodList(Twine Name, MethodListType MLT, 1461314564Sdim ArrayRef<const ObjCMethodDecl *> Methods); 1462198092Srdivacky 1463193326Sed /// EmitIvarList - Emit the ivar list for the given 1464193326Sed /// implementation. If ForClass is true the list of class ivars 1465193326Sed /// (i.e. metaclass ivars) is emitted, otherwise the list of 1466193326Sed /// interface ivars will be emitted. The return value has type 1467193326Sed /// IvarListnfABIPtrTy. 1468193326Sed llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID); 1469198092Srdivacky 1470193326Sed llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, 1471193326Sed const ObjCIvarDecl *Ivar, 1472193326Sed unsigned long int offset); 1473198092Srdivacky 1474193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1475193326Sed /// declaration, emitting it if necessary. The return value has type 1476193326Sed /// ProtocolPtrTy. 1477276479Sdim llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override; 1478198092Srdivacky 1479193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1480193326Sed /// object for the given declaration, emitting it if needed. These 1481193326Sed /// forward references will be filled in with empty bodies if no 1482193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1483276479Sdim llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override; 1484198092Srdivacky 1485193326Sed /// EmitProtocolList - Generate the list of referenced 1486193326Sed /// protocols. The return value has type ProtocolListPtrTy. 1487226633Sdim llvm::Constant *EmitProtocolList(Twine Name, 1488193326Sed ObjCProtocolDecl::protocol_iterator begin, 1489193326Sed ObjCProtocolDecl::protocol_iterator end); 1490198092Srdivacky 1491223017Sdim CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF, 1492223017Sdim ReturnValueSlot Return, 1493223017Sdim QualType ResultType, 1494223017Sdim Selector Sel, 1495223017Sdim llvm::Value *Receiver, 1496223017Sdim QualType Arg0Ty, 1497223017Sdim bool IsSuper, 1498223017Sdim const CallArgList &CallArgs, 1499223017Sdim const ObjCMethodDecl *Method); 1500341825Sdim 1501193326Sed /// GetClassGlobal - Return the global variable for the Objective-C 1502193326Sed /// class of the given name. 1503314564Sdim llvm::Constant *GetClassGlobal(StringRef Name, 1504314564Sdim ForDefinition_t IsForDefinition, 1505314564Sdim bool Weak = false, bool DLLImport = false); 1506314564Sdim llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID, 1507314564Sdim bool isMetaclass, 1508314564Sdim ForDefinition_t isForDefinition); 1509276479Sdim 1510353358Sdim llvm::Constant *GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID); 1511353358Sdim 1512353358Sdim llvm::Value *EmitLoadOfClassRef(CodeGenFunction &CGF, 1513353358Sdim const ObjCInterfaceDecl *ID, 1514353358Sdim llvm::GlobalVariable *Entry); 1515353358Sdim 1516193326Sed /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1517193326Sed /// for the given class reference. 1518249423Sdim llvm::Value *EmitClassRef(CodeGenFunction &CGF, 1519193326Sed const ObjCInterfaceDecl *ID); 1520341825Sdim 1521249423Sdim llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, 1522314564Sdim IdentifierInfo *II, 1523276479Sdim const ObjCInterfaceDecl *ID); 1524198092Srdivacky 1525276479Sdim llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override; 1526276479Sdim 1527193326Sed /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1528193326Sed /// for the given super class reference. 1529249423Sdim llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF, 1530198092Srdivacky const ObjCInterfaceDecl *ID); 1531198092Srdivacky 1532193326Sed /// EmitMetaClassRef - Return a Value * of the address of _class_t 1533193326Sed /// meta-data 1534249423Sdim llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF, 1535276479Sdim const ObjCInterfaceDecl *ID, bool Weak); 1536193326Sed 1537193326Sed /// ObjCIvarOffsetVariable - Returns the ivar offset variable for 1538193326Sed /// the given ivar. 1539193326Sed /// 1540193326Sed llvm::GlobalVariable * ObjCIvarOffsetVariable( 1541198092Srdivacky const ObjCInterfaceDecl *ID, 1542198092Srdivacky const ObjCIvarDecl *Ivar); 1543198092Srdivacky 1544193326Sed /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, 1545193326Sed /// for the given selector. 1546296417Sdim llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel); 1547360784Sdim Address EmitSelectorAddr(Selector Sel); 1548193326Sed 1549193326Sed /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C 1550193326Sed /// interface. The return value has type EHTypePtrTy. 1551212904Sdim llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID, 1552314564Sdim ForDefinition_t IsForDefinition); 1553193326Sed 1554309124Sdim StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; } 1555198092Srdivacky 1556309124Sdim StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; } 1557193326Sed 1558193326Sed void GetClassSizeInfo(const ObjCImplementationDecl *OID, 1559193326Sed uint32_t &InstanceStart, 1560193326Sed uint32_t &InstanceSize); 1561198092Srdivacky 1562193326Sed // Shamelessly stolen from Analysis/CFRefCount.cpp 1563193326Sed Selector GetNullarySelector(const char* name) const { 1564193326Sed IdentifierInfo* II = &CGM.getContext().Idents.get(name); 1565193326Sed return CGM.getContext().Selectors.getSelector(0, &II); 1566193326Sed } 1567198092Srdivacky 1568193326Sed Selector GetUnarySelector(const char* name) const { 1569193326Sed IdentifierInfo* II = &CGM.getContext().Idents.get(name); 1570193326Sed return CGM.getContext().Selectors.getSelector(1, &II); 1571193326Sed } 1572193326Sed 1573193326Sed /// ImplementationIsNonLazy - Check whether the given category or 1574193326Sed /// class implementation is "non-lazy". 1575193326Sed bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const; 1576193326Sed 1577249423Sdim bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF, 1578249423Sdim const ObjCIvarDecl *IV) { 1579276479Sdim // Annotate the load as an invariant load iff inside an instance method 1580276479Sdim // and ivar belongs to instance method's class and one of its super class. 1581276479Sdim // This check is needed because the ivar offset is a lazily 1582249423Sdim // initialised value that may depend on objc_msgSend to perform a fixup on 1583249423Sdim // the first message dispatch. 1584249423Sdim // 1585249423Sdim // An additional opportunity to mark the load as invariant arises when the 1586249423Sdim // base of the ivar access is a parameter to an Objective C method. 1587249423Sdim // However, because the parameters are not available in the current 1588249423Sdim // interface, we cannot perform this check. 1589360784Sdim // 1590360784Sdim // Note that for direct methods, because objc_msgSend is skipped, 1591360784Sdim // and that the method may be inlined, this optimization actually 1592360784Sdim // can't be performed. 1593276479Sdim if (const ObjCMethodDecl *MD = 1594276479Sdim dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl)) 1595360784Sdim if (MD->isInstanceMethod() && !MD->isDirectMethod()) 1596276479Sdim if (const ObjCInterfaceDecl *ID = MD->getClassInterface()) 1597276479Sdim return IV->getContainingInterface()->isSuperClassOf(ID); 1598249423Sdim return false; 1599249423Sdim } 1600249423Sdim 1601353358Sdim bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) { 1602353358Sdim // NSObject is a fixed size. If we can see the @implementation of a class 1603353358Sdim // which inherits from NSObject then we know that all it's offsets also must 1604353358Sdim // be fixed. FIXME: Can we do this if see a chain of super classes with 1605353358Sdim // implementations leading to NSObject? 1606353358Sdim return ID->getImplementation() && ID->getSuperClass() && 1607353358Sdim ID->getSuperClass()->getName() == "NSObject"; 1608353358Sdim } 1609353358Sdim 1610193326Sedpublic: 1611193326Sed CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); 1612314564Sdim 1613314564Sdim llvm::Constant *getNSConstantStringClassRef() override; 1614314564Sdim 1615276479Sdim llvm::Function *ModuleInitFunction() override; 1616198092Srdivacky 1617276479Sdim CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1618276479Sdim ReturnValueSlot Return, 1619276479Sdim QualType ResultType, Selector Sel, 1620276479Sdim llvm::Value *Receiver, 1621276479Sdim const CallArgList &CallArgs, 1622276479Sdim const ObjCInterfaceDecl *Class, 1623276479Sdim const ObjCMethodDecl *Method) override; 1624198092Srdivacky 1625276479Sdim CodeGen::RValue 1626193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1627276479Sdim ReturnValueSlot Return, QualType ResultType, 1628276479Sdim Selector Sel, const ObjCInterfaceDecl *Class, 1629276479Sdim bool isCategoryImpl, llvm::Value *Receiver, 1630276479Sdim bool IsClassMessage, const CallArgList &CallArgs, 1631276479Sdim const ObjCMethodDecl *Method) override; 1632198092Srdivacky 1633276479Sdim llvm::Value *GetClass(CodeGenFunction &CGF, 1634276479Sdim const ObjCInterfaceDecl *ID) override; 1635198092Srdivacky 1636296417Sdim llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override 1637296417Sdim { return EmitSelector(CGF, Sel); } 1638296417Sdim Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override 1639360784Sdim { return EmitSelectorAddr(Sel); } 1640193326Sed 1641193326Sed /// The NeXT/Apple runtimes do not support typed selectors; just emit an 1642193326Sed /// untyped one. 1643276479Sdim llvm::Value *GetSelector(CodeGenFunction &CGF, 1644276479Sdim const ObjCMethodDecl *Method) override 1645249423Sdim { return EmitSelector(CGF, Method->getSelector()); } 1646198092Srdivacky 1647276479Sdim void GenerateCategory(const ObjCCategoryImplDecl *CMD) override; 1648198092Srdivacky 1649276479Sdim void GenerateClass(const ObjCImplementationDecl *ClassDecl) override; 1650234353Sdim 1651276479Sdim void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {} 1652234353Sdim 1653276479Sdim llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, 1654276479Sdim const ObjCProtocolDecl *PD) override; 1655198092Srdivacky 1656276479Sdim llvm::Constant *GetEHType(QualType T) override; 1657212904Sdim 1658353358Sdim llvm::FunctionCallee GetPropertyGetFunction() override { 1659193326Sed return ObjCTypes.getGetPropertyFn(); 1660193326Sed } 1661353358Sdim llvm::FunctionCallee GetPropertySetFunction() override { 1662198092Srdivacky return ObjCTypes.getSetPropertyFn(); 1663193326Sed } 1664276479Sdim 1665353358Sdim llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic, 1666353358Sdim bool copy) override { 1667234353Sdim return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy); 1668234353Sdim } 1669276479Sdim 1670353358Sdim llvm::FunctionCallee GetSetStructFunction() override { 1671207619Srdivacky return ObjCTypes.getCopyStructFn(); 1672207619Srdivacky } 1673309124Sdim 1674353358Sdim llvm::FunctionCallee GetGetStructFunction() override { 1675218893Sdim return ObjCTypes.getCopyStructFn(); 1676218893Sdim } 1677309124Sdim 1678353358Sdim llvm::FunctionCallee GetCppAtomicObjectSetFunction() override { 1679234353Sdim return ObjCTypes.getCppAtomicObjectFunction(); 1680234353Sdim } 1681309124Sdim 1682353358Sdim llvm::FunctionCallee GetCppAtomicObjectGetFunction() override { 1683249423Sdim return ObjCTypes.getCppAtomicObjectFunction(); 1684249423Sdim } 1685276479Sdim 1686353358Sdim llvm::FunctionCallee EnumerationMutationFunction() override { 1687193326Sed return ObjCTypes.getEnumerationMutationFn(); 1688193326Sed } 1689198092Srdivacky 1690276479Sdim void EmitTryStmt(CodeGen::CodeGenFunction &CGF, 1691276479Sdim const ObjCAtTryStmt &S) override; 1692276479Sdim void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1693276479Sdim const ObjCAtSynchronizedStmt &S) override; 1694276479Sdim void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S, 1695276479Sdim bool ClearInsertionPoint=true) override; 1696276479Sdim llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1697296417Sdim Address AddrWeakObj) override; 1698276479Sdim void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1699296417Sdim llvm::Value *src, Address edst) override; 1700276479Sdim void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1701296417Sdim llvm::Value *src, Address dest, 1702276479Sdim bool threadlocal = false) override; 1703276479Sdim void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 1704296417Sdim llvm::Value *src, Address dest, 1705276479Sdim llvm::Value *ivarOffset) override; 1706276479Sdim void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 1707296417Sdim llvm::Value *src, Address dest) override; 1708276479Sdim void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 1709296417Sdim Address dest, Address src, 1710276479Sdim llvm::Value *size) override; 1711276479Sdim LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, 1712276479Sdim llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, 1713276479Sdim unsigned CVRQualifiers) override; 1714276479Sdim llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 1715276479Sdim const ObjCInterfaceDecl *Interface, 1716276479Sdim const ObjCIvarDecl *Ivar) override; 1717193326Sed}; 1718198092Srdivacky 1719223017Sdim/// A helper class for performing the null-initialization of a return 1720223017Sdim/// value. 1721223017Sdimstruct NullReturnState { 1722223017Sdim llvm::BasicBlock *NullBB; 1723276479Sdim NullReturnState() : NullBB(nullptr) {} 1724223017Sdim 1725249423Sdim /// Perform a null-check of the given receiver. 1726223017Sdim void init(CodeGenFunction &CGF, llvm::Value *receiver) { 1727249423Sdim // Make blocks for the null-receiver and call edges. 1728249423Sdim NullBB = CGF.createBasicBlock("msgSend.null-receiver"); 1729249423Sdim llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call"); 1730223017Sdim 1731223017Sdim // Check for a null receiver and, if there is one, jump to the 1732249423Sdim // null-receiver block. There's no point in trying to avoid it: 1733249423Sdim // we're always going to put *something* there, because otherwise 1734249423Sdim // we shouldn't have done this null-check in the first place. 1735223017Sdim llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver); 1736223017Sdim CGF.Builder.CreateCondBr(isNull, NullBB, callBB); 1737223017Sdim 1738223017Sdim // Otherwise, start performing the call. 1739223017Sdim CGF.EmitBlock(callBB); 1740223017Sdim } 1741223017Sdim 1742249423Sdim /// Complete the null-return operation. It is valid to call this 1743249423Sdim /// regardless of whether 'init' has been called. 1744321369Sdim RValue complete(CodeGenFunction &CGF, 1745321369Sdim ReturnValueSlot returnSlot, 1746321369Sdim RValue result, 1747321369Sdim QualType resultType, 1748234353Sdim const CallArgList &CallArgs, 1749234353Sdim const ObjCMethodDecl *Method) { 1750249423Sdim // If we never had to do a null-check, just use the raw result. 1751223017Sdim if (!NullBB) return result; 1752249423Sdim 1753249423Sdim // The continuation block. This will be left null if we don't have an 1754249423Sdim // IP, which can happen if the method we're calling is marked noreturn. 1755276479Sdim llvm::BasicBlock *contBB = nullptr; 1756276479Sdim 1757249423Sdim // Finish the call path. 1758249423Sdim llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock(); 1759249423Sdim if (callBB) { 1760249423Sdim contBB = CGF.createBasicBlock("msgSend.cont"); 1761249423Sdim CGF.Builder.CreateBr(contBB); 1762234353Sdim } 1763223017Sdim 1764249423Sdim // Okay, start emitting the null-receiver block. 1765223017Sdim CGF.EmitBlock(NullBB); 1766341825Sdim 1767249423Sdim // Release any consumed arguments we've got. 1768234353Sdim if (Method) { 1769234353Sdim CallArgList::const_iterator I = CallArgs.begin(); 1770234353Sdim for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(), 1771234353Sdim e = Method->param_end(); i != e; ++i, ++I) { 1772234353Sdim const ParmVarDecl *ParamDecl = (*i); 1773234353Sdim if (ParamDecl->hasAttr<NSConsumedAttr>()) { 1774341825Sdim RValue RV = I->getRValue(CGF); 1775341825Sdim assert(RV.isScalar() && 1776234353Sdim "NullReturnState::complete - arg not on object"); 1777249423Sdim CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime); 1778234353Sdim } 1779234353Sdim } 1780234353Sdim } 1781249423Sdim 1782249423Sdim // The phi code below assumes that we haven't needed any control flow yet. 1783249423Sdim assert(CGF.Builder.GetInsertBlock() == NullBB); 1784249423Sdim 1785249423Sdim // If we've got a void return, just jump to the continuation block. 1786249423Sdim if (result.isScalar() && resultType->isVoidType()) { 1787249423Sdim // No jumps required if the message-send was noreturn. 1788249423Sdim if (contBB) CGF.EmitBlock(contBB); 1789249423Sdim return result; 1790249423Sdim } 1791249423Sdim 1792249423Sdim // If we've got a scalar return, build a phi. 1793234353Sdim if (result.isScalar()) { 1794249423Sdim // Derive the null-initialization value. 1795249423Sdim llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType); 1796249423Sdim 1797249423Sdim // If no join is necessary, just flow out. 1798249423Sdim if (!contBB) return RValue::get(null); 1799249423Sdim 1800249423Sdim // Otherwise, build a phi. 1801234353Sdim CGF.EmitBlock(contBB); 1802249423Sdim llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2); 1803249423Sdim phi->addIncoming(result.getScalarVal(), callBB); 1804249423Sdim phi->addIncoming(null, NullBB); 1805249423Sdim return RValue::get(phi); 1806234353Sdim } 1807249423Sdim 1808249423Sdim // If we've got an aggregate return, null the buffer out. 1809249423Sdim // FIXME: maybe we should be doing things differently for all the 1810249423Sdim // cases where the ABI has us returning (1) non-agg values in 1811249423Sdim // memory or (2) agg values in registers. 1812249423Sdim if (result.isAggregate()) { 1813234353Sdim assert(result.isAggregate() && "null init of non-aggregate result?"); 1814321369Sdim if (!returnSlot.isUnused()) 1815321369Sdim CGF.EmitNullInitialization(result.getAggregateAddress(), resultType); 1816249423Sdim if (contBB) CGF.EmitBlock(contBB); 1817234353Sdim return result; 1818234353Sdim } 1819223017Sdim 1820249423Sdim // Complex types. 1821223017Sdim CGF.EmitBlock(contBB); 1822249423Sdim CodeGenFunction::ComplexPairTy callResult = result.getComplexVal(); 1823249423Sdim 1824249423Sdim // Find the scalar type and its zero value. 1825249423Sdim llvm::Type *scalarTy = callResult.first->getType(); 1826249423Sdim llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy); 1827249423Sdim 1828249423Sdim // Build phis for both coordinates. 1829249423Sdim llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2); 1830249423Sdim real->addIncoming(callResult.first, callBB); 1831249423Sdim real->addIncoming(scalarZero, NullBB); 1832249423Sdim llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2); 1833249423Sdim imag->addIncoming(callResult.second, callBB); 1834249423Sdim imag->addIncoming(scalarZero, NullBB); 1835249423Sdim return RValue::getComplex(real, imag); 1836223017Sdim } 1837223017Sdim}; 1838223017Sdim 1839193326Sed} // end anonymous namespace 1840193326Sed 1841193326Sed/* *** Helper Functions *** */ 1842193326Sed 1843193326Sed/// getConstantGEP() - Help routine to construct simple GEPs. 1844198092Srdivackystatic llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext, 1845288943Sdim llvm::GlobalVariable *C, unsigned idx0, 1846193326Sed unsigned idx1) { 1847193326Sed llvm::Value *Idxs[] = { 1848198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0), 1849198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1) 1850193326Sed }; 1851288943Sdim return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs); 1852193326Sed} 1853193326Sed 1854193326Sed/// hasObjCExceptionAttribute - Return true if this class or any super 1855193326Sed/// class has the __objc_exception__ attribute. 1856198092Srdivackystatic bool hasObjCExceptionAttribute(ASTContext &Context, 1857194613Sed const ObjCInterfaceDecl *OID) { 1858195341Sed if (OID->hasAttr<ObjCExceptionAttr>()) 1859193326Sed return true; 1860193326Sed if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 1861194613Sed return hasObjCExceptionAttribute(Context, Super); 1862193326Sed return false; 1863193326Sed} 1864193326Sed 1865353358Sdimstatic llvm::GlobalValue::LinkageTypes 1866353358SdimgetLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section) { 1867353358Sdim if (CGM.getTriple().isOSBinFormatMachO() && 1868353358Sdim (Section.empty() || Section.startswith("__DATA"))) 1869353358Sdim return llvm::GlobalValue::InternalLinkage; 1870353358Sdim return llvm::GlobalValue::PrivateLinkage; 1871353358Sdim} 1872353358Sdim 1873353358Sdim/// A helper function to create an internal or private global variable. 1874353358Sdimstatic llvm::GlobalVariable * 1875353358SdimfinishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder, 1876353358Sdim const llvm::Twine &Name, CodeGenModule &CGM) { 1877353358Sdim std::string SectionName; 1878353358Sdim if (CGM.getTriple().isOSBinFormatMachO()) 1879353358Sdim SectionName = "__DATA, __objc_const"; 1880353358Sdim auto *GV = Builder.finishAndCreateGlobal( 1881353358Sdim Name, CGM.getPointerAlign(), /*constant*/ false, 1882353358Sdim getLinkageTypeForObjCMetadata(CGM, SectionName)); 1883353358Sdim GV->setSection(SectionName); 1884353358Sdim return GV; 1885353358Sdim} 1886353358Sdim 1887193326Sed/* *** CGObjCMac Public Interface *** */ 1888198092Srdivacky 1889193326SedCGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), 1890198092Srdivacky ObjCTypes(cgm) { 1891193326Sed ObjCABI = 1; 1892198092Srdivacky EmitImageInfo(); 1893193326Sed} 1894193326Sed 1895193326Sed/// GetClass - Return a reference to the class for the given interface 1896193326Sed/// decl. 1897249423Sdimllvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF, 1898193326Sed const ObjCInterfaceDecl *ID) { 1899249423Sdim return EmitClassRef(CGF, ID); 1900193326Sed} 1901193326Sed 1902193326Sed/// GetSelector - Return the pointer to the unique'd string for this selector. 1903296417Sdimllvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) { 1904296417Sdim return EmitSelector(CGF, Sel); 1905193326Sed} 1906296417SdimAddress CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) { 1907360784Sdim return EmitSelectorAddr(Sel); 1908296417Sdim} 1909249423Sdimllvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl 1910198092Srdivacky *Method) { 1911249423Sdim return EmitSelector(CGF, Method->getSelector()); 1912193326Sed} 1913193326Sed 1914212904Sdimllvm::Constant *CGObjCMac::GetEHType(QualType T) { 1915224145Sdim if (T->isObjCIdType() || 1916224145Sdim T->isObjCQualifiedIdType()) { 1917224145Sdim return CGM.GetAddrOfRTTIDescriptor( 1918226633Sdim CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true); 1919224145Sdim } 1920224145Sdim if (T->isObjCClassType() || 1921224145Sdim T->isObjCQualifiedClassType()) { 1922224145Sdim return CGM.GetAddrOfRTTIDescriptor( 1923226633Sdim CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true); 1924224145Sdim } 1925224145Sdim if (T->isObjCObjectPointerType()) 1926224145Sdim return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true); 1927341825Sdim 1928212904Sdim llvm_unreachable("asking for catch type for ObjC type in fragile runtime"); 1929212904Sdim} 1930212904Sdim 1931193326Sed/// Generate a constant CFString object. 1932198092Srdivacky/* 1933198092Srdivacky struct __builtin_CFString { 1934198092Srdivacky const int *isa; // point to __CFConstantStringClassReference 1935198092Srdivacky int flags; 1936198092Srdivacky const char *str; 1937198092Srdivacky long length; 1938198092Srdivacky }; 1939193326Sed*/ 1940193326Sed 1941207619Srdivacky/// or Generate a constant NSString object. 1942207619Srdivacky/* 1943207619Srdivacky struct __builtin_NSString { 1944207619Srdivacky const int *isa; // point to __NSConstantStringClassReference 1945207619Srdivacky const char *str; 1946207619Srdivacky unsigned int length; 1947207619Srdivacky }; 1948207619Srdivacky*/ 1949207619Srdivacky 1950314564SdimConstantAddress 1951314564SdimCGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) { 1952314564Sdim return (!CGM.getLangOpts().NoConstantCFStrings 1953314564Sdim ? CGM.GetAddrOfConstantCFString(SL) 1954314564Sdim : GenerateConstantNSString(SL)); 1955193326Sed} 1956193326Sed 1957314564Sdimstatic llvm::StringMapEntry<llvm::GlobalVariable *> & 1958314564SdimGetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map, 1959314564Sdim const StringLiteral *Literal, unsigned &StringLength) { 1960314564Sdim StringRef String = Literal->getString(); 1961314564Sdim StringLength = String.size(); 1962314564Sdim return *Map.insert(std::make_pair(String, nullptr)).first; 1963314564Sdim} 1964314564Sdim 1965314564Sdimllvm::Constant *CGObjCMac::getNSConstantStringClassRef() { 1966314564Sdim if (llvm::Value *V = ConstantStringClassRef) 1967314564Sdim return cast<llvm::Constant>(V); 1968314564Sdim 1969314564Sdim auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass; 1970314564Sdim std::string str = 1971314564Sdim StringClass.empty() ? "_NSConstantStringClassReference" 1972314564Sdim : "_" + StringClass + "ClassReference"; 1973314564Sdim 1974314564Sdim llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0); 1975314564Sdim auto GV = CGM.CreateRuntimeVariable(PTy, str); 1976314564Sdim auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo()); 1977314564Sdim ConstantStringClassRef = V; 1978314564Sdim return V; 1979314564Sdim} 1980314564Sdim 1981314564Sdimllvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() { 1982314564Sdim if (llvm::Value *V = ConstantStringClassRef) 1983314564Sdim return cast<llvm::Constant>(V); 1984314564Sdim 1985314564Sdim auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass; 1986341825Sdim std::string str = 1987341825Sdim StringClass.empty() ? "OBJC_CLASS_$_NSConstantString" 1988314564Sdim : "OBJC_CLASS_$_" + StringClass; 1989353358Sdim llvm::Constant *GV = GetClassGlobal(str, NotForDefinition); 1990314564Sdim 1991314564Sdim // Make sure the result is of the correct type. 1992314564Sdim auto V = llvm::ConstantExpr::getBitCast(GV, CGM.IntTy->getPointerTo()); 1993314564Sdim 1994314564Sdim ConstantStringClassRef = V; 1995314564Sdim return V; 1996314564Sdim} 1997314564Sdim 1998314564SdimConstantAddress 1999314564SdimCGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) { 2000314564Sdim unsigned StringLength = 0; 2001314564Sdim llvm::StringMapEntry<llvm::GlobalVariable *> &Entry = 2002314564Sdim GetConstantStringEntry(NSConstantStringMap, Literal, StringLength); 2003314564Sdim 2004314564Sdim if (auto *C = Entry.second) 2005314564Sdim return ConstantAddress(C, CharUnits::fromQuantity(C->getAlignment())); 2006314564Sdim 2007314564Sdim // If we don't already have it, get _NSConstantStringClassReference. 2008314564Sdim llvm::Constant *Class = getNSConstantStringClassRef(); 2009314564Sdim 2010314564Sdim // If we don't already have it, construct the type for a constant NSString. 2011314564Sdim if (!NSConstantStringType) { 2012314564Sdim NSConstantStringType = 2013314564Sdim llvm::StructType::create({ 2014314564Sdim CGM.Int32Ty->getPointerTo(), 2015314564Sdim CGM.Int8PtrTy, 2016314564Sdim CGM.IntTy 2017314564Sdim }, "struct.__builtin_NSString"); 2018314564Sdim } 2019314564Sdim 2020314564Sdim ConstantInitBuilder Builder(CGM); 2021314564Sdim auto Fields = Builder.beginStruct(NSConstantStringType); 2022314564Sdim 2023314564Sdim // Class pointer. 2024314564Sdim Fields.add(Class); 2025314564Sdim 2026314564Sdim // String pointer. 2027314564Sdim llvm::Constant *C = 2028314564Sdim llvm::ConstantDataArray::getString(VMContext, Entry.first()); 2029314564Sdim 2030314564Sdim llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage; 2031314564Sdim bool isConstant = !CGM.getLangOpts().WritableStrings; 2032314564Sdim 2033314564Sdim auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant, 2034314564Sdim Linkage, C, ".str"); 2035314564Sdim GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 2036314564Sdim // Don't enforce the target's minimum global alignment, since the only use 2037314564Sdim // of the string is via this class initializer. 2038360784Sdim GV->setAlignment(llvm::Align::None()); 2039314564Sdim Fields.addBitCast(GV, CGM.Int8PtrTy); 2040314564Sdim 2041314564Sdim // String length. 2042314564Sdim Fields.addInt(CGM.IntTy, StringLength); 2043314564Sdim 2044314564Sdim // The struct. 2045314564Sdim CharUnits Alignment = CGM.getPointerAlign(); 2046314564Sdim GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment, 2047314564Sdim /*constant*/ true, 2048314564Sdim llvm::GlobalVariable::PrivateLinkage); 2049314564Sdim const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip"; 2050314564Sdim const char *NSStringNonFragileABISection = 2051314564Sdim "__DATA,__objc_stringobj,regular,no_dead_strip"; 2052314564Sdim // FIXME. Fix section. 2053314564Sdim GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile() 2054314564Sdim ? NSStringNonFragileABISection 2055314564Sdim : NSStringSection); 2056314564Sdim Entry.second = GV; 2057314564Sdim 2058314564Sdim return ConstantAddress(GV, Alignment); 2059314564Sdim} 2060314564Sdim 2061234353Sdimenum { 2062234353Sdim kCFTaggedObjectID_Integer = (1 << 1) + 1 2063234353Sdim}; 2064234353Sdim 2065193326Sed/// Generates a message send where the super is the receiver. This is 2066193326Sed/// a message send to self with special delivery semantics indicating 2067193326Sed/// which class's method should be called. 2068193326SedCodeGen::RValue 2069193326SedCGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 2070208600Srdivacky ReturnValueSlot Return, 2071193326Sed QualType ResultType, 2072193326Sed Selector Sel, 2073193326Sed const ObjCInterfaceDecl *Class, 2074193326Sed bool isCategoryImpl, 2075193326Sed llvm::Value *Receiver, 2076193326Sed bool IsClassMessage, 2077198092Srdivacky const CodeGen::CallArgList &CallArgs, 2078198092Srdivacky const ObjCMethodDecl *Method) { 2079193326Sed // Create and init a super structure; this is a (receiver, class) 2080193326Sed // pair we will pass to objc_msgSendSuper. 2081296417Sdim Address ObjCSuper = 2082296417Sdim CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), 2083296417Sdim "objc_super"); 2084198092Srdivacky llvm::Value *ReceiverAsObject = 2085193326Sed CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); 2086353358Sdim CGF.Builder.CreateStore(ReceiverAsObject, 2087353358Sdim CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 2088193326Sed 2089193326Sed // If this is a class message the metaclass is passed as the target. 2090193326Sed llvm::Value *Target; 2091193326Sed if (IsClassMessage) { 2092193326Sed if (isCategoryImpl) { 2093193326Sed // Message sent to 'super' in a class method defined in a category 2094193326Sed // implementation requires an odd treatment. 2095193326Sed // If we are in a class method, we must retrieve the 2096193326Sed // _metaclass_ for the current class, pointed at by 2097193326Sed // the class's "isa" pointer. The following assumes that 2098193326Sed // isa" is the first ivar in a class (which it must be). 2099249423Sdim Target = EmitClassRef(CGF, Class->getSuperClass()); 2100288943Sdim Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0); 2101296417Sdim Target = CGF.Builder.CreateAlignedLoad(Target, CGF.getPointerAlign()); 2102198092Srdivacky } else { 2103288943Sdim llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class); 2104288943Sdim llvm::Value *SuperPtr = 2105288943Sdim CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1); 2106296417Sdim llvm::Value *Super = 2107296417Sdim CGF.Builder.CreateAlignedLoad(SuperPtr, CGF.getPointerAlign()); 2108193326Sed Target = Super; 2109198092Srdivacky } 2110288943Sdim } else if (isCategoryImpl) 2111249423Sdim Target = EmitClassRef(CGF, Class->getSuperClass()); 2112199482Srdivacky else { 2113199482Srdivacky llvm::Value *ClassPtr = EmitSuperClassRef(Class); 2114288943Sdim ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1); 2115296417Sdim Target = CGF.Builder.CreateAlignedLoad(ClassPtr, CGF.getPointerAlign()); 2116193326Sed } 2117193326Sed // FIXME: We shouldn't need to do this cast, rectify the ASTContext and 2118193326Sed // ObjCTypes types. 2119226633Sdim llvm::Type *ClassTy = 2120193326Sed CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); 2121193326Sed Target = CGF.Builder.CreateBitCast(Target, ClassTy); 2122353358Sdim CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 2123360784Sdim return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.getPointer(), 2124360784Sdim ObjCTypes.SuperPtrCTy, true, CallArgs, Method, Class, 2125360784Sdim ObjCTypes); 2126193326Sed} 2127198092Srdivacky 2128198092Srdivacky/// Generate code for a message send expression. 2129193326SedCodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 2130208600Srdivacky ReturnValueSlot Return, 2131193326Sed QualType ResultType, 2132193326Sed Selector Sel, 2133193326Sed llvm::Value *Receiver, 2134193326Sed const CallArgList &CallArgs, 2135207619Srdivacky const ObjCInterfaceDecl *Class, 2136193326Sed const ObjCMethodDecl *Method) { 2137360784Sdim return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver, 2138360784Sdim CGF.getContext().getObjCIdType(), false, CallArgs, 2139360784Sdim Method, Class, ObjCTypes); 2140193326Sed} 2141193326Sed 2142296417Sdimstatic bool isWeakLinkedClass(const ObjCInterfaceDecl *ID) { 2143296417Sdim do { 2144296417Sdim if (ID->isWeakImported()) 2145296417Sdim return true; 2146296417Sdim } while ((ID = ID->getSuperClass())); 2147296417Sdim 2148296417Sdim return false; 2149296417Sdim} 2150296417Sdim 2151198092SrdivackyCodeGen::RValue 2152223017SdimCGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, 2153223017Sdim ReturnValueSlot Return, 2154223017Sdim QualType ResultType, 2155360784Sdim Selector Sel, 2156223017Sdim llvm::Value *Arg0, 2157223017Sdim QualType Arg0Ty, 2158223017Sdim bool IsSuper, 2159223017Sdim const CallArgList &CallArgs, 2160223017Sdim const ObjCMethodDecl *Method, 2161296417Sdim const ObjCInterfaceDecl *ClassReceiver, 2162223017Sdim const ObjCCommonTypesHelper &ObjCTypes) { 2163360784Sdim CodeGenTypes &Types = CGM.getTypes(); 2164360784Sdim auto selTy = CGF.getContext().getObjCSelType(); 2165360784Sdim llvm::Value *SelValue; 2166360784Sdim 2167360784Sdim if (Method && Method->isDirectMethod()) { 2168360784Sdim // Direct methods will synthesize the proper `_cmd` internally, 2169360784Sdim // so just don't bother with setting the `_cmd` argument. 2170360784Sdim assert(!IsSuper); 2171360784Sdim SelValue = llvm::UndefValue::get(Types.ConvertType(selTy)); 2172360784Sdim } else { 2173360784Sdim SelValue = GetSelector(CGF, Sel); 2174360784Sdim } 2175360784Sdim 2176193326Sed CallArgList ActualArgs; 2177193326Sed if (!IsSuper) 2178226633Sdim Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy); 2179221345Sdim ActualArgs.add(RValue::get(Arg0), Arg0Ty); 2180360784Sdim ActualArgs.add(RValue::get(SelValue), selTy); 2181224145Sdim ActualArgs.addFrom(CallArgs); 2182198092Srdivacky 2183234353Sdim // If we're calling a method, use the formal signature. 2184234353Sdim MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs); 2185198092Srdivacky 2186210299Sed if (Method) 2187276479Sdim assert(CGM.getContext().getCanonicalType(Method->getReturnType()) == 2188276479Sdim CGM.getContext().getCanonicalType(ResultType) && 2189210299Sed "Result type mismatch!"); 2190210299Sed 2191296417Sdim bool ReceiverCanBeNull = true; 2192296417Sdim 2193296417Sdim // Super dispatch assumes that self is non-null; even the messenger 2194296417Sdim // doesn't have a null check internally. 2195296417Sdim if (IsSuper) { 2196296417Sdim ReceiverCanBeNull = false; 2197296417Sdim 2198296417Sdim // If this is a direct dispatch of a class method, check whether the class, 2199296417Sdim // or anything in its hierarchy, was weak-linked. 2200296417Sdim } else if (ClassReceiver && Method && Method->isClassMethod()) { 2201296417Sdim ReceiverCanBeNull = isWeakLinkedClass(ClassReceiver); 2202296417Sdim 2203296417Sdim // If we're emitting a method, and self is const (meaning just ARC, for now), 2204296417Sdim // and the receiver is a load of self, then self is a valid object. 2205296417Sdim } else if (auto CurMethod = 2206296417Sdim dyn_cast_or_null<ObjCMethodDecl>(CGF.CurCodeDecl)) { 2207296417Sdim auto Self = CurMethod->getSelfDecl(); 2208296417Sdim if (Self->getType().isConstQualified()) { 2209296417Sdim if (auto LI = dyn_cast<llvm::LoadInst>(Arg0->stripPointerCasts())) { 2210296417Sdim llvm::Value *SelfAddr = CGF.GetAddrOfLocalVar(Self).getPointer(); 2211296417Sdim if (SelfAddr == LI->getPointerOperand()) { 2212296417Sdim ReceiverCanBeNull = false; 2213296417Sdim } 2214296417Sdim } 2215296417Sdim } 2216296417Sdim } 2217296417Sdim 2218321369Sdim bool RequiresNullCheck = false; 2219223017Sdim 2220353358Sdim llvm::FunctionCallee Fn = nullptr; 2221360784Sdim if (Method && Method->isDirectMethod()) { 2222360784Sdim Fn = GenerateDirectMethod(Method, Method->getClassInterface()); 2223360784Sdim } else if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) { 2224321369Sdim if (ReceiverCanBeNull) RequiresNullCheck = true; 2225193326Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) 2226198092Srdivacky : ObjCTypes.getSendStretFn(IsSuper); 2227210299Sed } else if (CGM.ReturnTypeUsesFPRet(ResultType)) { 2228210299Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper) 2229210299Sed : ObjCTypes.getSendFpretFn(IsSuper); 2230234353Sdim } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) { 2231234353Sdim Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper) 2232234353Sdim : ObjCTypes.getSendFp2retFn(IsSuper); 2233193326Sed } else { 2234276479Sdim // arm64 uses objc_msgSend for stret methods and yet null receiver check 2235276479Sdim // must be made for it. 2236296417Sdim if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo)) 2237321369Sdim RequiresNullCheck = true; 2238193326Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper) 2239198092Srdivacky : ObjCTypes.getSendFn(IsSuper); 2240193326Sed } 2241296417Sdim 2242353358Sdim // Cast function to proper signature 2243353358Sdim llvm::Constant *BitcastFn = cast<llvm::Constant>( 2244353358Sdim CGF.Builder.CreateBitCast(Fn.getCallee(), MSI.MessengerType)); 2245353358Sdim 2246321369Sdim // We don't need to emit a null check to zero out an indirect result if the 2247321369Sdim // result is ignored. 2248321369Sdim if (Return.isUnused()) 2249321369Sdim RequiresNullCheck = false; 2250321369Sdim 2251296417Sdim // Emit a null-check if there's a consumed argument other than the receiver. 2252321369Sdim if (!RequiresNullCheck && CGM.getLangOpts().ObjCAutoRefCount && Method) { 2253309124Sdim for (const auto *ParamDecl : Method->parameters()) { 2254234353Sdim if (ParamDecl->hasAttr<NSConsumedAttr>()) { 2255296417Sdim RequiresNullCheck = true; 2256234353Sdim break; 2257234353Sdim } 2258234353Sdim } 2259296417Sdim } 2260321369Sdim 2261321369Sdim NullReturnState nullReturn; 2262321369Sdim if (RequiresNullCheck) { 2263321369Sdim nullReturn.init(CGF, Arg0); 2264321369Sdim } 2265341825Sdim 2266353358Sdim llvm::CallBase *CallSite; 2267353358Sdim CGCallee Callee = CGCallee::forDirect(BitcastFn); 2268314564Sdim RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, 2269314564Sdim &CallSite); 2270296417Sdim 2271296417Sdim // Mark the call as noreturn if the method is marked noreturn and the 2272296417Sdim // receiver cannot be null. 2273296417Sdim if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) { 2274353358Sdim CallSite->setDoesNotReturn(); 2275296417Sdim } 2276296417Sdim 2277321369Sdim return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs, 2278296417Sdim RequiresNullCheck ? Method : nullptr); 2279193326Sed} 2280193326Sed 2281296417Sdimstatic Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT, 2282296417Sdim bool pointee = false) { 2283296417Sdim // Note that GC qualification applies recursively to C pointer types 2284296417Sdim // that aren't otherwise decorated. This is weird, but it's probably 2285296417Sdim // an intentional workaround to the unreliable placement of GC qualifiers. 2286212904Sdim if (FQT.isObjCGCStrong()) 2287212904Sdim return Qualifiers::Strong; 2288296417Sdim 2289296417Sdim if (FQT.isObjCGCWeak()) 2290212904Sdim return Qualifiers::Weak; 2291296417Sdim 2292296417Sdim if (auto ownership = FQT.getObjCLifetime()) { 2293296417Sdim // Ownership does not apply recursively to C pointer types. 2294296417Sdim if (pointee) return Qualifiers::GCNone; 2295296417Sdim switch (ownership) { 2296296417Sdim case Qualifiers::OCL_Weak: return Qualifiers::Weak; 2297296417Sdim case Qualifiers::OCL_Strong: return Qualifiers::Strong; 2298296417Sdim case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone; 2299296417Sdim case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?"); 2300296417Sdim case Qualifiers::OCL_None: llvm_unreachable("known nonzero"); 2301296417Sdim } 2302296417Sdim llvm_unreachable("bad objc ownership"); 2303296417Sdim } 2304341825Sdim 2305296417Sdim // Treat unqualified retainable pointers as strong. 2306212904Sdim if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) 2307212904Sdim return Qualifiers::Strong; 2308341825Sdim 2309296417Sdim // Walk into C pointer types, but only in GC. 2310296417Sdim if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) { 2311296417Sdim if (const PointerType *PT = FQT->getAs<PointerType>()) 2312296417Sdim return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true); 2313296417Sdim } 2314341825Sdim 2315212904Sdim return Qualifiers::GCNone; 2316212904Sdim} 2317212904Sdim 2318296417Sdimnamespace { 2319296417Sdim struct IvarInfo { 2320296417Sdim CharUnits Offset; 2321296417Sdim uint64_t SizeInWords; 2322296417Sdim IvarInfo(CharUnits offset, uint64_t sizeInWords) 2323296417Sdim : Offset(offset), SizeInWords(sizeInWords) {} 2324296417Sdim 2325296417Sdim // Allow sorting based on byte pos. 2326296417Sdim bool operator<(const IvarInfo &other) const { 2327296417Sdim return Offset < other.Offset; 2328296417Sdim } 2329296417Sdim }; 2330296417Sdim 2331296417Sdim /// A helper class for building GC layout strings. 2332296417Sdim class IvarLayoutBuilder { 2333296417Sdim CodeGenModule &CGM; 2334296417Sdim 2335296417Sdim /// The start of the layout. Offsets will be relative to this value, 2336296417Sdim /// and entries less than this value will be silently discarded. 2337296417Sdim CharUnits InstanceBegin; 2338296417Sdim 2339296417Sdim /// The end of the layout. Offsets will never exceed this value. 2340296417Sdim CharUnits InstanceEnd; 2341296417Sdim 2342296417Sdim /// Whether we're generating the strong layout or the weak layout. 2343296417Sdim bool ForStrongLayout; 2344296417Sdim 2345296417Sdim /// Whether the offsets in IvarsInfo might be out-of-order. 2346296417Sdim bool IsDisordered = false; 2347296417Sdim 2348296417Sdim llvm::SmallVector<IvarInfo, 8> IvarsInfo; 2349309124Sdim 2350296417Sdim public: 2351296417Sdim IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin, 2352296417Sdim CharUnits instanceEnd, bool forStrongLayout) 2353296417Sdim : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd), 2354296417Sdim ForStrongLayout(forStrongLayout) { 2355296417Sdim } 2356296417Sdim 2357296417Sdim void visitRecord(const RecordType *RT, CharUnits offset); 2358296417Sdim 2359296417Sdim template <class Iterator, class GetOffsetFn> 2360341825Sdim void visitAggregate(Iterator begin, Iterator end, 2361296417Sdim CharUnits aggrOffset, 2362296417Sdim const GetOffsetFn &getOffset); 2363296417Sdim 2364296417Sdim void visitField(const FieldDecl *field, CharUnits offset); 2365296417Sdim 2366296417Sdim /// Add the layout of a block implementation. 2367296417Sdim void visitBlock(const CGBlockInfo &blockInfo); 2368296417Sdim 2369296417Sdim /// Is there any information for an interesting bitmap? 2370296417Sdim bool hasBitmapData() const { return !IvarsInfo.empty(); } 2371296417Sdim 2372296417Sdim llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC, 2373296417Sdim llvm::SmallVectorImpl<unsigned char> &buffer); 2374296417Sdim 2375296417Sdim static void dump(ArrayRef<unsigned char> buffer) { 2376296417Sdim const unsigned char *s = buffer.data(); 2377296417Sdim for (unsigned i = 0, e = buffer.size(); i < e; i++) 2378296417Sdim if (!(s[i] & 0xf0)) 2379296417Sdim printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); 2380296417Sdim else 2381296417Sdim printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); 2382296417Sdim printf("\n"); 2383296417Sdim } 2384296417Sdim }; 2385309124Sdim} // end anonymous namespace 2386296417Sdim 2387218893Sdimllvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, 2388218893Sdim const CGBlockInfo &blockInfo) { 2389341825Sdim 2390234353Sdim llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); 2391296417Sdim if (CGM.getLangOpts().getGC() == LangOptions::NonGC) 2392218893Sdim return nullPtr; 2393218893Sdim 2394296417Sdim IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize, 2395296417Sdim /*for strong layout*/ true); 2396296417Sdim 2397296417Sdim builder.visitBlock(blockInfo); 2398296417Sdim 2399296417Sdim if (!builder.hasBitmapData()) 2400296417Sdim return nullPtr; 2401296417Sdim 2402296417Sdim llvm::SmallVector<unsigned char, 32> buffer; 2403296417Sdim llvm::Constant *C = builder.buildBitmap(*this, buffer); 2404296417Sdim if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) { 2405296417Sdim printf("\n block variable layout for block: "); 2406296417Sdim builder.dump(buffer); 2407296417Sdim } 2408341825Sdim 2409296417Sdim return C; 2410296417Sdim} 2411296417Sdim 2412296417Sdimvoid IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) { 2413218893Sdim // __isa is the first field in block descriptor and must assume by runtime's 2414218893Sdim // convention that it is GC'able. 2415296417Sdim IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1)); 2416218893Sdim 2417218893Sdim const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 2418218893Sdim 2419218893Sdim // Ignore the optional 'this' capture: C++ objects are not assumed 2420218893Sdim // to be GC'ed. 2421218893Sdim 2422296417Sdim CharUnits lastFieldOffset; 2423296417Sdim 2424218893Sdim // Walk the captured variables. 2425276479Sdim for (const auto &CI : blockDecl->captures()) { 2426276479Sdim const VarDecl *variable = CI.getVariable(); 2427218893Sdim QualType type = variable->getType(); 2428218893Sdim 2429218893Sdim const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 2430218893Sdim 2431218893Sdim // Ignore constant captures. 2432218893Sdim if (capture.isConstant()) continue; 2433218893Sdim 2434296417Sdim CharUnits fieldOffset = capture.getOffset(); 2435218893Sdim 2436296417Sdim // Block fields are not necessarily ordered; if we detect that we're 2437296417Sdim // adding them out-of-order, make sure we sort later. 2438296417Sdim if (fieldOffset < lastFieldOffset) 2439296417Sdim IsDisordered = true; 2440296417Sdim lastFieldOffset = fieldOffset; 2441296417Sdim 2442218893Sdim // __block variables are passed by their descriptor address. 2443276479Sdim if (CI.isByRef()) { 2444296417Sdim IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1)); 2445212904Sdim continue; 2446212904Sdim } 2447218893Sdim 2448218893Sdim assert(!type->isArrayType() && "array variable should not be caught"); 2449218893Sdim if (const RecordType *record = type->getAs<RecordType>()) { 2450296417Sdim visitRecord(record, fieldOffset); 2451218893Sdim continue; 2452218893Sdim } 2453341825Sdim 2454218893Sdim Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type); 2455218893Sdim 2456296417Sdim if (GCAttr == Qualifiers::Strong) { 2457296417Sdim assert(CGM.getContext().getTypeSize(type) 2458296417Sdim == CGM.getTarget().getPointerWidth(0)); 2459296417Sdim IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1)); 2460296417Sdim } 2461212904Sdim } 2462212904Sdim} 2463212904Sdim 2464243830Sdim/// getBlockCaptureLifetime - This routine returns life time of the captured 2465243830Sdim/// block variable for the purpose of block layout meta-data generation. FQT is 2466243830Sdim/// the type of the variable captured in the block. 2467249423SdimQualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT, 2468249423Sdim bool ByrefLayout) { 2469296417Sdim // If it has an ownership qualifier, we're done. 2470296417Sdim if (auto lifetime = FQT.getObjCLifetime()) 2471296417Sdim return lifetime; 2472296417Sdim 2473296417Sdim // If it doesn't, and this is ARC, it has no ownership. 2474243830Sdim if (CGM.getLangOpts().ObjCAutoRefCount) 2475296417Sdim return Qualifiers::OCL_None; 2476341825Sdim 2477296417Sdim // In MRC, retainable pointers are owned by non-__block variables. 2478243830Sdim if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) 2479249423Sdim return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong; 2480341825Sdim 2481243830Sdim return Qualifiers::OCL_None; 2482243830Sdim} 2483243830Sdim 2484243830Sdimvoid CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref, 2485243830Sdim Qualifiers::ObjCLifetime LifeTime, 2486243830Sdim CharUnits FieldOffset, 2487243830Sdim CharUnits FieldSize) { 2488243830Sdim // __block variables are passed by their descriptor address. 2489243830Sdim if (IsByref) 2490243830Sdim RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, 2491243830Sdim FieldSize)); 2492243830Sdim else if (LifeTime == Qualifiers::OCL_Strong) 2493243830Sdim RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, 2494243830Sdim FieldSize)); 2495243830Sdim else if (LifeTime == Qualifiers::OCL_Weak) 2496243830Sdim RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, 2497243830Sdim FieldSize)); 2498243830Sdim else if (LifeTime == Qualifiers::OCL_ExplicitNone) 2499243830Sdim RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, 2500243830Sdim FieldSize)); 2501243830Sdim else 2502243830Sdim RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, 2503243830Sdim FieldOffset, 2504243830Sdim FieldSize)); 2505243830Sdim} 2506243830Sdim 2507243830Sdimvoid CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, 2508243830Sdim const RecordDecl *RD, 2509243830Sdim ArrayRef<const FieldDecl*> RecFields, 2510249423Sdim CharUnits BytePos, bool &HasUnion, 2511249423Sdim bool ByrefLayout) { 2512243830Sdim bool IsUnion = (RD && RD->isUnion()); 2513243830Sdim CharUnits MaxUnionSize = CharUnits::Zero(); 2514276479Sdim const FieldDecl *MaxField = nullptr; 2515276479Sdim const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr; 2516243830Sdim CharUnits MaxFieldOffset = CharUnits::Zero(); 2517243830Sdim CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero(); 2518341825Sdim 2519243830Sdim if (RecFields.empty()) 2520243830Sdim return; 2521251662Sdim unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); 2522341825Sdim 2523243830Sdim for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { 2524243830Sdim const FieldDecl *Field = RecFields[i]; 2525243830Sdim // Note that 'i' here is actually the field index inside RD of Field, 2526243830Sdim // although this dependency is hidden. 2527243830Sdim const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); 2528243830Sdim CharUnits FieldOffset = 2529243830Sdim CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i)); 2530341825Sdim 2531243830Sdim // Skip over unnamed or bitfields 2532243830Sdim if (!Field->getIdentifier() || Field->isBitField()) { 2533243830Sdim LastFieldBitfieldOrUnnamed = Field; 2534243830Sdim LastBitfieldOrUnnamedOffset = FieldOffset; 2535243830Sdim continue; 2536243830Sdim } 2537276479Sdim 2538276479Sdim LastFieldBitfieldOrUnnamed = nullptr; 2539243830Sdim QualType FQT = Field->getType(); 2540243830Sdim if (FQT->isRecordType() || FQT->isUnionType()) { 2541243830Sdim if (FQT->isUnionType()) 2542243830Sdim HasUnion = true; 2543341825Sdim 2544243830Sdim BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(), 2545243830Sdim BytePos + FieldOffset, HasUnion); 2546243830Sdim continue; 2547243830Sdim } 2548341825Sdim 2549243830Sdim if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 2550360784Sdim auto *CArray = cast<ConstantArrayType>(Array); 2551243830Sdim uint64_t ElCount = CArray->getSize().getZExtValue(); 2552243830Sdim assert(CArray && "only array with known element size is supported"); 2553243830Sdim FQT = CArray->getElementType(); 2554243830Sdim while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 2555360784Sdim auto *CArray = cast<ConstantArrayType>(Array); 2556243830Sdim ElCount *= CArray->getSize().getZExtValue(); 2557243830Sdim FQT = CArray->getElementType(); 2558243830Sdim } 2559243830Sdim if (FQT->isRecordType() && ElCount) { 2560243830Sdim int OldIndex = RunSkipBlockVars.size() - 1; 2561243830Sdim const RecordType *RT = FQT->getAs<RecordType>(); 2562243830Sdim BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, 2563243830Sdim HasUnion); 2564341825Sdim 2565243830Sdim // Replicate layout information for each array element. Note that 2566243830Sdim // one element is already done. 2567243830Sdim uint64_t ElIx = 1; 2568243830Sdim for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) { 2569243830Sdim CharUnits Size = CGM.getContext().getTypeSizeInChars(RT); 2570243830Sdim for (int i = OldIndex+1; i <= FirstIndex; ++i) 2571243830Sdim RunSkipBlockVars.push_back( 2572243830Sdim RUN_SKIP(RunSkipBlockVars[i].opcode, 2573243830Sdim RunSkipBlockVars[i].block_var_bytepos + Size*ElIx, 2574243830Sdim RunSkipBlockVars[i].block_var_size)); 2575243830Sdim } 2576243830Sdim continue; 2577243830Sdim } 2578243830Sdim } 2579243830Sdim CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType()); 2580243830Sdim if (IsUnion) { 2581243830Sdim CharUnits UnionIvarSize = FieldSize; 2582243830Sdim if (UnionIvarSize > MaxUnionSize) { 2583243830Sdim MaxUnionSize = UnionIvarSize; 2584243830Sdim MaxField = Field; 2585243830Sdim MaxFieldOffset = FieldOffset; 2586243830Sdim } 2587243830Sdim } else { 2588243830Sdim UpdateRunSkipBlockVars(false, 2589249423Sdim getBlockCaptureLifetime(FQT, ByrefLayout), 2590243830Sdim BytePos + FieldOffset, 2591243830Sdim FieldSize); 2592243830Sdim } 2593243830Sdim } 2594341825Sdim 2595243830Sdim if (LastFieldBitfieldOrUnnamed) { 2596243830Sdim if (LastFieldBitfieldOrUnnamed->isBitField()) { 2597243830Sdim // Last field was a bitfield. Must update the info. 2598243830Sdim uint64_t BitFieldSize 2599243830Sdim = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext()); 2600243830Sdim unsigned UnsSize = (BitFieldSize / ByteSizeInBits) + 2601243830Sdim ((BitFieldSize % ByteSizeInBits) != 0); 2602243830Sdim CharUnits Size = CharUnits::fromQuantity(UnsSize); 2603243830Sdim Size += LastBitfieldOrUnnamedOffset; 2604243830Sdim UpdateRunSkipBlockVars(false, 2605249423Sdim getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(), 2606249423Sdim ByrefLayout), 2607243830Sdim BytePos + LastBitfieldOrUnnamedOffset, 2608243830Sdim Size); 2609243830Sdim } else { 2610243830Sdim assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed"); 2611243830Sdim // Last field was unnamed. Must update skip info. 2612243830Sdim CharUnits FieldSize 2613243830Sdim = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType()); 2614243830Sdim UpdateRunSkipBlockVars(false, 2615249423Sdim getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(), 2616249423Sdim ByrefLayout), 2617243830Sdim BytePos + LastBitfieldOrUnnamedOffset, 2618243830Sdim FieldSize); 2619243830Sdim } 2620243830Sdim } 2621341825Sdim 2622243830Sdim if (MaxField) 2623243830Sdim UpdateRunSkipBlockVars(false, 2624249423Sdim getBlockCaptureLifetime(MaxField->getType(), ByrefLayout), 2625243830Sdim BytePos + MaxFieldOffset, 2626243830Sdim MaxUnionSize); 2627243830Sdim} 2628243830Sdim 2629243830Sdimvoid CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT, 2630243830Sdim CharUnits BytePos, 2631249423Sdim bool &HasUnion, 2632249423Sdim bool ByrefLayout) { 2633243830Sdim const RecordDecl *RD = RT->getDecl(); 2634276479Sdim SmallVector<const FieldDecl*, 16> Fields(RD->fields()); 2635243830Sdim llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); 2636243830Sdim const llvm::StructLayout *RecLayout = 2637243830Sdim CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty)); 2638341825Sdim 2639249423Sdim BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout); 2640243830Sdim} 2641243830Sdim 2642243830Sdim/// InlineLayoutInstruction - This routine produce an inline instruction for the 2643243830Sdim/// block variable layout if it can. If not, it returns 0. Rules are as follow: 2644243830Sdim/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world, 2645243830Sdim/// an inline layout of value 0x0000000000000xyz is interpreted as follows: 2646243830Sdim/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by 2647243830Sdim/// y captured object of BLOCK_LAYOUT_BYREF. Followed by 2648243830Sdim/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero 2649243830Sdim/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no 2650243830Sdim/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured. 2651243830Sdimuint64_t CGObjCCommonMac::InlineLayoutInstruction( 2652243830Sdim SmallVectorImpl<unsigned char> &Layout) { 2653243830Sdim uint64_t Result = 0; 2654243830Sdim if (Layout.size() <= 3) { 2655243830Sdim unsigned size = Layout.size(); 2656243830Sdim unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0; 2657243830Sdim unsigned char inst; 2658243830Sdim enum BLOCK_LAYOUT_OPCODE opcode ; 2659243830Sdim switch (size) { 2660243830Sdim case 3: 2661243830Sdim inst = Layout[0]; 2662243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2663243830Sdim if (opcode == BLOCK_LAYOUT_STRONG) 2664243830Sdim strong_word_count = (inst & 0xF)+1; 2665243830Sdim else 2666243830Sdim return 0; 2667243830Sdim inst = Layout[1]; 2668243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2669243830Sdim if (opcode == BLOCK_LAYOUT_BYREF) 2670243830Sdim byref_word_count = (inst & 0xF)+1; 2671243830Sdim else 2672243830Sdim return 0; 2673243830Sdim inst = Layout[2]; 2674243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2675243830Sdim if (opcode == BLOCK_LAYOUT_WEAK) 2676243830Sdim weak_word_count = (inst & 0xF)+1; 2677243830Sdim else 2678243830Sdim return 0; 2679243830Sdim break; 2680341825Sdim 2681243830Sdim case 2: 2682243830Sdim inst = Layout[0]; 2683243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2684243830Sdim if (opcode == BLOCK_LAYOUT_STRONG) { 2685243830Sdim strong_word_count = (inst & 0xF)+1; 2686243830Sdim inst = Layout[1]; 2687243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2688243830Sdim if (opcode == BLOCK_LAYOUT_BYREF) 2689243830Sdim byref_word_count = (inst & 0xF)+1; 2690243830Sdim else if (opcode == BLOCK_LAYOUT_WEAK) 2691243830Sdim weak_word_count = (inst & 0xF)+1; 2692243830Sdim else 2693243830Sdim return 0; 2694243830Sdim } 2695243830Sdim else if (opcode == BLOCK_LAYOUT_BYREF) { 2696243830Sdim byref_word_count = (inst & 0xF)+1; 2697243830Sdim inst = Layout[1]; 2698243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2699243830Sdim if (opcode == BLOCK_LAYOUT_WEAK) 2700243830Sdim weak_word_count = (inst & 0xF)+1; 2701243830Sdim else 2702243830Sdim return 0; 2703243830Sdim } 2704243830Sdim else 2705243830Sdim return 0; 2706243830Sdim break; 2707341825Sdim 2708243830Sdim case 1: 2709243830Sdim inst = Layout[0]; 2710243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2711243830Sdim if (opcode == BLOCK_LAYOUT_STRONG) 2712243830Sdim strong_word_count = (inst & 0xF)+1; 2713243830Sdim else if (opcode == BLOCK_LAYOUT_BYREF) 2714243830Sdim byref_word_count = (inst & 0xF)+1; 2715243830Sdim else if (opcode == BLOCK_LAYOUT_WEAK) 2716243830Sdim weak_word_count = (inst & 0xF)+1; 2717243830Sdim else 2718243830Sdim return 0; 2719243830Sdim break; 2720341825Sdim 2721243830Sdim default: 2722243830Sdim return 0; 2723243830Sdim } 2724341825Sdim 2725243830Sdim // Cannot inline when any of the word counts is 15. Because this is one less 2726243830Sdim // than the actual work count (so 15 means 16 actual word counts), 2727243830Sdim // and we can only display 0 thru 15 word counts. 2728243830Sdim if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16) 2729243830Sdim return 0; 2730341825Sdim 2731243830Sdim unsigned count = 2732243830Sdim (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0); 2733341825Sdim 2734243830Sdim if (size == count) { 2735243830Sdim if (strong_word_count) 2736243830Sdim Result = strong_word_count; 2737243830Sdim Result <<= 4; 2738243830Sdim if (byref_word_count) 2739243830Sdim Result += byref_word_count; 2740243830Sdim Result <<= 4; 2741243830Sdim if (weak_word_count) 2742243830Sdim Result += weak_word_count; 2743243830Sdim } 2744243830Sdim } 2745243830Sdim return Result; 2746243830Sdim} 2747243830Sdim 2748249423Sdimllvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) { 2749243830Sdim llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); 2750249423Sdim if (RunSkipBlockVars.empty()) 2751249423Sdim return nullPtr; 2752251662Sdim unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); 2753251662Sdim unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); 2754243830Sdim unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; 2755341825Sdim 2756243830Sdim // Sort on byte position; captures might not be allocated in order, 2757243830Sdim // and unions can do funny things. 2758243830Sdim llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end()); 2759243830Sdim SmallVector<unsigned char, 16> Layout; 2760341825Sdim 2761243830Sdim unsigned size = RunSkipBlockVars.size(); 2762243830Sdim for (unsigned i = 0; i < size; i++) { 2763243830Sdim enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode; 2764243830Sdim CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos; 2765243830Sdim CharUnits end_byte_pos = start_byte_pos; 2766243830Sdim unsigned j = i+1; 2767243830Sdim while (j < size) { 2768243830Sdim if (opcode == RunSkipBlockVars[j].opcode) { 2769243830Sdim end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos; 2770243830Sdim i++; 2771243830Sdim } 2772243830Sdim else 2773243830Sdim break; 2774243830Sdim } 2775243830Sdim CharUnits size_in_bytes = 2776249423Sdim end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size; 2777243830Sdim if (j < size) { 2778243830Sdim CharUnits gap = 2779249423Sdim RunSkipBlockVars[j].block_var_bytepos - 2780249423Sdim RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size; 2781243830Sdim size_in_bytes += gap; 2782243830Sdim } 2783243830Sdim CharUnits residue_in_bytes = CharUnits::Zero(); 2784243830Sdim if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) { 2785243830Sdim residue_in_bytes = size_in_bytes % WordSizeInBytes; 2786243830Sdim size_in_bytes -= residue_in_bytes; 2787243830Sdim opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS; 2788243830Sdim } 2789341825Sdim 2790243830Sdim unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes; 2791243830Sdim while (size_in_words >= 16) { 2792243830Sdim // Note that value in imm. is one less that the actual 2793243830Sdim // value. So, 0xf means 16 words follow! 2794243830Sdim unsigned char inst = (opcode << 4) | 0xf; 2795243830Sdim Layout.push_back(inst); 2796243830Sdim size_in_words -= 16; 2797243830Sdim } 2798243830Sdim if (size_in_words > 0) { 2799243830Sdim // Note that value in imm. is one less that the actual 2800243830Sdim // value. So, we subtract 1 away! 2801243830Sdim unsigned char inst = (opcode << 4) | (size_in_words-1); 2802243830Sdim Layout.push_back(inst); 2803243830Sdim } 2804243830Sdim if (residue_in_bytes > CharUnits::Zero()) { 2805243830Sdim unsigned char inst = 2806249423Sdim (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1); 2807243830Sdim Layout.push_back(inst); 2808243830Sdim } 2809243830Sdim } 2810341825Sdim 2811296417Sdim while (!Layout.empty()) { 2812296417Sdim unsigned char inst = Layout.back(); 2813243830Sdim enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2814243830Sdim if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS) 2815243830Sdim Layout.pop_back(); 2816243830Sdim else 2817243830Sdim break; 2818243830Sdim } 2819341825Sdim 2820243830Sdim uint64_t Result = InlineLayoutInstruction(Layout); 2821243830Sdim if (Result != 0) { 2822243830Sdim // Block variable layout instruction has been inlined. 2823243830Sdim if (CGM.getLangOpts().ObjCGCBitmapPrint) { 2824249423Sdim if (ComputeByrefLayout) 2825296417Sdim printf("\n Inline BYREF variable layout: "); 2826249423Sdim else 2827296417Sdim printf("\n Inline block variable layout: "); 2828296417Sdim printf("0x0%" PRIx64 "", Result); 2829296417Sdim if (auto numStrong = (Result & 0xF00) >> 8) 2830296417Sdim printf(", BL_STRONG:%d", (int) numStrong); 2831296417Sdim if (auto numByref = (Result & 0x0F0) >> 4) 2832296417Sdim printf(", BL_BYREF:%d", (int) numByref); 2833296417Sdim if (auto numWeak = (Result & 0x00F) >> 0) 2834296417Sdim printf(", BL_WEAK:%d", (int) numWeak); 2835296417Sdim printf(", BL_OPERATOR:0\n"); 2836243830Sdim } 2837296417Sdim return llvm::ConstantInt::get(CGM.IntPtrTy, Result); 2838243830Sdim } 2839341825Sdim 2840243830Sdim unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0; 2841243830Sdim Layout.push_back(inst); 2842243830Sdim std::string BitMap; 2843243830Sdim for (unsigned i = 0, e = Layout.size(); i != e; i++) 2844243830Sdim BitMap += Layout[i]; 2845341825Sdim 2846243830Sdim if (CGM.getLangOpts().ObjCGCBitmapPrint) { 2847249423Sdim if (ComputeByrefLayout) 2848296417Sdim printf("\n Byref variable layout: "); 2849249423Sdim else 2850296417Sdim printf("\n Block variable layout: "); 2851243830Sdim for (unsigned i = 0, e = BitMap.size(); i != e; i++) { 2852243830Sdim unsigned char inst = BitMap[i]; 2853243830Sdim enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2854243830Sdim unsigned delta = 1; 2855243830Sdim switch (opcode) { 2856243830Sdim case BLOCK_LAYOUT_OPERATOR: 2857243830Sdim printf("BL_OPERATOR:"); 2858243830Sdim delta = 0; 2859243830Sdim break; 2860243830Sdim case BLOCK_LAYOUT_NON_OBJECT_BYTES: 2861243830Sdim printf("BL_NON_OBJECT_BYTES:"); 2862243830Sdim break; 2863243830Sdim case BLOCK_LAYOUT_NON_OBJECT_WORDS: 2864243830Sdim printf("BL_NON_OBJECT_WORD:"); 2865243830Sdim break; 2866243830Sdim case BLOCK_LAYOUT_STRONG: 2867243830Sdim printf("BL_STRONG:"); 2868243830Sdim break; 2869243830Sdim case BLOCK_LAYOUT_BYREF: 2870243830Sdim printf("BL_BYREF:"); 2871243830Sdim break; 2872243830Sdim case BLOCK_LAYOUT_WEAK: 2873243830Sdim printf("BL_WEAK:"); 2874243830Sdim break; 2875243830Sdim case BLOCK_LAYOUT_UNRETAINED: 2876243830Sdim printf("BL_UNRETAINED:"); 2877243830Sdim break; 2878249423Sdim } 2879243830Sdim // Actual value of word count is one more that what is in the imm. 2880243830Sdim // field of the instruction 2881249423Sdim printf("%d", (inst & 0xf) + delta); 2882243830Sdim if (i < e-1) 2883243830Sdim printf(", "); 2884243830Sdim else 2885243830Sdim printf("\n"); 2886243830Sdim } 2887243830Sdim } 2888280031Sdim 2889314564Sdim auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName, 2890314564Sdim /*ForceNonFragileABI=*/true, 2891314564Sdim /*NullTerminate=*/false); 2892243830Sdim return getConstantGEP(VMContext, Entry, 0, 0); 2893243830Sdim} 2894243830Sdim 2895344779Sdimstatic std::string getBlockLayoutInfoString( 2896344779Sdim const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> &RunSkipBlockVars, 2897344779Sdim bool HasCopyDisposeHelpers) { 2898344779Sdim std::string Str; 2899344779Sdim for (const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) { 2900344779Sdim if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) { 2901344779Sdim // Copy/dispose helpers don't have any information about 2902344779Sdim // __unsafe_unretained captures, so unconditionally concatenate a string. 2903344779Sdim Str += "u"; 2904344779Sdim } else if (HasCopyDisposeHelpers) { 2905344779Sdim // Information about __strong, __weak, or byref captures has already been 2906344779Sdim // encoded into the names of the copy/dispose helpers. We have to add a 2907344779Sdim // string here only when the copy/dispose helpers aren't generated (which 2908344779Sdim // happens when the block is non-escaping). 2909344779Sdim continue; 2910344779Sdim } else { 2911344779Sdim switch (R.opcode) { 2912344779Sdim case CGObjCCommonMac::BLOCK_LAYOUT_STRONG: 2913344779Sdim Str += "s"; 2914344779Sdim break; 2915344779Sdim case CGObjCCommonMac::BLOCK_LAYOUT_BYREF: 2916344779Sdim Str += "r"; 2917344779Sdim break; 2918344779Sdim case CGObjCCommonMac::BLOCK_LAYOUT_WEAK: 2919344779Sdim Str += "w"; 2920344779Sdim break; 2921344779Sdim default: 2922344779Sdim continue; 2923344779Sdim } 2924344779Sdim } 2925344779Sdim Str += llvm::to_string(R.block_var_bytepos.getQuantity()); 2926344779Sdim Str += "l" + llvm::to_string(R.block_var_size.getQuantity()); 2927344779Sdim } 2928344779Sdim return Str; 2929344779Sdim} 2930344779Sdim 2931344779Sdimvoid CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM, 2932344779Sdim const CGBlockInfo &blockInfo) { 2933249423Sdim assert(CGM.getLangOpts().getGC() == LangOptions::NonGC); 2934341825Sdim 2935249423Sdim RunSkipBlockVars.clear(); 2936249423Sdim bool hasUnion = false; 2937341825Sdim 2938251662Sdim unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); 2939251662Sdim unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); 2940249423Sdim unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; 2941341825Sdim 2942249423Sdim const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 2943341825Sdim 2944249423Sdim // Calculate the basic layout of the block structure. 2945249423Sdim const llvm::StructLayout *layout = 2946249423Sdim CGM.getDataLayout().getStructLayout(blockInfo.StructureType); 2947341825Sdim 2948249423Sdim // Ignore the optional 'this' capture: C++ objects are not assumed 2949249423Sdim // to be GC'ed. 2950249423Sdim if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero()) 2951249423Sdim UpdateRunSkipBlockVars(false, Qualifiers::OCL_None, 2952249423Sdim blockInfo.BlockHeaderForcedGapOffset, 2953249423Sdim blockInfo.BlockHeaderForcedGapSize); 2954249423Sdim // Walk the captured variables. 2955276479Sdim for (const auto &CI : blockDecl->captures()) { 2956276479Sdim const VarDecl *variable = CI.getVariable(); 2957249423Sdim QualType type = variable->getType(); 2958341825Sdim 2959249423Sdim const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 2960341825Sdim 2961249423Sdim // Ignore constant captures. 2962249423Sdim if (capture.isConstant()) continue; 2963341825Sdim 2964249423Sdim CharUnits fieldOffset = 2965249423Sdim CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex())); 2966341825Sdim 2967249423Sdim assert(!type->isArrayType() && "array variable should not be caught"); 2968276479Sdim if (!CI.isByRef()) 2969249423Sdim if (const RecordType *record = type->getAs<RecordType>()) { 2970249423Sdim BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion); 2971249423Sdim continue; 2972249423Sdim } 2973249423Sdim CharUnits fieldSize; 2974276479Sdim if (CI.isByRef()) 2975249423Sdim fieldSize = CharUnits::fromQuantity(WordSizeInBytes); 2976249423Sdim else 2977249423Sdim fieldSize = CGM.getContext().getTypeSizeInChars(type); 2978276479Sdim UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false), 2979249423Sdim fieldOffset, fieldSize); 2980249423Sdim } 2981344779Sdim} 2982344779Sdim 2983344779Sdimllvm::Constant * 2984344779SdimCGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM, 2985344779Sdim const CGBlockInfo &blockInfo) { 2986344779Sdim fillRunSkipBlockVars(CGM, blockInfo); 2987249423Sdim return getBitmapBlockLayout(false); 2988249423Sdim} 2989249423Sdim 2990344779Sdimstd::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM, 2991344779Sdim const CGBlockInfo &blockInfo) { 2992344779Sdim fillRunSkipBlockVars(CGM, blockInfo); 2993344779Sdim return getBlockLayoutInfoString(RunSkipBlockVars, 2994344779Sdim blockInfo.needsCopyDisposeHelpers()); 2995344779Sdim} 2996344779Sdim 2997249423Sdimllvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM, 2998249423Sdim QualType T) { 2999249423Sdim assert(CGM.getLangOpts().getGC() == LangOptions::NonGC); 3000249423Sdim assert(!T->isArrayType() && "__block array variable should not be caught"); 3001249423Sdim CharUnits fieldOffset; 3002249423Sdim RunSkipBlockVars.clear(); 3003249423Sdim bool hasUnion = false; 3004249423Sdim if (const RecordType *record = T->getAs<RecordType>()) { 3005249423Sdim BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */); 3006249423Sdim llvm::Constant *Result = getBitmapBlockLayout(true); 3007296417Sdim if (isa<llvm::ConstantInt>(Result)) 3008296417Sdim Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy); 3009249423Sdim return Result; 3010249423Sdim } 3011249423Sdim llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); 3012249423Sdim return nullPtr; 3013249423Sdim} 3014249423Sdim 3015249423Sdimllvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF, 3016193326Sed const ObjCProtocolDecl *PD) { 3017193326Sed // FIXME: I don't understand why gcc generates this, or where it is 3018193326Sed // resolved. Investigate. Its also wasteful to look this up over and over. 3019193326Sed LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); 3020193326Sed 3021193326Sed return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD), 3022234353Sdim ObjCTypes.getExternalProtocolPtrTy()); 3023193326Sed} 3024193326Sed 3025193326Sedvoid CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) { 3026193326Sed // FIXME: We shouldn't need this, the protocol decl should contain enough 3027193326Sed // information to tell us whether this was a declaration or a definition. 3028193326Sed DefinedProtocols.insert(PD->getIdentifier()); 3029193326Sed 3030193326Sed // If we have generated a forward reference to this protocol, emit 3031193326Sed // it now. Otherwise do nothing, the protocol objects are lazily 3032193326Sed // emitted. 3033198092Srdivacky if (Protocols.count(PD->getIdentifier())) 3034193326Sed GetOrEmitProtocol(PD); 3035193326Sed} 3036193326Sed 3037193326Sedllvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) { 3038193326Sed if (DefinedProtocols.count(PD->getIdentifier())) 3039193326Sed return GetOrEmitProtocol(PD); 3040341825Sdim 3041193326Sed return GetOrEmitProtocolRef(PD); 3042193326Sed} 3043193326Sed 3044309124Sdimllvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime( 3045309124Sdim CodeGenFunction &CGF, 3046309124Sdim const ObjCInterfaceDecl *ID, 3047309124Sdim ObjCCommonTypesHelper &ObjCTypes) { 3048353358Sdim llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn(); 3049309124Sdim 3050309124Sdim llvm::Value *className = 3051309124Sdim CGF.CGM.GetAddrOfConstantCString(ID->getObjCRuntimeNameAsString()) 3052309124Sdim .getPointer(); 3053309124Sdim ASTContext &ctx = CGF.CGM.getContext(); 3054309124Sdim className = 3055309124Sdim CGF.Builder.CreateBitCast(className, 3056309124Sdim CGF.ConvertType( 3057309124Sdim ctx.getPointerType(ctx.CharTy.withConst()))); 3058309124Sdim llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className); 3059309124Sdim call->setDoesNotThrow(); 3060309124Sdim return call; 3061309124Sdim} 3062309124Sdim 3063193326Sed/* 3064276479Sdim// Objective-C 1.0 extensions 3065198092Srdivackystruct _objc_protocol { 3066198092Srdivackystruct _objc_protocol_extension *isa; 3067198092Srdivackychar *protocol_name; 3068198092Srdivackystruct _objc_protocol_list *protocol_list; 3069198092Srdivackystruct _objc__method_prototype_list *instance_methods; 3070198092Srdivackystruct _objc__method_prototype_list *class_methods 3071198092Srdivacky}; 3072193326Sed 3073198092SrdivackySee EmitProtocolExtension(). 3074193326Sed*/ 3075193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { 3076234353Sdim llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()]; 3077193326Sed 3078193326Sed // Early exit if a defining object has already been generated. 3079193326Sed if (Entry && Entry->hasInitializer()) 3080193326Sed return Entry; 3081193326Sed 3082234353Sdim // Use the protocol definition, if there is one. 3083234353Sdim if (const ObjCProtocolDecl *Def = PD->getDefinition()) 3084234353Sdim PD = Def; 3085234353Sdim 3086193326Sed // FIXME: I don't understand why gcc generates this, or where it is 3087193326Sed // resolved. Investigate. Its also wasteful to look this up over and over. 3088193326Sed LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); 3089193326Sed 3090193326Sed // Construct method lists. 3091314564Sdim auto methodLists = ProtocolMethodLists::get(PD); 3092193326Sed 3093314564Sdim ConstantInitBuilder builder(CGM); 3094314564Sdim auto values = builder.beginStruct(ObjCTypes.ProtocolTy); 3095314564Sdim values.add(EmitProtocolExtension(PD, methodLists)); 3096314564Sdim values.add(GetClassName(PD->getObjCRuntimeNameAsString())); 3097314564Sdim values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(), 3098314564Sdim PD->protocol_begin(), PD->protocol_end())); 3099314564Sdim values.add(methodLists.emitMethodList(this, PD, 3100314564Sdim ProtocolMethodLists::RequiredInstanceMethods)); 3101314564Sdim values.add(methodLists.emitMethodList(this, PD, 3102314564Sdim ProtocolMethodLists::RequiredClassMethods)); 3103223017Sdim 3104193326Sed if (Entry) { 3105276479Sdim // Already created, update the initializer. 3106276479Sdim assert(Entry->hasPrivateLinkage()); 3107314564Sdim values.finishAndSetAsInitializer(Entry); 3108193326Sed } else { 3109314564Sdim Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(), 3110314564Sdim CGM.getPointerAlign(), 3111314564Sdim /*constant*/ false, 3112314564Sdim llvm::GlobalValue::PrivateLinkage); 3113193326Sed Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); 3114234353Sdim 3115234353Sdim Protocols[PD->getIdentifier()] = Entry; 3116193326Sed } 3117276479Sdim CGM.addCompilerUsedGlobal(Entry); 3118193326Sed 3119193326Sed return Entry; 3120193326Sed} 3121193326Sed 3122193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { 3123193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 3124193326Sed 3125193326Sed if (!Entry) { 3126193326Sed // We use the initializer as a marker of whether this is a forward 3127193326Sed // reference or not. At module finalization we add the empty 3128193326Sed // contents for protocols which were referenced but never defined. 3129280031Sdim Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, 3130280031Sdim false, llvm::GlobalValue::PrivateLinkage, 3131280031Sdim nullptr, "OBJC_PROTOCOL_" + PD->getName()); 3132193326Sed Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); 3133193326Sed // FIXME: Is this necessary? Why only for protocol? 3134360784Sdim Entry->setAlignment(llvm::Align(4)); 3135193326Sed } 3136198092Srdivacky 3137193326Sed return Entry; 3138193326Sed} 3139193326Sed 3140193326Sed/* 3141193326Sed struct _objc_protocol_extension { 3142198092Srdivacky uint32_t size; 3143198092Srdivacky struct objc_method_description_list *optional_instance_methods; 3144198092Srdivacky struct objc_method_description_list *optional_class_methods; 3145198092Srdivacky struct objc_property_list *instance_properties; 3146234353Sdim const char ** extendedMethodTypes; 3147309124Sdim struct objc_property_list *class_properties; 3148193326Sed }; 3149193326Sed*/ 3150193326Sedllvm::Constant * 3151193326SedCGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, 3152314564Sdim const ProtocolMethodLists &methodLists) { 3153314564Sdim auto optInstanceMethods = 3154314564Sdim methodLists.emitMethodList(this, PD, 3155314564Sdim ProtocolMethodLists::OptionalInstanceMethods); 3156314564Sdim auto optClassMethods = 3157314564Sdim methodLists.emitMethodList(this, PD, 3158314564Sdim ProtocolMethodLists::OptionalClassMethods); 3159193326Sed 3160314564Sdim auto extendedMethodTypes = 3161314564Sdim EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(), 3162314564Sdim methodLists.emitExtendedTypesArray(this), 3163314564Sdim ObjCTypes); 3164314564Sdim 3165314564Sdim auto instanceProperties = 3166314564Sdim EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD, 3167314564Sdim ObjCTypes, false); 3168314564Sdim auto classProperties = 3169314564Sdim EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr, 3170314564Sdim PD, ObjCTypes, true); 3171314564Sdim 3172193326Sed // Return null if no extension bits are used. 3173314564Sdim if (optInstanceMethods->isNullValue() && 3174314564Sdim optClassMethods->isNullValue() && 3175314564Sdim extendedMethodTypes->isNullValue() && 3176314564Sdim instanceProperties->isNullValue() && 3177314564Sdim classProperties->isNullValue()) { 3178193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); 3179314564Sdim } 3180193326Sed 3181314564Sdim uint64_t size = 3182314564Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); 3183193326Sed 3184314564Sdim ConstantInitBuilder builder(CGM); 3185314564Sdim auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy); 3186314564Sdim values.addInt(ObjCTypes.IntTy, size); 3187314564Sdim values.add(optInstanceMethods); 3188314564Sdim values.add(optClassMethods); 3189314564Sdim values.add(instanceProperties); 3190314564Sdim values.add(extendedMethodTypes); 3191314564Sdim values.add(classProperties); 3192314564Sdim 3193193326Sed // No special section, but goes in llvm.used 3194353358Sdim return CreateMetadataVar("_OBJC_PROTOCOLEXT_" + PD->getName(), values, 3195296417Sdim StringRef(), CGM.getPointerAlign(), true); 3196193326Sed} 3197193326Sed 3198193326Sed/* 3199193326Sed struct objc_protocol_list { 3200234353Sdim struct objc_protocol_list *next; 3201234353Sdim long count; 3202234353Sdim Protocol *list[]; 3203193326Sed }; 3204193326Sed*/ 3205193326Sedllvm::Constant * 3206314564SdimCGObjCMac::EmitProtocolList(Twine name, 3207193326Sed ObjCProtocolDecl::protocol_iterator begin, 3208193326Sed ObjCProtocolDecl::protocol_iterator end) { 3209193326Sed // Just return null for empty protocol lists 3210314564Sdim if (begin == end) 3211193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 3212193326Sed 3213314564Sdim ConstantInitBuilder builder(CGM); 3214314564Sdim auto values = builder.beginStruct(); 3215193326Sed 3216193326Sed // This field is only used by the runtime. 3217314564Sdim values.addNullPointer(ObjCTypes.ProtocolListPtrTy); 3218198092Srdivacky 3219314564Sdim // Reserve a slot for the count. 3220314564Sdim auto countSlot = values.addPlaceholder(); 3221314564Sdim 3222314564Sdim auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy); 3223314564Sdim for (; begin != end; ++begin) { 3224314564Sdim refsArray.add(GetProtocolRef(*begin)); 3225314564Sdim } 3226314564Sdim auto count = refsArray.size(); 3227314564Sdim 3228314564Sdim // This list is null terminated. 3229314564Sdim refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy); 3230314564Sdim 3231314564Sdim refsArray.finishAndAddTo(values); 3232314564Sdim values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count); 3233314564Sdim 3234314564Sdim StringRef section; 3235314564Sdim if (CGM.getTriple().isOSBinFormatMachO()) 3236314564Sdim section = "__OBJC,__cat_cls_meth,regular,no_dead_strip"; 3237314564Sdim 3238198092Srdivacky llvm::GlobalVariable *GV = 3239314564Sdim CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false); 3240193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy); 3241193326Sed} 3242193326Sed 3243341825Sdimstatic void 3244234353SdimPushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet, 3245314564Sdim SmallVectorImpl<const ObjCPropertyDecl *> &Properties, 3246276479Sdim const ObjCProtocolDecl *Proto, 3247309124Sdim bool IsClassProperty) { 3248276479Sdim for (const auto *PD : Proto->properties()) { 3249309124Sdim if (IsClassProperty != PD->isClassProperty()) 3250309124Sdim continue; 3251280031Sdim if (!PropertySet.insert(PD->getIdentifier()).second) 3252200583Srdivacky continue; 3253314564Sdim Properties.push_back(PD); 3254200583Srdivacky } 3255360784Sdim 3256360784Sdim for (const auto *P : Proto->protocols()) 3257360784Sdim PushProtocolProperties(PropertySet, Properties, P, IsClassProperty); 3258200583Srdivacky} 3259200583Srdivacky 3260193326Sed/* 3261193326Sed struct _objc_property { 3262234353Sdim const char * const name; 3263234353Sdim const char * const attributes; 3264193326Sed }; 3265193326Sed 3266193326Sed struct _objc_property_list { 3267234353Sdim uint32_t entsize; // sizeof (struct _objc_property) 3268234353Sdim uint32_t prop_count; 3269234353Sdim struct _objc_property[prop_count]; 3270193326Sed }; 3271193326Sed*/ 3272226633Sdimllvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name, 3273198092Srdivacky const Decl *Container, 3274198092Srdivacky const ObjCContainerDecl *OCD, 3275309124Sdim const ObjCCommonTypesHelper &ObjCTypes, 3276309124Sdim bool IsClassProperty) { 3277309124Sdim if (IsClassProperty) { 3278309124Sdim // Make this entry NULL for OS X with deployment target < 10.11, for iOS 3279309124Sdim // with deployment target < 9.0. 3280309124Sdim const llvm::Triple &Triple = CGM.getTarget().getTriple(); 3281309124Sdim if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) || 3282309124Sdim (Triple.isiOS() && Triple.isOSVersionLT(9))) 3283309124Sdim return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 3284309124Sdim } 3285309124Sdim 3286314564Sdim SmallVector<const ObjCPropertyDecl *, 16> Properties; 3287200583Srdivacky llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet; 3288296417Sdim 3289296417Sdim if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) 3290296417Sdim for (const ObjCCategoryDecl *ClassExt : OID->known_extensions()) 3291296417Sdim for (auto *PD : ClassExt->properties()) { 3292309124Sdim if (IsClassProperty != PD->isClassProperty()) 3293309124Sdim continue; 3294296417Sdim PropertySet.insert(PD->getIdentifier()); 3295314564Sdim Properties.push_back(PD); 3296296417Sdim } 3297309124Sdim 3298276479Sdim for (const auto *PD : OCD->properties()) { 3299309124Sdim if (IsClassProperty != PD->isClassProperty()) 3300309124Sdim continue; 3301296417Sdim // Don't emit duplicate metadata for properties that were already in a 3302296417Sdim // class extension. 3303296417Sdim if (!PropertySet.insert(PD->getIdentifier()).second) 3304296417Sdim continue; 3305314564Sdim Properties.push_back(PD); 3306193326Sed } 3307296417Sdim 3308210299Sed if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) { 3309276479Sdim for (const auto *P : OID->all_referenced_protocols()) 3310314564Sdim PushProtocolProperties(PropertySet, Properties, P, IsClassProperty); 3311210299Sed } 3312210299Sed else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) { 3313276479Sdim for (const auto *P : CD->protocols()) 3314314564Sdim PushProtocolProperties(PropertySet, Properties, P, IsClassProperty); 3315210299Sed } 3316193326Sed 3317193326Sed // Return null for empty list. 3318193326Sed if (Properties.empty()) 3319193326Sed return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 3320193326Sed 3321314564Sdim unsigned propertySize = 3322243830Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy); 3323193326Sed 3324314564Sdim ConstantInitBuilder builder(CGM); 3325314564Sdim auto values = builder.beginStruct(); 3326314564Sdim values.addInt(ObjCTypes.IntTy, propertySize); 3327314564Sdim values.addInt(ObjCTypes.IntTy, Properties.size()); 3328314564Sdim auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy); 3329314564Sdim for (auto PD : Properties) { 3330360784Sdim if (PD->isDirectProperty()) 3331360784Sdim continue; 3332314564Sdim auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy); 3333314564Sdim property.add(GetPropertyName(PD->getIdentifier())); 3334314564Sdim property.add(GetPropertyTypeString(PD, Container)); 3335314564Sdim property.finishAndAddTo(propertiesArray); 3336314564Sdim } 3337314564Sdim propertiesArray.finishAndAddTo(values); 3338314564Sdim 3339314564Sdim StringRef Section; 3340314564Sdim if (CGM.getTriple().isOSBinFormatMachO()) 3341314564Sdim Section = (ObjCABI == 2) ? "__DATA, __objc_const" 3342314564Sdim : "__OBJC,__property,regular,no_dead_strip"; 3343314564Sdim 3344198092Srdivacky llvm::GlobalVariable *GV = 3345314564Sdim CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true); 3346193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy); 3347193326Sed} 3348193326Sed 3349234353Sdimllvm::Constant * 3350234353SdimCGObjCCommonMac::EmitProtocolMethodTypes(Twine Name, 3351234353Sdim ArrayRef<llvm::Constant*> MethodTypes, 3352234353Sdim const ObjCCommonTypesHelper &ObjCTypes) { 3353234353Sdim // Return null for empty list. 3354234353Sdim if (MethodTypes.empty()) 3355234353Sdim return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy); 3356234353Sdim 3357234353Sdim llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 3358234353Sdim MethodTypes.size()); 3359234353Sdim llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes); 3360234353Sdim 3361314564Sdim StringRef Section; 3362314564Sdim if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2) 3363314564Sdim Section = "__DATA, __objc_const"; 3364234353Sdim 3365296417Sdim llvm::GlobalVariable *GV = 3366314564Sdim CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true); 3367314564Sdim return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy); 3368193326Sed} 3369193326Sed 3370193326Sed/* 3371193326Sed struct _objc_category { 3372198092Srdivacky char *category_name; 3373198092Srdivacky char *class_name; 3374198092Srdivacky struct _objc_method_list *instance_methods; 3375198092Srdivacky struct _objc_method_list *class_methods; 3376198092Srdivacky struct _objc_protocol_list *protocols; 3377198092Srdivacky uint32_t size; // <rdar://4585769> 3378198092Srdivacky struct _objc_property_list *instance_properties; 3379309124Sdim struct _objc_property_list *class_properties; 3380193326Sed }; 3381198092Srdivacky*/ 3382193326Sedvoid CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 3383243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy); 3384193326Sed 3385193326Sed // FIXME: This is poor design, the OCD should have a pointer to the category 3386193326Sed // decl. Additionally, note that Category can be null for the @implementation 3387193326Sed // w/o an @interface case. Sema should just create one for us as it does for 3388193326Sed // @implementation so everyone else can live life under a clear blue sky. 3389193326Sed const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); 3390198092Srdivacky const ObjCCategoryDecl *Category = 3391193326Sed Interface->FindCategoryDeclaration(OCD->getIdentifier()); 3392193326Sed 3393234353Sdim SmallString<256> ExtName; 3394198398Srdivacky llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_' 3395198398Srdivacky << OCD->getName(); 3396198398Srdivacky 3397314564Sdim ConstantInitBuilder Builder(CGM); 3398314564Sdim auto Values = Builder.beginStruct(ObjCTypes.CategoryTy); 3399276479Sdim 3400314564Sdim enum { 3401314564Sdim InstanceMethods, 3402314564Sdim ClassMethods, 3403314564Sdim NumMethodLists 3404314564Sdim }; 3405314564Sdim SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists]; 3406314564Sdim for (const auto *MD : OCD->methods()) { 3407360784Sdim if (!MD->isDirectMethod()) 3408360784Sdim Methods[unsigned(MD->isClassMethod())].push_back(MD); 3409314564Sdim } 3410193326Sed 3411314564Sdim Values.add(GetClassName(OCD->getName())); 3412314564Sdim Values.add(GetClassName(Interface->getObjCRuntimeNameAsString())); 3413193326Sed LazySymbols.insert(Interface->getIdentifier()); 3414314564Sdim 3415314564Sdim Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods, 3416314564Sdim Methods[InstanceMethods])); 3417314564Sdim Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods, 3418314564Sdim Methods[ClassMethods])); 3419193326Sed if (Category) { 3420314564Sdim Values.add( 3421280031Sdim EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(), 3422314564Sdim Category->protocol_begin(), Category->protocol_end())); 3423193326Sed } else { 3424314564Sdim Values.addNullPointer(ObjCTypes.ProtocolListPtrTy); 3425193326Sed } 3426314564Sdim Values.addInt(ObjCTypes.IntTy, Size); 3427193326Sed 3428193326Sed // If there is no category @interface then there can be no properties. 3429193326Sed if (Category) { 3430353358Sdim Values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(), 3431314564Sdim OCD, Category, ObjCTypes, false)); 3432353358Sdim Values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), 3433314564Sdim OCD, Category, ObjCTypes, true)); 3434193326Sed } else { 3435314564Sdim Values.addNullPointer(ObjCTypes.PropertyListPtrTy); 3436314564Sdim Values.addNullPointer(ObjCTypes.PropertyListPtrTy); 3437193326Sed } 3438198092Srdivacky 3439198092Srdivacky llvm::GlobalVariable *GV = 3440314564Sdim CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values, 3441296417Sdim "__OBJC,__category,regular,no_dead_strip", 3442296417Sdim CGM.getPointerAlign(), true); 3443193326Sed DefinedCategories.push_back(GV); 3444314564Sdim DefinedCategoryNames.insert(llvm::CachedHashString(ExtName)); 3445221345Sdim // method definition entries must be clear for next implementation. 3446221345Sdim MethodDefinitions.clear(); 3447193326Sed} 3448193326Sed 3449243830Sdimenum FragileClassFlags { 3450296417Sdim /// Apparently: is not a meta-class. 3451243830Sdim FragileABI_Class_Factory = 0x00001, 3452296417Sdim 3453296417Sdim /// Is a meta-class. 3454243830Sdim FragileABI_Class_Meta = 0x00002, 3455296417Sdim 3456296417Sdim /// Has a non-trivial constructor or destructor. 3457243830Sdim FragileABI_Class_HasCXXStructors = 0x02000, 3458296417Sdim 3459296417Sdim /// Has hidden visibility. 3460296417Sdim FragileABI_Class_Hidden = 0x20000, 3461296417Sdim 3462296417Sdim /// Class implementation was compiled under ARC. 3463296417Sdim FragileABI_Class_CompiledByARC = 0x04000000, 3464296417Sdim 3465296417Sdim /// Class implementation was compiled under MRC and has MRC weak ivars. 3466296417Sdim /// Exclusive with CompiledByARC. 3467296417Sdim FragileABI_Class_HasMRCWeakIvars = 0x08000000, 3468193326Sed}; 3469193326Sed 3470243830Sdimenum NonFragileClassFlags { 3471243830Sdim /// Is a meta-class. 3472243830Sdim NonFragileABI_Class_Meta = 0x00001, 3473243830Sdim 3474243830Sdim /// Is a root class. 3475243830Sdim NonFragileABI_Class_Root = 0x00002, 3476243830Sdim 3477296417Sdim /// Has a non-trivial constructor or destructor. 3478243830Sdim NonFragileABI_Class_HasCXXStructors = 0x00004, 3479243830Sdim 3480243830Sdim /// Has hidden visibility. 3481243830Sdim NonFragileABI_Class_Hidden = 0x00010, 3482243830Sdim 3483243830Sdim /// Has the exception attribute. 3484243830Sdim NonFragileABI_Class_Exception = 0x00020, 3485243830Sdim 3486243830Sdim /// (Obsolete) ARC-specific: this class has a .release_ivars method 3487243830Sdim NonFragileABI_Class_HasIvarReleaser = 0x00040, 3488243830Sdim 3489243830Sdim /// Class implementation was compiled under ARC. 3490243830Sdim NonFragileABI_Class_CompiledByARC = 0x00080, 3491243830Sdim 3492243830Sdim /// Class has non-trivial destructors, but zero-initialization is okay. 3493296417Sdim NonFragileABI_Class_HasCXXDestructorOnly = 0x00100, 3494296417Sdim 3495296417Sdim /// Class implementation was compiled under MRC and has MRC weak ivars. 3496296417Sdim /// Exclusive with CompiledByARC. 3497296417Sdim NonFragileABI_Class_HasMRCWeakIvars = 0x00200, 3498243830Sdim}; 3499243830Sdim 3500296417Sdimstatic bool hasWeakMember(QualType type) { 3501296417Sdim if (type.getObjCLifetime() == Qualifiers::OCL_Weak) { 3502296417Sdim return true; 3503296417Sdim } 3504296417Sdim 3505296417Sdim if (auto recType = type->getAs<RecordType>()) { 3506296417Sdim for (auto field : recType->getDecl()->fields()) { 3507296417Sdim if (hasWeakMember(field->getType())) 3508296417Sdim return true; 3509296417Sdim } 3510296417Sdim } 3511296417Sdim 3512296417Sdim return false; 3513296417Sdim} 3514296417Sdim 3515296417Sdim/// For compatibility, we only want to set the "HasMRCWeakIvars" flag 3516296417Sdim/// (and actually fill in a layout string) if we really do have any 3517296417Sdim/// __weak ivars. 3518296417Sdimstatic bool hasMRCWeakIvars(CodeGenModule &CGM, 3519296417Sdim const ObjCImplementationDecl *ID) { 3520296417Sdim if (!CGM.getLangOpts().ObjCWeak) return false; 3521296417Sdim assert(CGM.getLangOpts().getGC() == LangOptions::NonGC); 3522296417Sdim 3523296417Sdim for (const ObjCIvarDecl *ivar = 3524296417Sdim ID->getClassInterface()->all_declared_ivar_begin(); 3525296417Sdim ivar; ivar = ivar->getNextIvar()) { 3526296417Sdim if (hasWeakMember(ivar->getType())) 3527296417Sdim return true; 3528296417Sdim } 3529296417Sdim 3530296417Sdim return false; 3531296417Sdim} 3532296417Sdim 3533193326Sed/* 3534193326Sed struct _objc_class { 3535198092Srdivacky Class isa; 3536198092Srdivacky Class super_class; 3537198092Srdivacky const char *name; 3538198092Srdivacky long version; 3539198092Srdivacky long info; 3540198092Srdivacky long instance_size; 3541198092Srdivacky struct _objc_ivar_list *ivars; 3542198092Srdivacky struct _objc_method_list *methods; 3543198092Srdivacky struct _objc_cache *cache; 3544198092Srdivacky struct _objc_protocol_list *protocols; 3545198092Srdivacky // Objective-C 1.0 extensions (<rdr://4585769>) 3546198092Srdivacky const char *ivar_layout; 3547198092Srdivacky struct _objc_class_ext *ext; 3548193326Sed }; 3549193326Sed 3550193326Sed See EmitClassExtension(); 3551198092Srdivacky*/ 3552193326Sedvoid CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { 3553341825Sdim IdentifierInfo *RuntimeName = 3554341825Sdim &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString()); 3555341825Sdim DefinedSymbols.insert(RuntimeName); 3556193326Sed 3557193326Sed std::string ClassName = ID->getNameAsString(); 3558193326Sed // FIXME: Gross 3559198092Srdivacky ObjCInterfaceDecl *Interface = 3560193326Sed const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); 3561198092Srdivacky llvm::Constant *Protocols = 3562280031Sdim EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(), 3563280031Sdim Interface->all_referenced_protocol_begin(), 3564280031Sdim Interface->all_referenced_protocol_end()); 3565243830Sdim unsigned Flags = FragileABI_Class_Factory; 3566243830Sdim if (ID->hasNonZeroConstructors() || ID->hasDestructors()) 3567243830Sdim Flags |= FragileABI_Class_HasCXXStructors; 3568193326Sed 3569296417Sdim bool hasMRCWeak = false; 3570296417Sdim 3571296417Sdim if (CGM.getLangOpts().ObjCAutoRefCount) 3572296417Sdim Flags |= FragileABI_Class_CompiledByARC; 3573296417Sdim else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID))) 3574296417Sdim Flags |= FragileABI_Class_HasMRCWeakIvars; 3575296417Sdim 3576296417Sdim CharUnits Size = 3577296417Sdim CGM.getContext().getASTObjCImplementationLayout(ID).getSize(); 3578296417Sdim 3579193326Sed // FIXME: Set CXX-structors flag. 3580218893Sdim if (ID->getClassInterface()->getVisibility() == HiddenVisibility) 3581243830Sdim Flags |= FragileABI_Class_Hidden; 3582193326Sed 3583314564Sdim enum { 3584314564Sdim InstanceMethods, 3585314564Sdim ClassMethods, 3586314564Sdim NumMethodLists 3587314564Sdim }; 3588314564Sdim SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists]; 3589314564Sdim for (const auto *MD : ID->methods()) { 3590360784Sdim if (!MD->isDirectMethod()) 3591360784Sdim Methods[unsigned(MD->isClassMethod())].push_back(MD); 3592314564Sdim } 3593276479Sdim 3594276479Sdim for (const auto *PID : ID->property_impls()) { 3595193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { 3596360784Sdim if (PID->getPropertyDecl()->isDirectProperty()) 3597360784Sdim continue; 3598360784Sdim if (ObjCMethodDecl *MD = PID->getGetterMethodDecl()) 3599314564Sdim if (GetMethodDefinition(MD)) 3600314564Sdim Methods[InstanceMethods].push_back(MD); 3601360784Sdim if (ObjCMethodDecl *MD = PID->getSetterMethodDecl()) 3602314564Sdim if (GetMethodDefinition(MD)) 3603314564Sdim Methods[InstanceMethods].push_back(MD); 3604193326Sed } 3605193326Sed } 3606193326Sed 3607314564Sdim ConstantInitBuilder builder(CGM); 3608314564Sdim auto values = builder.beginStruct(ObjCTypes.ClassTy); 3609314564Sdim values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods])); 3610193326Sed if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) { 3611193326Sed // Record a reference to the super class. 3612193326Sed LazySymbols.insert(Super->getIdentifier()); 3613193326Sed 3614314564Sdim values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()), 3615314564Sdim ObjCTypes.ClassPtrTy); 3616193326Sed } else { 3617314564Sdim values.addNullPointer(ObjCTypes.ClassPtrTy); 3618193326Sed } 3619314564Sdim values.add(GetClassName(ID->getObjCRuntimeNameAsString())); 3620193326Sed // Version is always 0. 3621314564Sdim values.addInt(ObjCTypes.LongTy, 0); 3622314564Sdim values.addInt(ObjCTypes.LongTy, Flags); 3623314564Sdim values.addInt(ObjCTypes.LongTy, Size.getQuantity()); 3624314564Sdim values.add(EmitIvarList(ID, false)); 3625314564Sdim values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods, 3626314564Sdim Methods[InstanceMethods])); 3627193326Sed // cache is always NULL. 3628314564Sdim values.addNullPointer(ObjCTypes.CachePtrTy); 3629314564Sdim values.add(Protocols); 3630314564Sdim values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size)); 3631314564Sdim values.add(EmitClassExtension(ID, Size, hasMRCWeak, 3632314564Sdim /*isMetaclass*/ false)); 3633314564Sdim 3634280031Sdim std::string Name("OBJC_CLASS_"); 3635199482Srdivacky Name += ClassName; 3636199482Srdivacky const char *Section = "__OBJC,__class,regular,no_dead_strip"; 3637199482Srdivacky // Check for a forward reference. 3638276479Sdim llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); 3639199482Srdivacky if (GV) { 3640199482Srdivacky assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 3641199482Srdivacky "Forward metaclass reference has incorrect type."); 3642314564Sdim values.finishAndSetAsInitializer(GV); 3643199482Srdivacky GV->setSection(Section); 3644360784Sdim GV->setAlignment(CGM.getPointerAlign().getAsAlign()); 3645276479Sdim CGM.addCompilerUsedGlobal(GV); 3646276479Sdim } else 3647314564Sdim GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true); 3648193326Sed DefinedClasses.push_back(GV); 3649276479Sdim ImplementedClasses.push_back(Interface); 3650221345Sdim // method definition entries must be clear for next implementation. 3651221345Sdim MethodDefinitions.clear(); 3652193326Sed} 3653193326Sed 3654193326Sedllvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, 3655193326Sed llvm::Constant *Protocols, 3656314564Sdim ArrayRef<const ObjCMethodDecl*> Methods) { 3657243830Sdim unsigned Flags = FragileABI_Class_Meta; 3658243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy); 3659193326Sed 3660218893Sdim if (ID->getClassInterface()->getVisibility() == HiddenVisibility) 3661243830Sdim Flags |= FragileABI_Class_Hidden; 3662198092Srdivacky 3663314564Sdim ConstantInitBuilder builder(CGM); 3664314564Sdim auto values = builder.beginStruct(ObjCTypes.ClassTy); 3665193326Sed // The isa for the metaclass is the root of the hierarchy. 3666193326Sed const ObjCInterfaceDecl *Root = ID->getClassInterface(); 3667193326Sed while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) 3668193326Sed Root = Super; 3669314564Sdim values.addBitCast(GetClassName(Root->getObjCRuntimeNameAsString()), 3670314564Sdim ObjCTypes.ClassPtrTy); 3671193326Sed // The super class for the metaclass is emitted as the name of the 3672193326Sed // super class. The runtime fixes this up to point to the 3673193326Sed // *metaclass* for the super class. 3674193326Sed if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) { 3675314564Sdim values.addBitCast(GetClassName(Super->getObjCRuntimeNameAsString()), 3676314564Sdim ObjCTypes.ClassPtrTy); 3677193326Sed } else { 3678314564Sdim values.addNullPointer(ObjCTypes.ClassPtrTy); 3679193326Sed } 3680314564Sdim values.add(GetClassName(ID->getObjCRuntimeNameAsString())); 3681193326Sed // Version is always 0. 3682314564Sdim values.addInt(ObjCTypes.LongTy, 0); 3683314564Sdim values.addInt(ObjCTypes.LongTy, Flags); 3684314564Sdim values.addInt(ObjCTypes.LongTy, Size); 3685314564Sdim values.add(EmitIvarList(ID, true)); 3686314564Sdim values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods, 3687314564Sdim Methods)); 3688193326Sed // cache is always NULL. 3689314564Sdim values.addNullPointer(ObjCTypes.CachePtrTy); 3690314564Sdim values.add(Protocols); 3691193326Sed // ivar_layout for metaclass is always NULL. 3692314564Sdim values.addNullPointer(ObjCTypes.Int8PtrTy); 3693309124Sdim // The class extension is used to store class properties for metaclasses. 3694314564Sdim values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/, 3695314564Sdim /*isMetaclass*/true)); 3696193326Sed 3697280031Sdim std::string Name("OBJC_METACLASS_"); 3698239462Sdim Name += ID->getName(); 3699193326Sed 3700193326Sed // Check for a forward reference. 3701276479Sdim llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); 3702193326Sed if (GV) { 3703193326Sed assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 3704193326Sed "Forward metaclass reference has incorrect type."); 3705314564Sdim values.finishAndSetAsInitializer(GV); 3706193326Sed } else { 3707314564Sdim GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(), 3708314564Sdim /*constant*/ false, 3709314564Sdim llvm::GlobalValue::PrivateLinkage); 3710193326Sed } 3711193326Sed GV->setSection("__OBJC,__meta_class,regular,no_dead_strip"); 3712276479Sdim CGM.addCompilerUsedGlobal(GV); 3713193326Sed 3714193326Sed return GV; 3715193326Sed} 3716193326Sed 3717198092Srdivackyllvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) { 3718280031Sdim std::string Name = "OBJC_METACLASS_" + ID->getNameAsString(); 3719193326Sed 3720193326Sed // FIXME: Should we look these up somewhere other than the module. Its a bit 3721193326Sed // silly since we only generate these while processing an implementation, so 3722193326Sed // exactly one pointer would work if know when we entered/exitted an 3723193326Sed // implementation block. 3724193326Sed 3725193326Sed // Check for an existing forward reference. 3726193326Sed // Previously, metaclass with internal linkage may have been defined. 3727193326Sed // pass 'true' as 2nd argument so it is returned. 3728276479Sdim llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); 3729276479Sdim if (!GV) 3730276479Sdim GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 3731276479Sdim llvm::GlobalValue::PrivateLinkage, nullptr, 3732276479Sdim Name); 3733276479Sdim 3734276479Sdim assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 3735276479Sdim "Forward metaclass reference has incorrect type."); 3736276479Sdim return GV; 3737193326Sed} 3738193326Sed 3739199482Srdivackyllvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) { 3740280031Sdim std::string Name = "OBJC_CLASS_" + ID->getNameAsString(); 3741276479Sdim llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); 3742276479Sdim 3743276479Sdim if (!GV) 3744276479Sdim GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 3745276479Sdim llvm::GlobalValue::PrivateLinkage, nullptr, 3746276479Sdim Name); 3747276479Sdim 3748276479Sdim assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 3749276479Sdim "Forward class metadata reference has incorrect type."); 3750276479Sdim return GV; 3751199482Srdivacky} 3752199482Srdivacky 3753193326Sed/* 3754296417Sdim Emit a "class extension", which in this specific context means extra 3755296417Sdim data that doesn't fit in the normal fragile-ABI class structure, and 3756296417Sdim has nothing to do with the language concept of a class extension. 3757296417Sdim 3758193326Sed struct objc_class_ext { 3759198092Srdivacky uint32_t size; 3760198092Srdivacky const char *weak_ivar_layout; 3761198092Srdivacky struct _objc_property_list *properties; 3762193326Sed }; 3763193326Sed*/ 3764193326Sedllvm::Constant * 3765296417SdimCGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID, 3766309124Sdim CharUnits InstanceSize, bool hasMRCWeakIvars, 3767314564Sdim bool isMetaclass) { 3768314564Sdim // Weak ivar layout. 3769314564Sdim llvm::Constant *layout; 3770314564Sdim if (isMetaclass) { 3771314564Sdim layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy); 3772314564Sdim } else { 3773314564Sdim layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize, 3774314564Sdim hasMRCWeakIvars); 3775314564Sdim } 3776193326Sed 3777314564Sdim // Properties. 3778314564Sdim llvm::Constant *propertyList = 3779353358Sdim EmitPropertyList((isMetaclass ? Twine("_OBJC_$_CLASS_PROP_LIST_") 3780353358Sdim : Twine("_OBJC_$_PROP_LIST_")) 3781314564Sdim + ID->getName(), 3782314564Sdim ID, ID->getClassInterface(), ObjCTypes, isMetaclass); 3783193326Sed 3784193326Sed // Return null if no extension bits are used. 3785314564Sdim if (layout->isNullValue() && propertyList->isNullValue()) { 3786193326Sed return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); 3787314564Sdim } 3788193326Sed 3789314564Sdim uint64_t size = 3790314564Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy); 3791314564Sdim 3792314564Sdim ConstantInitBuilder builder(CGM); 3793314564Sdim auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy); 3794314564Sdim values.addInt(ObjCTypes.IntTy, size); 3795314564Sdim values.add(layout); 3796314564Sdim values.add(propertyList); 3797314564Sdim 3798314564Sdim return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values, 3799296417Sdim "__OBJC,__class_ext,regular,no_dead_strip", 3800296417Sdim CGM.getPointerAlign(), true); 3801193326Sed} 3802193326Sed 3803193326Sed/* 3804193326Sed struct objc_ivar { 3805234353Sdim char *ivar_name; 3806234353Sdim char *ivar_type; 3807234353Sdim int ivar_offset; 3808193326Sed }; 3809193326Sed 3810193326Sed struct objc_ivar_list { 3811234353Sdim int ivar_count; 3812234353Sdim struct objc_ivar list[count]; 3813193326Sed }; 3814198092Srdivacky*/ 3815193326Sedllvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, 3816193326Sed bool ForClass) { 3817193326Sed // When emitting the root class GCC emits ivar entries for the 3818193326Sed // actual class structure. It is not clear if we need to follow this 3819193326Sed // behavior; for now lets try and get away with not doing it. If so, 3820193326Sed // the cleanest solution would be to make up an ObjCInterfaceDecl 3821193326Sed // for the class. 3822193326Sed if (ForClass) 3823193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); 3824198092Srdivacky 3825226633Sdim const ObjCInterfaceDecl *OID = ID->getClassInterface(); 3826198092Srdivacky 3827314564Sdim ConstantInitBuilder builder(CGM); 3828314564Sdim auto ivarList = builder.beginStruct(); 3829314564Sdim auto countSlot = ivarList.addPlaceholder(); 3830314564Sdim auto ivars = ivarList.beginArray(ObjCTypes.IvarTy); 3831314564Sdim 3832341825Sdim for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); 3833224145Sdim IVD; IVD = IVD->getNextIvar()) { 3834193576Sed // Ignore unnamed bit-fields. 3835193576Sed if (!IVD->getDeclName()) 3836198092Srdivacky continue; 3837314564Sdim 3838314564Sdim auto ivar = ivars.beginStruct(ObjCTypes.IvarTy); 3839314564Sdim ivar.add(GetMethodVarName(IVD->getIdentifier())); 3840314564Sdim ivar.add(GetMethodVarType(IVD)); 3841314564Sdim ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD)); 3842314564Sdim ivar.finishAndAddTo(ivars); 3843193326Sed } 3844193326Sed 3845193326Sed // Return null for empty list. 3846314564Sdim auto count = ivars.size(); 3847314564Sdim if (count == 0) { 3848314564Sdim ivars.abandon(); 3849314564Sdim ivarList.abandon(); 3850193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); 3851314564Sdim } 3852193326Sed 3853314564Sdim ivars.finishAndAddTo(ivarList); 3854314564Sdim ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count); 3855193326Sed 3856193326Sed llvm::GlobalVariable *GV; 3857193326Sed if (ForClass) 3858280031Sdim GV = 3859314564Sdim CreateMetadataVar("OBJC_CLASS_VARIABLES_" + ID->getName(), ivarList, 3860296417Sdim "__OBJC,__class_vars,regular,no_dead_strip", 3861296417Sdim CGM.getPointerAlign(), true); 3862193326Sed else 3863314564Sdim GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList, 3864296417Sdim "__OBJC,__instance_vars,regular,no_dead_strip", 3865296417Sdim CGM.getPointerAlign(), true); 3866193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy); 3867193326Sed} 3868193326Sed 3869314564Sdim/// Build a struct objc_method_description constant for the given method. 3870314564Sdim/// 3871314564Sdim/// struct objc_method_description { 3872314564Sdim/// SEL method_name; 3873314564Sdim/// char *method_types; 3874314564Sdim/// }; 3875314564Sdimvoid CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder, 3876314564Sdim const ObjCMethodDecl *MD) { 3877314564Sdim auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy); 3878314564Sdim description.addBitCast(GetMethodVarName(MD->getSelector()), 3879314564Sdim ObjCTypes.SelectorPtrTy); 3880314564Sdim description.add(GetMethodVarType(MD)); 3881314564Sdim description.finishAndAddTo(builder); 3882314564Sdim} 3883198092Srdivacky 3884314564Sdim/// Build a struct objc_method constant for the given method. 3885314564Sdim/// 3886314564Sdim/// struct objc_method { 3887314564Sdim/// SEL method_name; 3888314564Sdim/// char *method_types; 3889314564Sdim/// void *method; 3890314564Sdim/// }; 3891314564Sdimvoid CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder, 3892314564Sdim const ObjCMethodDecl *MD) { 3893314564Sdim llvm::Function *fn = GetMethodDefinition(MD); 3894314564Sdim assert(fn && "no definition registered for method"); 3895193326Sed 3896314564Sdim auto method = builder.beginStruct(ObjCTypes.MethodTy); 3897314564Sdim method.addBitCast(GetMethodVarName(MD->getSelector()), 3898314564Sdim ObjCTypes.SelectorPtrTy); 3899314564Sdim method.add(GetMethodVarType(MD)); 3900314564Sdim method.addBitCast(fn, ObjCTypes.Int8PtrTy); 3901314564Sdim method.finishAndAddTo(builder); 3902193326Sed} 3903193326Sed 3904314564Sdim/// Build a struct objc_method_list or struct objc_method_description_list, 3905314564Sdim/// as appropriate. 3906314564Sdim/// 3907314564Sdim/// struct objc_method_list { 3908314564Sdim/// struct objc_method_list *obsolete; 3909314564Sdim/// int count; 3910314564Sdim/// struct objc_method methods_list[count]; 3911314564Sdim/// }; 3912314564Sdim/// 3913314564Sdim/// struct objc_method_description_list { 3914314564Sdim/// int count; 3915314564Sdim/// struct objc_method_description list[count]; 3916314564Sdim/// }; 3917314564Sdimllvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT, 3918314564Sdim ArrayRef<const ObjCMethodDecl *> methods) { 3919314564Sdim StringRef prefix; 3920314564Sdim StringRef section; 3921314564Sdim bool forProtocol = false; 3922314564Sdim switch (MLT) { 3923314564Sdim case MethodListType::CategoryInstanceMethods: 3924314564Sdim prefix = "OBJC_CATEGORY_INSTANCE_METHODS_"; 3925314564Sdim section = "__OBJC,__cat_inst_meth,regular,no_dead_strip"; 3926314564Sdim forProtocol = false; 3927314564Sdim break; 3928314564Sdim case MethodListType::CategoryClassMethods: 3929314564Sdim prefix = "OBJC_CATEGORY_CLASS_METHODS_"; 3930314564Sdim section = "__OBJC,__cat_cls_meth,regular,no_dead_strip"; 3931314564Sdim forProtocol = false; 3932314564Sdim break; 3933314564Sdim case MethodListType::InstanceMethods: 3934314564Sdim prefix = "OBJC_INSTANCE_METHODS_"; 3935314564Sdim section = "__OBJC,__inst_meth,regular,no_dead_strip"; 3936314564Sdim forProtocol = false; 3937314564Sdim break; 3938314564Sdim case MethodListType::ClassMethods: 3939314564Sdim prefix = "OBJC_CLASS_METHODS_"; 3940314564Sdim section = "__OBJC,__cls_meth,regular,no_dead_strip"; 3941314564Sdim forProtocol = false; 3942314564Sdim break; 3943314564Sdim case MethodListType::ProtocolInstanceMethods: 3944314564Sdim prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_"; 3945314564Sdim section = "__OBJC,__cat_inst_meth,regular,no_dead_strip"; 3946314564Sdim forProtocol = true; 3947314564Sdim break; 3948314564Sdim case MethodListType::ProtocolClassMethods: 3949314564Sdim prefix = "OBJC_PROTOCOL_CLASS_METHODS_"; 3950314564Sdim section = "__OBJC,__cat_cls_meth,regular,no_dead_strip"; 3951314564Sdim forProtocol = true; 3952314564Sdim break; 3953314564Sdim case MethodListType::OptionalProtocolInstanceMethods: 3954314564Sdim prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"; 3955314564Sdim section = "__OBJC,__cat_inst_meth,regular,no_dead_strip"; 3956314564Sdim forProtocol = true; 3957314564Sdim break; 3958314564Sdim case MethodListType::OptionalProtocolClassMethods: 3959314564Sdim prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_"; 3960314564Sdim section = "__OBJC,__cat_cls_meth,regular,no_dead_strip"; 3961314564Sdim forProtocol = true; 3962314564Sdim break; 3963314564Sdim } 3964314564Sdim 3965193326Sed // Return null for empty list. 3966314564Sdim if (methods.empty()) 3967314564Sdim return llvm::Constant::getNullValue(forProtocol 3968314564Sdim ? ObjCTypes.MethodDescriptionListPtrTy 3969314564Sdim : ObjCTypes.MethodListPtrTy); 3970193326Sed 3971314564Sdim // For protocols, this is an objc_method_description_list, which has 3972314564Sdim // a slightly different structure. 3973314564Sdim if (forProtocol) { 3974314564Sdim ConstantInitBuilder builder(CGM); 3975314564Sdim auto values = builder.beginStruct(); 3976314564Sdim values.addInt(ObjCTypes.IntTy, methods.size()); 3977314564Sdim auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy); 3978314564Sdim for (auto MD : methods) { 3979314564Sdim emitMethodDescriptionConstant(methodArray, MD); 3980314564Sdim } 3981314564Sdim methodArray.finishAndAddTo(values); 3982193326Sed 3983314564Sdim llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section, 3984314564Sdim CGM.getPointerAlign(), true); 3985314564Sdim return llvm::ConstantExpr::getBitCast(GV, 3986314564Sdim ObjCTypes.MethodDescriptionListPtrTy); 3987314564Sdim } 3988314564Sdim 3989314564Sdim // Otherwise, it's an objc_method_list. 3990314564Sdim ConstantInitBuilder builder(CGM); 3991314564Sdim auto values = builder.beginStruct(); 3992314564Sdim values.addNullPointer(ObjCTypes.Int8PtrTy); 3993314564Sdim values.addInt(ObjCTypes.IntTy, methods.size()); 3994314564Sdim auto methodArray = values.beginArray(ObjCTypes.MethodTy); 3995314564Sdim for (auto MD : methods) { 3996360784Sdim if (!MD->isDirectMethod()) 3997360784Sdim emitMethodConstant(methodArray, MD); 3998314564Sdim } 3999314564Sdim methodArray.finishAndAddTo(values); 4000314564Sdim 4001314564Sdim llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section, 4002314564Sdim CGM.getPointerAlign(), true); 4003224145Sdim return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy); 4004193326Sed} 4005193326Sed 4006193326Sedllvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD, 4007198092Srdivacky const ObjCContainerDecl *CD) { 4008360784Sdim llvm::Function *Method; 4009360784Sdim 4010360784Sdim if (OMD->isDirectMethod()) { 4011360784Sdim Method = GenerateDirectMethod(OMD, CD); 4012360784Sdim } else { 4013360784Sdim SmallString<256> Name; 4014360784Sdim GetNameForMethod(OMD, CD, Name); 4015360784Sdim 4016360784Sdim CodeGenTypes &Types = CGM.getTypes(); 4017360784Sdim llvm::FunctionType *MethodTy = 4018360784Sdim Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD)); 4019360784Sdim Method = 4020360784Sdim llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage, 4021360784Sdim Name.str(), &CGM.getModule()); 4022360784Sdim } 4023360784Sdim 4024360784Sdim MethodDefinitions.insert(std::make_pair(OMD, Method)); 4025360784Sdim 4026360784Sdim return Method; 4027360784Sdim} 4028360784Sdim 4029360784Sdimllvm::Function * 4030360784SdimCGObjCCommonMac::GenerateDirectMethod(const ObjCMethodDecl *OMD, 4031360784Sdim const ObjCContainerDecl *CD) { 4032360784Sdim auto I = DirectMethodDefinitions.find(OMD->getCanonicalDecl()); 4033360784Sdim if (I != DirectMethodDefinitions.end()) 4034360784Sdim return I->second; 4035360784Sdim 4036234353Sdim SmallString<256> Name; 4037360784Sdim GetNameForMethod(OMD, CD, Name, /*ignoreCategoryNamespace*/true); 4038193326Sed 4039193326Sed CodeGenTypes &Types = CGM.getTypes(); 4040226633Sdim llvm::FunctionType *MethodTy = 4041234353Sdim Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD)); 4042198092Srdivacky llvm::Function *Method = 4043360784Sdim llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage, 4044360784Sdim Name.str(), &CGM.getModule()); 4045360784Sdim DirectMethodDefinitions.insert(std::make_pair(OMD->getCanonicalDecl(), Method)); 4046193326Sed 4047193326Sed return Method; 4048193326Sed} 4049193326Sed 4050360784Sdimvoid CGObjCCommonMac::GenerateDirectMethodPrologue( 4051360784Sdim CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD, 4052360784Sdim const ObjCContainerDecl *CD) { 4053360784Sdim auto &Builder = CGF.Builder; 4054360784Sdim bool ReceiverCanBeNull = true; 4055360784Sdim auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl()); 4056360784Sdim auto selfValue = Builder.CreateLoad(selfAddr); 4057360784Sdim 4058360784Sdim // Generate: 4059360784Sdim // 4060360784Sdim // /* for class methods only to force class lazy initialization */ 4061360784Sdim // self = [self self]; 4062360784Sdim // 4063360784Sdim // /* unless the receiver is never NULL */ 4064360784Sdim // if (self == nil) { 4065360784Sdim // return (ReturnType){ }; 4066360784Sdim // } 4067360784Sdim // 4068360784Sdim // _cmd = @selector(...) 4069360784Sdim // ... 4070360784Sdim 4071360784Sdim if (OMD->isClassMethod()) { 4072360784Sdim const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD); 4073360784Sdim assert(OID && 4074360784Sdim "GenerateDirectMethod() should be called with the Class Interface"); 4075360784Sdim Selector SelfSel = GetNullarySelector("self", CGM.getContext()); 4076360784Sdim auto ResultType = CGF.getContext().getObjCIdType(); 4077360784Sdim RValue result; 4078360784Sdim CallArgList Args; 4079360784Sdim 4080360784Sdim // TODO: If this method is inlined, the caller might know that `self` is 4081360784Sdim // already initialized; for example, it might be an ordinary Objective-C 4082360784Sdim // method which always receives an initialized `self`, or it might have just 4083360784Sdim // forced initialization on its own. 4084360784Sdim // 4085360784Sdim // We should find a way to eliminate this unnecessary initialization in such 4086360784Sdim // cases in LLVM. 4087360784Sdim result = GeneratePossiblySpecializedMessageSend( 4088360784Sdim CGF, ReturnValueSlot(), ResultType, SelfSel, selfValue, Args, OID, 4089360784Sdim nullptr, true); 4090360784Sdim Builder.CreateStore(result.getScalarVal(), selfAddr); 4091360784Sdim 4092360784Sdim // Nullable `Class` expressions cannot be messaged with a direct method 4093360784Sdim // so the only reason why the receive can be null would be because 4094360784Sdim // of weak linking. 4095360784Sdim ReceiverCanBeNull = isWeakLinkedClass(OID); 4096360784Sdim } 4097360784Sdim 4098360784Sdim if (ReceiverCanBeNull) { 4099360784Sdim llvm::BasicBlock *SelfIsNilBlock = 4100360784Sdim CGF.createBasicBlock("objc_direct_method.self_is_nil"); 4101360784Sdim llvm::BasicBlock *ContBlock = 4102360784Sdim CGF.createBasicBlock("objc_direct_method.cont"); 4103360784Sdim 4104360784Sdim // if (self == nil) { 4105360784Sdim auto selfTy = cast<llvm::PointerType>(selfValue->getType()); 4106360784Sdim auto Zero = llvm::ConstantPointerNull::get(selfTy); 4107360784Sdim 4108360784Sdim llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 4109360784Sdim Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock, 4110360784Sdim ContBlock, MDHelper.createBranchWeights(1, 1 << 20)); 4111360784Sdim 4112360784Sdim CGF.EmitBlock(SelfIsNilBlock); 4113360784Sdim 4114360784Sdim // return (ReturnType){ }; 4115360784Sdim auto retTy = OMD->getReturnType(); 4116360784Sdim Builder.SetInsertPoint(SelfIsNilBlock); 4117360784Sdim if (!retTy->isVoidType()) { 4118360784Sdim CGF.EmitNullInitialization(CGF.ReturnValue, retTy); 4119360784Sdim } 4120360784Sdim CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 4121360784Sdim // } 4122360784Sdim 4123360784Sdim // rest of the body 4124360784Sdim CGF.EmitBlock(ContBlock); 4125360784Sdim Builder.SetInsertPoint(ContBlock); 4126360784Sdim } 4127360784Sdim 4128360784Sdim // only synthesize _cmd if it's referenced 4129360784Sdim if (OMD->getCmdDecl()->isUsed()) { 4130360784Sdim Builder.CreateStore(GetSelector(CGF, OMD), 4131360784Sdim CGF.GetAddrOfLocalVar(OMD->getCmdDecl())); 4132360784Sdim } 4133360784Sdim} 4134360784Sdim 4135276479Sdimllvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name, 4136314564Sdim ConstantStructBuilder &Init, 4137314564Sdim StringRef Section, 4138314564Sdim CharUnits Align, 4139314564Sdim bool AddToUsed) { 4140353358Sdim llvm::GlobalValue::LinkageTypes LT = 4141353358Sdim getLinkageTypeForObjCMetadata(CGM, Section); 4142314564Sdim llvm::GlobalVariable *GV = 4143353358Sdim Init.finishAndCreateGlobal(Name, Align, /*constant*/ false, LT); 4144314564Sdim if (!Section.empty()) 4145314564Sdim GV->setSection(Section); 4146314564Sdim if (AddToUsed) 4147314564Sdim CGM.addCompilerUsedGlobal(GV); 4148314564Sdim return GV; 4149314564Sdim} 4150314564Sdim 4151314564Sdimllvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name, 4152276479Sdim llvm::Constant *Init, 4153276479Sdim StringRef Section, 4154296417Sdim CharUnits Align, 4155276479Sdim bool AddToUsed) { 4156226633Sdim llvm::Type *Ty = Init->getType(); 4157353358Sdim llvm::GlobalValue::LinkageTypes LT = 4158353358Sdim getLinkageTypeForObjCMetadata(CGM, Section); 4159198092Srdivacky llvm::GlobalVariable *GV = 4160353358Sdim new llvm::GlobalVariable(CGM.getModule(), Ty, false, LT, Init, Name); 4161276479Sdim if (!Section.empty()) 4162193326Sed GV->setSection(Section); 4163360784Sdim GV->setAlignment(Align.getAsAlign()); 4164193326Sed if (AddToUsed) 4165276479Sdim CGM.addCompilerUsedGlobal(GV); 4166193326Sed return GV; 4167193326Sed} 4168193326Sed 4169314564Sdimllvm::GlobalVariable * 4170314564SdimCGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type, 4171314564Sdim bool ForceNonFragileABI, 4172314564Sdim bool NullTerminate) { 4173314564Sdim StringRef Label; 4174314564Sdim switch (Type) { 4175314564Sdim case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break; 4176314564Sdim case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break; 4177314564Sdim case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break; 4178314564Sdim case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break; 4179314564Sdim } 4180314564Sdim 4181314564Sdim bool NonFragile = ForceNonFragileABI || isNonFragileABI(); 4182314564Sdim 4183314564Sdim StringRef Section; 4184314564Sdim switch (Type) { 4185314564Sdim case ObjCLabelType::ClassName: 4186314564Sdim Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals" 4187314564Sdim : "__TEXT,__cstring,cstring_literals"; 4188314564Sdim break; 4189314564Sdim case ObjCLabelType::MethodVarName: 4190314564Sdim Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals" 4191314564Sdim : "__TEXT,__cstring,cstring_literals"; 4192314564Sdim break; 4193314564Sdim case ObjCLabelType::MethodVarType: 4194314564Sdim Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals" 4195314564Sdim : "__TEXT,__cstring,cstring_literals"; 4196314564Sdim break; 4197314564Sdim case ObjCLabelType::PropertyName: 4198314564Sdim Section = "__TEXT,__cstring,cstring_literals"; 4199314564Sdim break; 4200314564Sdim } 4201314564Sdim 4202314564Sdim llvm::Constant *Value = 4203314564Sdim llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate); 4204314564Sdim llvm::GlobalVariable *GV = 4205314564Sdim new llvm::GlobalVariable(CGM.getModule(), Value->getType(), 4206314564Sdim /*isConstant=*/true, 4207314564Sdim llvm::GlobalValue::PrivateLinkage, Value, Label); 4208314564Sdim if (CGM.getTriple().isOSBinFormatMachO()) 4209314564Sdim GV->setSection(Section); 4210314564Sdim GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4211360784Sdim GV->setAlignment(CharUnits::One().getAsAlign()); 4212314564Sdim CGM.addCompilerUsedGlobal(GV); 4213314564Sdim 4214314564Sdim return GV; 4215314564Sdim} 4216314564Sdim 4217198092Srdivackyllvm::Function *CGObjCMac::ModuleInitFunction() { 4218193326Sed // Abuse this interface function as a place to finalize. 4219193326Sed FinishModule(); 4220276479Sdim return nullptr; 4221193326Sed} 4222193326Sed 4223353358Sdimllvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() { 4224193326Sed return ObjCTypes.getGetPropertyFn(); 4225193326Sed} 4226193326Sed 4227353358Sdimllvm::FunctionCallee CGObjCMac::GetPropertySetFunction() { 4228193326Sed return ObjCTypes.getSetPropertyFn(); 4229193326Sed} 4230193326Sed 4231353358Sdimllvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(bool atomic, 4232353358Sdim bool copy) { 4233234353Sdim return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy); 4234234353Sdim} 4235234353Sdim 4236353358Sdimllvm::FunctionCallee CGObjCMac::GetGetStructFunction() { 4237207619Srdivacky return ObjCTypes.getCopyStructFn(); 4238207619Srdivacky} 4239309124Sdim 4240353358Sdimllvm::FunctionCallee CGObjCMac::GetSetStructFunction() { 4241218893Sdim return ObjCTypes.getCopyStructFn(); 4242218893Sdim} 4243207619Srdivacky 4244353358Sdimllvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() { 4245234353Sdim return ObjCTypes.getCppAtomicObjectFunction(); 4246234353Sdim} 4247309124Sdim 4248353358Sdimllvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() { 4249249423Sdim return ObjCTypes.getCppAtomicObjectFunction(); 4250249423Sdim} 4251234353Sdim 4252353358Sdimllvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() { 4253193326Sed return ObjCTypes.getEnumerationMutationFn(); 4254193326Sed} 4255193326Sed 4256210299Sedvoid CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) { 4257210299Sed return EmitTryOrSynchronizedStmt(CGF, S); 4258210299Sed} 4259210299Sed 4260210299Sedvoid CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF, 4261210299Sed const ObjCAtSynchronizedStmt &S) { 4262210299Sed return EmitTryOrSynchronizedStmt(CGF, S); 4263210299Sed} 4264210299Sed 4265212904Sdimnamespace { 4266296417Sdim struct PerformFragileFinally final : EHScopeStack::Cleanup { 4267212904Sdim const Stmt &S; 4268296417Sdim Address SyncArgSlot; 4269296417Sdim Address CallTryExitVar; 4270296417Sdim Address ExceptionData; 4271212904Sdim ObjCTypesHelper &ObjCTypes; 4272212904Sdim PerformFragileFinally(const Stmt *S, 4273296417Sdim Address SyncArgSlot, 4274296417Sdim Address CallTryExitVar, 4275296417Sdim Address ExceptionData, 4276212904Sdim ObjCTypesHelper *ObjCTypes) 4277212904Sdim : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar), 4278212904Sdim ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {} 4279212904Sdim 4280276479Sdim void Emit(CodeGenFunction &CGF, Flags flags) override { 4281212904Sdim // Check whether we need to call objc_exception_try_exit. 4282212904Sdim // In optimized code, this branch will always be folded. 4283212904Sdim llvm::BasicBlock *FinallyCallExit = 4284212904Sdim CGF.createBasicBlock("finally.call_exit"); 4285212904Sdim llvm::BasicBlock *FinallyNoCallExit = 4286212904Sdim CGF.createBasicBlock("finally.no_call_exit"); 4287212904Sdim CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar), 4288212904Sdim FinallyCallExit, FinallyNoCallExit); 4289212904Sdim 4290212904Sdim CGF.EmitBlock(FinallyCallExit); 4291249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(), 4292296417Sdim ExceptionData.getPointer()); 4293212904Sdim 4294212904Sdim CGF.EmitBlock(FinallyNoCallExit); 4295212904Sdim 4296212904Sdim if (isa<ObjCAtTryStmt>(S)) { 4297212904Sdim if (const ObjCAtFinallyStmt* FinallyStmt = 4298212904Sdim cast<ObjCAtTryStmt>(S).getFinallyStmt()) { 4299249423Sdim // Don't try to do the @finally if this is an EH cleanup. 4300249423Sdim if (flags.isForEHCleanup()) return; 4301249423Sdim 4302212904Sdim // Save the current cleanup destination in case there's 4303212904Sdim // control flow inside the finally statement. 4304212904Sdim llvm::Value *CurCleanupDest = 4305212904Sdim CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot()); 4306212904Sdim 4307212904Sdim CGF.EmitStmt(FinallyStmt->getFinallyBody()); 4308212904Sdim 4309212904Sdim if (CGF.HaveInsertPoint()) { 4310212904Sdim CGF.Builder.CreateStore(CurCleanupDest, 4311212904Sdim CGF.getNormalCleanupDestSlot()); 4312212904Sdim } else { 4313212904Sdim // Currently, the end of the cleanup must always exist. 4314212904Sdim CGF.EnsureInsertPoint(); 4315212904Sdim } 4316212904Sdim } 4317212904Sdim } else { 4318212904Sdim // Emit objc_sync_exit(expr); as finally's sole statement for 4319212904Sdim // @synchronized. 4320212904Sdim llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot); 4321249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg); 4322212904Sdim } 4323212904Sdim } 4324212904Sdim }; 4325212904Sdim 4326212904Sdim class FragileHazards { 4327212904Sdim CodeGenFunction &CGF; 4328226633Sdim SmallVector<llvm::Value*, 20> Locals; 4329212904Sdim llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry; 4330212904Sdim 4331212904Sdim llvm::InlineAsm *ReadHazard; 4332212904Sdim llvm::InlineAsm *WriteHazard; 4333212904Sdim 4334212904Sdim llvm::FunctionType *GetAsmFnType(); 4335212904Sdim 4336212904Sdim void collectLocals(); 4337212904Sdim void emitReadHazard(CGBuilderTy &Builder); 4338212904Sdim 4339212904Sdim public: 4340212904Sdim FragileHazards(CodeGenFunction &CGF); 4341212904Sdim 4342212904Sdim void emitWriteHazard(); 4343212904Sdim void emitHazardsInNewBlocks(); 4344212904Sdim }; 4345309124Sdim} // end anonymous namespace 4346212904Sdim 4347212904Sdim/// Create the fragile-ABI read and write hazards based on the current 4348212904Sdim/// state of the function, which is presumed to be immediately prior 4349212904Sdim/// to a @try block. These hazards are used to maintain correct 4350212904Sdim/// semantics in the face of optimization and the fragile ABI's 4351212904Sdim/// cavalier use of setjmp/longjmp. 4352212904SdimFragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) { 4353212904Sdim collectLocals(); 4354212904Sdim 4355212904Sdim if (Locals.empty()) return; 4356212904Sdim 4357212904Sdim // Collect all the blocks in the function. 4358212904Sdim for (llvm::Function::iterator 4359212904Sdim I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I) 4360212904Sdim BlocksBeforeTry.insert(&*I); 4361212904Sdim 4362212904Sdim llvm::FunctionType *AsmFnTy = GetAsmFnType(); 4363212904Sdim 4364212904Sdim // Create a read hazard for the allocas. This inhibits dead-store 4365212904Sdim // optimizations and forces the values to memory. This hazard is 4366212904Sdim // inserted before any 'throwing' calls in the protected scope to 4367212904Sdim // reflect the possibility that the variables might be read from the 4368212904Sdim // catch block if the call throws. 4369212904Sdim { 4370212904Sdim std::string Constraint; 4371212904Sdim for (unsigned I = 0, E = Locals.size(); I != E; ++I) { 4372212904Sdim if (I) Constraint += ','; 4373212904Sdim Constraint += "*m"; 4374212904Sdim } 4375212904Sdim 4376212904Sdim ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false); 4377212904Sdim } 4378212904Sdim 4379212904Sdim // Create a write hazard for the allocas. This inhibits folding 4380212904Sdim // loads across the hazard. This hazard is inserted at the 4381212904Sdim // beginning of the catch path to reflect the possibility that the 4382212904Sdim // variables might have been written within the protected scope. 4383212904Sdim { 4384212904Sdim std::string Constraint; 4385212904Sdim for (unsigned I = 0, E = Locals.size(); I != E; ++I) { 4386212904Sdim if (I) Constraint += ','; 4387212904Sdim Constraint += "=*m"; 4388212904Sdim } 4389212904Sdim 4390212904Sdim WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false); 4391212904Sdim } 4392212904Sdim} 4393212904Sdim 4394212904Sdim/// Emit a write hazard at the current location. 4395212904Sdimvoid FragileHazards::emitWriteHazard() { 4396212904Sdim if (Locals.empty()) return; 4397212904Sdim 4398249423Sdim CGF.EmitNounwindRuntimeCall(WriteHazard, Locals); 4399212904Sdim} 4400212904Sdim 4401212904Sdimvoid FragileHazards::emitReadHazard(CGBuilderTy &Builder) { 4402212904Sdim assert(!Locals.empty()); 4403249423Sdim llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals); 4404249423Sdim call->setDoesNotThrow(); 4405249423Sdim call->setCallingConv(CGF.getRuntimeCC()); 4406212904Sdim} 4407212904Sdim 4408212904Sdim/// Emit read hazards in all the protected blocks, i.e. all the blocks 4409212904Sdim/// which have been inserted since the beginning of the try. 4410212904Sdimvoid FragileHazards::emitHazardsInNewBlocks() { 4411212904Sdim if (Locals.empty()) return; 4412212904Sdim 4413296417Sdim CGBuilderTy Builder(CGF, CGF.getLLVMContext()); 4414212904Sdim 4415212904Sdim // Iterate through all blocks, skipping those prior to the try. 4416212904Sdim for (llvm::Function::iterator 4417212904Sdim FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) { 4418212904Sdim llvm::BasicBlock &BB = *FI; 4419212904Sdim if (BlocksBeforeTry.count(&BB)) continue; 4420212904Sdim 4421212904Sdim // Walk through all the calls in the block. 4422212904Sdim for (llvm::BasicBlock::iterator 4423212904Sdim BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) { 4424212904Sdim llvm::Instruction &I = *BI; 4425212904Sdim 4426212904Sdim // Ignore instructions that aren't non-intrinsic calls. 4427212904Sdim // These are the only calls that can possibly call longjmp. 4428353358Sdim if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) 4429353358Sdim continue; 4430212904Sdim if (isa<llvm::IntrinsicInst>(I)) 4431212904Sdim continue; 4432212904Sdim 4433212904Sdim // Ignore call sites marked nounwind. This may be questionable, 4434212904Sdim // since 'nounwind' doesn't necessarily mean 'does not call longjmp'. 4435353358Sdim if (cast<llvm::CallBase>(I).doesNotThrow()) 4436353358Sdim continue; 4437212904Sdim 4438212904Sdim // Insert a read hazard before the call. This will ensure that 4439212904Sdim // any writes to the locals are performed before making the 4440212904Sdim // call. If the call throws, then this is sufficient to 4441212904Sdim // guarantee correctness as long as it doesn't also write to any 4442212904Sdim // locals. 4443212904Sdim Builder.SetInsertPoint(&BB, BI); 4444212904Sdim emitReadHazard(Builder); 4445212904Sdim } 4446212904Sdim } 4447212904Sdim} 4448212904Sdim 4449296417Sdimstatic void addIfPresent(llvm::DenseSet<llvm::Value*> &S, Address V) { 4450296417Sdim if (V.isValid()) S.insert(V.getPointer()); 4451296417Sdim} 4452296417Sdim 4453212904Sdimvoid FragileHazards::collectLocals() { 4454212904Sdim // Compute a set of allocas to ignore. 4455212904Sdim llvm::DenseSet<llvm::Value*> AllocasToIgnore; 4456212904Sdim addIfPresent(AllocasToIgnore, CGF.ReturnValue); 4457212904Sdim addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest); 4458212904Sdim 4459212904Sdim // Collect all the allocas currently in the function. This is 4460212904Sdim // probably way too aggressive. 4461212904Sdim llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock(); 4462212904Sdim for (llvm::BasicBlock::iterator 4463212904Sdim I = Entry.begin(), E = Entry.end(); I != E; ++I) 4464212904Sdim if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I)) 4465212904Sdim Locals.push_back(&*I); 4466212904Sdim} 4467212904Sdim 4468212904Sdimllvm::FunctionType *FragileHazards::GetAsmFnType() { 4469226633Sdim SmallVector<llvm::Type *, 16> tys(Locals.size()); 4470223017Sdim for (unsigned i = 0, e = Locals.size(); i != e; ++i) 4471223017Sdim tys[i] = Locals[i]->getType(); 4472223017Sdim return llvm::FunctionType::get(CGF.VoidTy, tys, false); 4473212904Sdim} 4474212904Sdim 4475198092Srdivacky/* 4476193326Sed 4477198092Srdivacky Objective-C setjmp-longjmp (sjlj) Exception Handling 4478198092Srdivacky -- 4479193326Sed 4480210299Sed A catch buffer is a setjmp buffer plus: 4481210299Sed - a pointer to the exception that was caught 4482210299Sed - a pointer to the previous exception data buffer 4483210299Sed - two pointers of reserved storage 4484210299Sed Therefore catch buffers form a stack, with a pointer to the top 4485210299Sed of the stack kept in thread-local storage. 4486210299Sed 4487210299Sed objc_exception_try_enter pushes a catch buffer onto the EH stack. 4488210299Sed objc_exception_try_exit pops the given catch buffer, which is 4489210299Sed required to be the top of the EH stack. 4490210299Sed objc_exception_throw pops the top of the EH stack, writes the 4491210299Sed thrown exception into the appropriate field, and longjmps 4492210299Sed to the setjmp buffer. It crashes the process (with a printf 4493210299Sed and an abort()) if there are no catch buffers on the stack. 4494210299Sed objc_exception_extract just reads the exception pointer out of the 4495210299Sed catch buffer. 4496210299Sed 4497210299Sed There's no reason an implementation couldn't use a light-weight 4498210299Sed setjmp here --- something like __builtin_setjmp, but API-compatible 4499210299Sed with the heavyweight setjmp. This will be more important if we ever 4500210299Sed want to implement correct ObjC/C++ exception interactions for the 4501210299Sed fragile ABI. 4502210299Sed 4503210299Sed Note that for this use of setjmp/longjmp to be correct, we may need 4504210299Sed to mark some local variables volatile: if a non-volatile local 4505210299Sed variable is modified between the setjmp and the longjmp, it has 4506210299Sed indeterminate value. For the purposes of LLVM IR, it may be 4507210299Sed sufficient to make loads and stores within the @try (to variables 4508210299Sed declared outside the @try) volatile. This is necessary for 4509210299Sed optimized correctness, but is not currently being done; this is 4510210299Sed being tracked as rdar://problem/8160285 4511210299Sed 4512198092Srdivacky The basic framework for a @try-catch-finally is as follows: 4513198092Srdivacky { 4514193326Sed objc_exception_data d; 4515193326Sed id _rethrow = null; 4516193326Sed bool _call_try_exit = true; 4517198092Srdivacky 4518193326Sed objc_exception_try_enter(&d); 4519193326Sed if (!setjmp(d.jmp_buf)) { 4520198092Srdivacky ... try body ... 4521193326Sed } else { 4522198092Srdivacky // exception path 4523198092Srdivacky id _caught = objc_exception_extract(&d); 4524198092Srdivacky 4525198092Srdivacky // enter new try scope for handlers 4526198092Srdivacky if (!setjmp(d.jmp_buf)) { 4527198092Srdivacky ... match exception and execute catch blocks ... 4528198092Srdivacky 4529198092Srdivacky // fell off end, rethrow. 4530198092Srdivacky _rethrow = _caught; 4531198092Srdivacky ... jump-through-finally to finally_rethrow ... 4532198092Srdivacky } else { 4533198092Srdivacky // exception in catch block 4534198092Srdivacky _rethrow = objc_exception_extract(&d); 4535198092Srdivacky _call_try_exit = false; 4536198092Srdivacky ... jump-through-finally to finally_rethrow ... 4537193326Sed } 4538198092Srdivacky } 4539193326Sed ... jump-through-finally to finally_end ... 4540193326Sed 4541198092Srdivacky finally: 4542193326Sed if (_call_try_exit) 4543198092Srdivacky objc_exception_try_exit(&d); 4544193326Sed 4545193326Sed ... finally block .... 4546193326Sed ... dispatch to finally destination ... 4547193326Sed 4548198092Srdivacky finally_rethrow: 4549193326Sed objc_exception_throw(_rethrow); 4550193326Sed 4551198092Srdivacky finally_end: 4552198092Srdivacky } 4553193326Sed 4554198092Srdivacky This framework differs slightly from the one gcc uses, in that gcc 4555198092Srdivacky uses _rethrow to determine if objc_exception_try_exit should be called 4556198092Srdivacky and if the object should be rethrown. This breaks in the face of 4557198092Srdivacky throwing nil and introduces unnecessary branches. 4558193326Sed 4559198092Srdivacky We specialize this framework for a few particular circumstances: 4560193326Sed 4561198092Srdivacky - If there are no catch blocks, then we avoid emitting the second 4562198092Srdivacky exception handling context. 4563193326Sed 4564198092Srdivacky - If there is a catch-all catch block (i.e. @catch(...) or @catch(id 4565198092Srdivacky e)) we avoid emitting the code to rethrow an uncaught exception. 4566193326Sed 4567198092Srdivacky - FIXME: If there is no @finally block we can do a few more 4568198092Srdivacky simplifications. 4569193326Sed 4570198092Srdivacky Rethrows and Jumps-Through-Finally 4571198092Srdivacky -- 4572193326Sed 4573210299Sed '@throw;' is supported by pushing the currently-caught exception 4574210299Sed onto ObjCEHStack while the @catch blocks are emitted. 4575193326Sed 4576210299Sed Branches through the @finally block are handled with an ordinary 4577210299Sed normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC 4578210299Sed exceptions are not compatible with C++ exceptions, and this is 4579210299Sed hardly the only place where this will go wrong. 4580193326Sed 4581210299Sed @synchronized(expr) { stmt; } is emitted as if it were: 4582210299Sed id synch_value = expr; 4583210299Sed objc_sync_enter(synch_value); 4584210299Sed @try { stmt; } @finally { objc_sync_exit(synch_value); } 4585193326Sed*/ 4586193326Sed 4587193326Sedvoid CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 4588193326Sed const Stmt &S) { 4589193326Sed bool isTry = isa<ObjCAtTryStmt>(S); 4590198092Srdivacky 4591210299Sed // A destination for the fall-through edges of the catch handlers to 4592210299Sed // jump to. 4593210299Sed CodeGenFunction::JumpDest FinallyEnd = 4594210299Sed CGF.getJumpDestInCurrentScope("finally.end"); 4595210299Sed 4596210299Sed // A destination for the rethrow edge of the catch handlers to jump 4597210299Sed // to. 4598210299Sed CodeGenFunction::JumpDest FinallyRethrow = 4599210299Sed CGF.getJumpDestInCurrentScope("finally.rethrow"); 4600210299Sed 4601193326Sed // For @synchronized, call objc_sync_enter(sync.expr). The 4602193326Sed // evaluation of the expression must occur before we enter the 4603212904Sdim // @synchronized. We can't avoid a temp here because we need the 4604212904Sdim // value to be preserved. If the backend ever does liveness 4605212904Sdim // correctly after setjmp, this will be unnecessary. 4606296417Sdim Address SyncArgSlot = Address::invalid(); 4607193326Sed if (!isTry) { 4608212904Sdim llvm::Value *SyncArg = 4609193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 4610193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); 4611249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg); 4612212904Sdim 4613296417Sdim SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), 4614296417Sdim CGF.getPointerAlign(), "sync.arg"); 4615212904Sdim CGF.Builder.CreateStore(SyncArg, SyncArgSlot); 4616193326Sed } 4617193326Sed 4618212904Sdim // Allocate memory for the setjmp buffer. This needs to be kept 4619212904Sdim // live throughout the try and catch blocks. 4620296417Sdim Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy, 4621296417Sdim CGF.getPointerAlign(), 4622296417Sdim "exceptiondata.ptr"); 4623210299Sed 4624212904Sdim // Create the fragile hazards. Note that this will not capture any 4625212904Sdim // of the allocas required for exception processing, but will 4626212904Sdim // capture the current basic block (which extends all the way to the 4627212904Sdim // setjmp call) as "before the @try". 4628212904Sdim FragileHazards Hazards(CGF); 4629212904Sdim 4630210299Sed // Create a flag indicating whether the cleanup needs to call 4631210299Sed // objc_exception_try_exit. This is true except when 4632210299Sed // - no catches match and we're branching through the cleanup 4633210299Sed // just to rethrow the exception, or 4634210299Sed // - a catch matched and we're falling out of the catch handler. 4635212904Sdim // The setjmp-safety rule here is that we should always store to this 4636212904Sdim // variable in a place that dominates the branch through the cleanup 4637212904Sdim // without passing through any setjmps. 4638296417Sdim Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), 4639296417Sdim CharUnits::One(), 4640296417Sdim "_call_try_exit"); 4641198092Srdivacky 4642218893Sdim // A slot containing the exception to rethrow. Only needed when we 4643218893Sdim // have both a @catch and a @finally. 4644296417Sdim Address PropagatingExnVar = Address::invalid(); 4645218893Sdim 4646210299Sed // Push a normal cleanup to leave the try scope. 4647249423Sdim CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S, 4648212904Sdim SyncArgSlot, 4649212904Sdim CallTryExitVar, 4650212904Sdim ExceptionData, 4651212904Sdim &ObjCTypes); 4652193326Sed 4653210299Sed // Enter a try block: 4654210299Sed // - Call objc_exception_try_enter to push ExceptionData on top of 4655210299Sed // the EH stack. 4656288943Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), 4657296417Sdim ExceptionData.getPointer()); 4658210299Sed 4659210299Sed // - Call setjmp on the exception data buffer. 4660210299Sed llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); 4661210299Sed llvm::Value *GEPIndexes[] = { Zero, Zero, Zero }; 4662288943Sdim llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP( 4663296417Sdim ObjCTypes.ExceptionDataTy, ExceptionData.getPointer(), GEPIndexes, 4664296417Sdim "setjmp_buffer"); 4665288943Sdim llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall( 4666288943Sdim ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result"); 4667234353Sdim SetJmpResult->setCanReturnTwice(); 4668210299Sed 4669210299Sed // If setjmp returned 0, enter the protected block; otherwise, 4670210299Sed // branch to the handler. 4671193326Sed llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); 4672193326Sed llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); 4673210299Sed llvm::Value *DidCatch = 4674212904Sdim CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); 4675212904Sdim CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock); 4676193326Sed 4677210299Sed // Emit the protected block. 4678193326Sed CGF.EmitBlock(TryBlock); 4679212904Sdim CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar); 4680198092Srdivacky CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() 4681210299Sed : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); 4682198092Srdivacky 4683212904Sdim CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP(); 4684212904Sdim 4685210299Sed // Emit the exception handler block. 4686193326Sed CGF.EmitBlock(TryHandler); 4687193326Sed 4688212904Sdim // Don't optimize loads of the in-scope locals across this point. 4689212904Sdim Hazards.emitWriteHazard(); 4690210299Sed 4691210299Sed // For a @synchronized (or a @try with no catches), just branch 4692210299Sed // through the cleanup to the rethrow block. 4693210299Sed if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) { 4694210299Sed // Tell the cleanup not to re-pop the exit. 4695212904Sdim CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar); 4696193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 4697210299Sed 4698210299Sed // Otherwise, we have to match against the caught exceptions. 4699210299Sed } else { 4700212904Sdim // Retrieve the exception object. We may emit multiple blocks but 4701212904Sdim // nothing can cross this so the value is already in SSA form. 4702212904Sdim llvm::CallInst *Caught = 4703249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), 4704296417Sdim ExceptionData.getPointer(), "caught"); 4705212904Sdim 4706210299Sed // Push the exception to rethrow onto the EH value stack for the 4707210299Sed // benefit of any @throws in the handlers. 4708210299Sed CGF.ObjCEHValueStack.push_back(Caught); 4709210299Sed 4710207619Srdivacky const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S); 4711198092Srdivacky 4712276479Sdim bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr); 4713193326Sed 4714276479Sdim llvm::BasicBlock *CatchBlock = nullptr; 4715276479Sdim llvm::BasicBlock *CatchHandler = nullptr; 4716212904Sdim if (HasFinally) { 4717218893Sdim // Save the currently-propagating exception before 4718218893Sdim // objc_exception_try_enter clears the exception slot. 4719218893Sdim PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(), 4720296417Sdim CGF.getPointerAlign(), 4721218893Sdim "propagating_exception"); 4722218893Sdim CGF.Builder.CreateStore(Caught, PropagatingExnVar); 4723218893Sdim 4724212904Sdim // Enter a new exception try block (in case a @catch block 4725212904Sdim // throws an exception). 4726249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), 4727296417Sdim ExceptionData.getPointer()); 4728210299Sed 4729212904Sdim llvm::CallInst *SetJmpResult = 4730249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), 4731249423Sdim SetJmpBuffer, "setjmp.result"); 4732234353Sdim SetJmpResult->setCanReturnTwice(); 4733198092Srdivacky 4734212904Sdim llvm::Value *Threw = 4735212904Sdim CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); 4736198092Srdivacky 4737212904Sdim CatchBlock = CGF.createBasicBlock("catch"); 4738212904Sdim CatchHandler = CGF.createBasicBlock("catch_for_catch"); 4739212904Sdim CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock); 4740212904Sdim 4741212904Sdim CGF.EmitBlock(CatchBlock); 4742212904Sdim } 4743212904Sdim 4744212904Sdim CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar); 4745212904Sdim 4746193326Sed // Handle catch list. As a special case we check if everything is 4747193326Sed // matched and avoid generating code for falling off the end if 4748193326Sed // so. 4749193326Sed bool AllMatched = false; 4750207619Srdivacky for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) { 4751207619Srdivacky const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I); 4752193326Sed 4753207619Srdivacky const VarDecl *CatchParam = CatchStmt->getCatchParamDecl(); 4754276479Sdim const ObjCObjectPointerType *OPT = nullptr; 4755193326Sed 4756193326Sed // catch(...) always matches. 4757193326Sed if (!CatchParam) { 4758193326Sed AllMatched = true; 4759193326Sed } else { 4760198092Srdivacky OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>(); 4761198092Srdivacky 4762210299Sed // catch(id e) always matches under this ABI, since only 4763210299Sed // ObjC exceptions end up here in the first place. 4764193326Sed // FIXME: For the time being we also match id<X>; this should 4765193326Sed // be rejected by Sema instead. 4766198092Srdivacky if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())) 4767193326Sed AllMatched = true; 4768193326Sed } 4769198092Srdivacky 4770210299Sed // If this is a catch-all, we don't need to test anything. 4771198092Srdivacky if (AllMatched) { 4772210299Sed CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF); 4773210299Sed 4774193326Sed if (CatchParam) { 4775218893Sdim CGF.EmitAutoVarDecl(*CatchParam); 4776193326Sed assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); 4777210299Sed 4778210299Sed // These types work out because ConvertType(id) == i8*. 4779296417Sdim EmitInitOfCatchParam(CGF, Caught, CatchParam); 4780193326Sed } 4781198092Srdivacky 4782193326Sed CGF.EmitStmt(CatchStmt->getCatchBody()); 4783210299Sed 4784210299Sed // The scope of the catch variable ends right here. 4785210299Sed CatchVarCleanups.ForceCleanup(); 4786210299Sed 4787193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 4788193326Sed break; 4789193326Sed } 4790198092Srdivacky 4791198092Srdivacky assert(OPT && "Unexpected non-object pointer type in @catch"); 4792208600Srdivacky const ObjCObjectType *ObjTy = OPT->getObjectType(); 4793210299Sed 4794210299Sed // FIXME: @catch (Class c) ? 4795208600Srdivacky ObjCInterfaceDecl *IDecl = ObjTy->getInterface(); 4796208600Srdivacky assert(IDecl && "Catch parameter must have Objective-C type!"); 4797193326Sed 4798193326Sed // Check if the @catch block matches the exception object. 4799249423Sdim llvm::Value *Class = EmitClassRef(CGF, IDecl); 4800198092Srdivacky 4801249423Sdim llvm::Value *matchArgs[] = { Class, Caught }; 4802210299Sed llvm::CallInst *Match = 4803249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(), 4804249423Sdim matchArgs, "match"); 4805198092Srdivacky 4806210299Sed llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match"); 4807210299Sed llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next"); 4808198092Srdivacky 4809198092Srdivacky CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"), 4810193326Sed MatchedBlock, NextCatchBlock); 4811198092Srdivacky 4812193326Sed // Emit the @catch block. 4813193326Sed CGF.EmitBlock(MatchedBlock); 4814210299Sed 4815210299Sed // Collect any cleanups for the catch variable. The scope lasts until 4816210299Sed // the end of the catch body. 4817212904Sdim CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF); 4818210299Sed 4819218893Sdim CGF.EmitAutoVarDecl(*CatchParam); 4820193326Sed assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); 4821193326Sed 4822210299Sed // Initialize the catch variable. 4823198092Srdivacky llvm::Value *Tmp = 4824198092Srdivacky CGF.Builder.CreateBitCast(Caught, 4825226633Sdim CGF.ConvertType(CatchParam->getType())); 4826296417Sdim EmitInitOfCatchParam(CGF, Tmp, CatchParam); 4827198092Srdivacky 4828193326Sed CGF.EmitStmt(CatchStmt->getCatchBody()); 4829210299Sed 4830210299Sed // We're done with the catch variable. 4831210299Sed CatchVarCleanups.ForceCleanup(); 4832210299Sed 4833193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 4834198092Srdivacky 4835193326Sed CGF.EmitBlock(NextCatchBlock); 4836193326Sed } 4837193326Sed 4838210299Sed CGF.ObjCEHValueStack.pop_back(); 4839210299Sed 4840212904Sdim // If nothing wanted anything to do with the caught exception, 4841212904Sdim // kill the extract call. 4842212904Sdim if (Caught->use_empty()) 4843212904Sdim Caught->eraseFromParent(); 4844212904Sdim 4845212904Sdim if (!AllMatched) 4846193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 4847198092Srdivacky 4848212904Sdim if (HasFinally) { 4849212904Sdim // Emit the exception handler for the @catch blocks. 4850212904Sdim CGF.EmitBlock(CatchHandler); 4851210299Sed 4852212904Sdim // In theory we might now need a write hazard, but actually it's 4853212904Sdim // unnecessary because there's no local-accessing code between 4854212904Sdim // the try's write hazard and here. 4855212904Sdim //Hazards.emitWriteHazard(); 4856210299Sed 4857218893Sdim // Extract the new exception and save it to the 4858218893Sdim // propagating-exception slot. 4859296417Sdim assert(PropagatingExnVar.isValid()); 4860218893Sdim llvm::CallInst *NewCaught = 4861249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), 4862296417Sdim ExceptionData.getPointer(), "caught"); 4863218893Sdim CGF.Builder.CreateStore(NewCaught, PropagatingExnVar); 4864218893Sdim 4865212904Sdim // Don't pop the catch handler; the throw already did. 4866212904Sdim CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar); 4867212904Sdim CGF.EmitBranchThroughCleanup(FinallyRethrow); 4868212904Sdim } 4869193326Sed } 4870198092Srdivacky 4871212904Sdim // Insert read hazards as required in the new blocks. 4872212904Sdim Hazards.emitHazardsInNewBlocks(); 4873212904Sdim 4874210299Sed // Pop the cleanup. 4875212904Sdim CGF.Builder.restoreIP(TryFallthroughIP); 4876212904Sdim if (CGF.HaveInsertPoint()) 4877212904Sdim CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar); 4878210299Sed CGF.PopCleanupBlock(); 4879212904Sdim CGF.EmitBlock(FinallyEnd.getBlock(), true); 4880193326Sed 4881210299Sed // Emit the rethrow block. 4882212904Sdim CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); 4883212904Sdim CGF.EmitBlock(FinallyRethrow.getBlock(), true); 4884210299Sed if (CGF.HaveInsertPoint()) { 4885218893Sdim // If we have a propagating-exception variable, check it. 4886218893Sdim llvm::Value *PropagatingExn; 4887296417Sdim if (PropagatingExnVar.isValid()) { 4888218893Sdim PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar); 4889212904Sdim 4890218893Sdim // Otherwise, just look in the buffer for the exception to throw. 4891218893Sdim } else { 4892218893Sdim llvm::CallInst *Caught = 4893249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), 4894296417Sdim ExceptionData.getPointer()); 4895218893Sdim PropagatingExn = Caught; 4896218893Sdim } 4897218893Sdim 4898249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(), 4899249423Sdim PropagatingExn); 4900210299Sed CGF.Builder.CreateUnreachable(); 4901193326Sed } 4902193326Sed 4903212904Sdim CGF.Builder.restoreIP(SavedIP); 4904193326Sed} 4905193326Sed 4906193326Sedvoid CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 4907249423Sdim const ObjCAtThrowStmt &S, 4908249423Sdim bool ClearInsertionPoint) { 4909193326Sed llvm::Value *ExceptionAsObject; 4910198092Srdivacky 4911193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 4912226633Sdim llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr); 4913198092Srdivacky ExceptionAsObject = 4914226633Sdim CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy); 4915193326Sed } else { 4916198092Srdivacky assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && 4917193326Sed "Unexpected rethrow outside @catch block."); 4918193326Sed ExceptionAsObject = CGF.ObjCEHValueStack.back(); 4919193326Sed } 4920198092Srdivacky 4921249423Sdim CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject) 4922210299Sed ->setDoesNotReturn(); 4923193326Sed CGF.Builder.CreateUnreachable(); 4924193326Sed 4925193326Sed // Clear the insertion point to indicate we are in unreachable code. 4926249423Sdim if (ClearInsertionPoint) 4927249423Sdim CGF.Builder.ClearInsertionPoint(); 4928193326Sed} 4929193326Sed 4930193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak 4931193326Sed/// object: objc_read_weak (id *src) 4932193326Sed/// 4933193326Sedllvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 4934296417Sdim Address AddrWeakObj) { 4935296417Sdim llvm::Type* DestTy = AddrWeakObj.getElementType(); 4936198092Srdivacky AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, 4937198092Srdivacky ObjCTypes.PtrObjectPtrTy); 4938249423Sdim llvm::Value *read_weak = 4939249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), 4940296417Sdim AddrWeakObj.getPointer(), "weakread"); 4941193326Sed read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); 4942193326Sed return read_weak; 4943193326Sed} 4944193326Sed 4945193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. 4946193326Sed/// objc_assign_weak (id src, id *dst) 4947193326Sed/// 4948193326Sedvoid CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 4949296417Sdim llvm::Value *src, Address dst) { 4950226633Sdim llvm::Type * SrcTy = src->getType(); 4951193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 4952243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 4953193326Sed assert(Size <= 8 && "does not support size > 8"); 4954314564Sdim src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty) 4955314564Sdim : CGF.Builder.CreateBitCast(src, CGM.Int64Ty); 4956193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 4957193326Sed } 4958193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 4959193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 4960296417Sdim llvm::Value *args[] = { src, dst.getPointer() }; 4961249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), 4962249423Sdim args, "weakassign"); 4963193326Sed} 4964193326Sed 4965193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. 4966193326Sed/// objc_assign_global (id src, id *dst) 4967193326Sed/// 4968193326Sedvoid CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 4969296417Sdim llvm::Value *src, Address dst, 4970212904Sdim bool threadlocal) { 4971226633Sdim llvm::Type * SrcTy = src->getType(); 4972193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 4973243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 4974193326Sed assert(Size <= 8 && "does not support size > 8"); 4975314564Sdim src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty) 4976314564Sdim : CGF.Builder.CreateBitCast(src, CGM.Int64Ty); 4977193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 4978193326Sed } 4979193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 4980193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 4981296417Sdim llvm::Value *args[] = { src, dst.getPointer() }; 4982212904Sdim if (!threadlocal) 4983249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), 4984249423Sdim args, "globalassign"); 4985212904Sdim else 4986249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), 4987249423Sdim args, "threadlocalassign"); 4988193326Sed} 4989193326Sed 4990193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. 4991198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset) 4992193326Sed/// 4993193326Sedvoid CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 4994296417Sdim llvm::Value *src, Address dst, 4995198092Srdivacky llvm::Value *ivarOffset) { 4996198092Srdivacky assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL"); 4997226633Sdim llvm::Type * SrcTy = src->getType(); 4998193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 4999243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 5000193326Sed assert(Size <= 8 && "does not support size > 8"); 5001314564Sdim src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty) 5002314564Sdim : CGF.Builder.CreateBitCast(src, CGM.Int64Ty); 5003193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5004193326Sed } 5005193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5006193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5007296417Sdim llvm::Value *args[] = { src, dst.getPointer(), ivarOffset }; 5008249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); 5009193326Sed} 5010193326Sed 5011193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. 5012193326Sed/// objc_assign_strongCast (id src, id *dst) 5013193326Sed/// 5014193326Sedvoid CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 5015296417Sdim llvm::Value *src, Address dst) { 5016226633Sdim llvm::Type * SrcTy = src->getType(); 5017193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5018243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 5019193326Sed assert(Size <= 8 && "does not support size > 8"); 5020314564Sdim src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty) 5021314564Sdim : CGF.Builder.CreateBitCast(src, CGM.Int64Ty); 5022193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5023193326Sed } 5024193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5025193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5026296417Sdim llvm::Value *args[] = { src, dst.getPointer() }; 5027249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), 5028296417Sdim args, "strongassign"); 5029193326Sed} 5030193326Sed 5031198092Srdivackyvoid CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 5032296417Sdim Address DestPtr, 5033296417Sdim Address SrcPtr, 5034210299Sed llvm::Value *size) { 5035198092Srdivacky SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); 5036198092Srdivacky DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); 5037296417Sdim llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), size }; 5038249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); 5039198092Srdivacky} 5040198092Srdivacky 5041193326Sed/// EmitObjCValueForIvar - Code Gen for ivar reference. 5042193326Sed/// 5043193326SedLValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 5044193326Sed QualType ObjectTy, 5045193326Sed llvm::Value *BaseValue, 5046193326Sed const ObjCIvarDecl *Ivar, 5047193326Sed unsigned CVRQualifiers) { 5048208600Srdivacky const ObjCInterfaceDecl *ID = 5049360784Sdim ObjectTy->castAs<ObjCObjectType>()->getInterface(); 5050193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 5051193326Sed EmitIvarOffset(CGF, ID, Ivar)); 5052193326Sed} 5053193326Sed 5054193326Sedllvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 5055193326Sed const ObjCInterfaceDecl *Interface, 5056193326Sed const ObjCIvarDecl *Ivar) { 5057193326Sed uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar); 5058193326Sed return llvm::ConstantInt::get( 5059198092Srdivacky CGM.getTypes().ConvertType(CGM.getContext().LongTy), 5060198092Srdivacky Offset); 5061193326Sed} 5062193326Sed 5063193326Sed/* *** Private Interface *** */ 5064193326Sed 5065321369Sdimstd::string CGObjCCommonMac::GetSectionName(StringRef Section, 5066321369Sdim StringRef MachOAttributes) { 5067321369Sdim switch (CGM.getTriple().getObjectFormat()) { 5068353358Sdim case llvm::Triple::UnknownObjectFormat: 5069321369Sdim llvm_unreachable("unexpected object file format"); 5070321369Sdim case llvm::Triple::MachO: { 5071321369Sdim if (MachOAttributes.empty()) 5072321369Sdim return ("__DATA," + Section).str(); 5073321369Sdim return ("__DATA," + Section + "," + MachOAttributes).str(); 5074321369Sdim } 5075321369Sdim case llvm::Triple::ELF: 5076321369Sdim assert(Section.substr(0, 2) == "__" && 5077321369Sdim "expected the name to begin with __"); 5078321369Sdim return Section.substr(2).str(); 5079321369Sdim case llvm::Triple::COFF: 5080321369Sdim assert(Section.substr(0, 2) == "__" && 5081321369Sdim "expected the name to begin with __"); 5082321369Sdim return ("." + Section.substr(2) + "$B").str(); 5083353358Sdim case llvm::Triple::Wasm: 5084353358Sdim case llvm::Triple::XCOFF: 5085353358Sdim llvm::report_fatal_error( 5086353358Sdim "Objective-C support is unimplemented for object file format."); 5087321369Sdim } 5088353358Sdim 5089353358Sdim llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType enum"); 5090321369Sdim} 5091321369Sdim 5092193326Sed/// EmitImageInfo - Emit the image info marker used to encode some module 5093193326Sed/// level information. 5094193326Sed/// 5095193326Sed/// See: <rdr://4810609&4810587&4810587> 5096193326Sed/// struct IMAGE_INFO { 5097193326Sed/// unsigned version; 5098193326Sed/// unsigned flags; 5099193326Sed/// }; 5100193326Sedenum ImageInfoFlags { 5101276479Sdim eImageInfo_FixAndContinue = (1 << 0), // This flag is no longer set by clang. 5102198092Srdivacky eImageInfo_GarbageCollected = (1 << 1), 5103198092Srdivacky eImageInfo_GCOnly = (1 << 2), 5104276479Sdim eImageInfo_OptimizedByDyld = (1 << 3), // This flag is set by the dyld shared cache. 5105193326Sed 5106207619Srdivacky // A flag indicating that the module has no instances of a @synthesize of a 5107207619Srdivacky // superclass variable. <rdar://problem/6803242> 5108276479Sdim eImageInfo_CorrectedSynthesize = (1 << 4), // This flag is no longer set by clang. 5109309124Sdim eImageInfo_ImageIsSimulated = (1 << 5), 5110309124Sdim eImageInfo_ClassProperties = (1 << 6) 5111193326Sed}; 5112193326Sed 5113207619Srdivackyvoid CGObjCCommonMac::EmitImageInfo() { 5114193326Sed unsigned version = 0; // Version is unused? 5115321369Sdim std::string Section = 5116321369Sdim (ObjCABI == 1) 5117321369Sdim ? "__OBJC,__image_info,regular" 5118321369Sdim : GetSectionName("__objc_imageinfo", "regular,no_dead_strip"); 5119193326Sed 5120234353Sdim // Generate module-level named metadata to convey this information to the 5121234353Sdim // linker and code-gen. 5122234353Sdim llvm::Module &Mod = CGM.getModule(); 5123198092Srdivacky 5124234353Sdim // Add the ObjC ABI version to the module flags. 5125234353Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI); 5126234353Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version", 5127234353Sdim version); 5128234353Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section", 5129321369Sdim llvm::MDString::get(VMContext, Section)); 5130193326Sed 5131234353Sdim if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { 5132234353Sdim // Non-GC overrides those files which specify GC. 5133234353Sdim Mod.addModuleFlag(llvm::Module::Override, 5134234353Sdim "Objective-C Garbage Collection", (uint32_t)0); 5135234353Sdim } else { 5136234353Sdim // Add the ObjC garbage collection value. 5137234353Sdim Mod.addModuleFlag(llvm::Module::Error, 5138234353Sdim "Objective-C Garbage Collection", 5139234353Sdim eImageInfo_GarbageCollected); 5140193326Sed 5141234353Sdim if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { 5142234353Sdim // Add the ObjC GC Only value. 5143234353Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only", 5144234353Sdim eImageInfo_GCOnly); 5145234353Sdim 5146234353Sdim // Require that GC be specified and set to eImageInfo_GarbageCollected. 5147280031Sdim llvm::Metadata *Ops[2] = { 5148280031Sdim llvm::MDString::get(VMContext, "Objective-C Garbage Collection"), 5149280031Sdim llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( 5150280031Sdim llvm::Type::getInt32Ty(VMContext), eImageInfo_GarbageCollected))}; 5151234353Sdim Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only", 5152234353Sdim llvm::MDNode::get(VMContext, Ops)); 5153234353Sdim } 5154234353Sdim } 5155239462Sdim 5156239462Sdim // Indicate whether we're compiling this to run on a simulator. 5157327952Sdim if (CGM.getTarget().getTriple().isSimulatorEnvironment()) 5158239462Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated", 5159239462Sdim eImageInfo_ImageIsSimulated); 5160309124Sdim 5161309124Sdim // Indicate whether we are generating class properties. 5162309124Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties", 5163309124Sdim eImageInfo_ClassProperties); 5164193326Sed} 5165193326Sed 5166193326Sed// struct objc_module { 5167193326Sed// unsigned long version; 5168193326Sed// unsigned long size; 5169193326Sed// const char *name; 5170193326Sed// Symtab symtab; 5171193326Sed// }; 5172193326Sed 5173193326Sed// FIXME: Get from somewhere 5174193326Sedstatic const int ModuleVersion = 7; 5175193326Sed 5176193326Sedvoid CGObjCMac::EmitModuleInfo() { 5177243830Sdim uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy); 5178198092Srdivacky 5179314564Sdim ConstantInitBuilder builder(CGM); 5180314564Sdim auto values = builder.beginStruct(ObjCTypes.ModuleTy); 5181314564Sdim values.addInt(ObjCTypes.LongTy, ModuleVersion); 5182314564Sdim values.addInt(ObjCTypes.LongTy, Size); 5183314564Sdim // This used to be the filename, now it is unused. <rdr://4327263> 5184314564Sdim values.add(GetClassName(StringRef(""))); 5185314564Sdim values.add(EmitModuleSymbols()); 5186314564Sdim CreateMetadataVar("OBJC_MODULES", values, 5187296417Sdim "__OBJC,__module_info,regular,no_dead_strip", 5188296417Sdim CGM.getPointerAlign(), true); 5189193326Sed} 5190193326Sed 5191193326Sedllvm::Constant *CGObjCMac::EmitModuleSymbols() { 5192193326Sed unsigned NumClasses = DefinedClasses.size(); 5193193326Sed unsigned NumCategories = DefinedCategories.size(); 5194193326Sed 5195193326Sed // Return null if no symbols were defined. 5196193326Sed if (!NumClasses && !NumCategories) 5197193326Sed return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy); 5198193326Sed 5199314564Sdim ConstantInitBuilder builder(CGM); 5200314564Sdim auto values = builder.beginStruct(); 5201314564Sdim values.addInt(ObjCTypes.LongTy, 0); 5202314564Sdim values.addNullPointer(ObjCTypes.SelectorPtrTy); 5203314564Sdim values.addInt(ObjCTypes.ShortTy, NumClasses); 5204314564Sdim values.addInt(ObjCTypes.ShortTy, NumCategories); 5205193326Sed 5206193326Sed // The runtime expects exactly the list of defined classes followed 5207193326Sed // by the list of defined categories, in a single array. 5208314564Sdim auto array = values.beginArray(ObjCTypes.Int8PtrTy); 5209276479Sdim for (unsigned i=0; i<NumClasses; i++) { 5210276479Sdim const ObjCInterfaceDecl *ID = ImplementedClasses[i]; 5211276479Sdim assert(ID); 5212276479Sdim if (ObjCImplementationDecl *IMP = ID->getImplementation()) 5213276479Sdim // We are implementing a weak imported interface. Give it external linkage 5214276479Sdim if (ID->isWeakImported() && !IMP->isWeakImported()) 5215276479Sdim DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage); 5216314564Sdim 5217314564Sdim array.addBitCast(DefinedClasses[i], ObjCTypes.Int8PtrTy); 5218276479Sdim } 5219193326Sed for (unsigned i=0; i<NumCategories; i++) 5220314564Sdim array.addBitCast(DefinedCategories[i], ObjCTypes.Int8PtrTy); 5221193326Sed 5222314564Sdim array.finishAndAddTo(values); 5223193326Sed 5224280031Sdim llvm::GlobalVariable *GV = CreateMetadataVar( 5225314564Sdim "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip", 5226296417Sdim CGM.getPointerAlign(), true); 5227193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy); 5228193326Sed} 5229193326Sed 5230249423Sdimllvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF, 5231249423Sdim IdentifierInfo *II) { 5232224145Sdim LazySymbols.insert(II); 5233341825Sdim 5234224145Sdim llvm::GlobalVariable *&Entry = ClassReferences[II]; 5235341825Sdim 5236193326Sed if (!Entry) { 5237198092Srdivacky llvm::Constant *Casted = 5238276479Sdim llvm::ConstantExpr::getBitCast(GetClassName(II->getName()), 5239224145Sdim ObjCTypes.ClassPtrTy); 5240280031Sdim Entry = CreateMetadataVar( 5241280031Sdim "OBJC_CLASS_REFERENCES_", Casted, 5242296417Sdim "__OBJC,__cls_refs,literal_pointers,no_dead_strip", 5243296417Sdim CGM.getPointerAlign(), true); 5244193326Sed } 5245341825Sdim 5246296417Sdim return CGF.Builder.CreateAlignedLoad(Entry, CGF.getPointerAlign()); 5247193326Sed} 5248193326Sed 5249249423Sdimllvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF, 5250224145Sdim const ObjCInterfaceDecl *ID) { 5251309124Sdim // If the class has the objc_runtime_visible attribute, we need to 5252309124Sdim // use the Objective-C runtime to get the class. 5253309124Sdim if (ID->hasAttr<ObjCRuntimeVisibleAttr>()) 5254309124Sdim return EmitClassRefViaRuntime(CGF, ID, ObjCTypes); 5255309124Sdim 5256341825Sdim IdentifierInfo *RuntimeName = 5257341825Sdim &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString()); 5258341825Sdim return EmitClassRefFromId(CGF, RuntimeName); 5259224145Sdim} 5260224145Sdim 5261249423Sdimllvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { 5262224145Sdim IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool"); 5263249423Sdim return EmitClassRefFromId(CGF, II); 5264224145Sdim} 5265224145Sdim 5266296417Sdimllvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) { 5267360784Sdim return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel)); 5268296417Sdim} 5269296417Sdim 5270360784SdimAddress CGObjCMac::EmitSelectorAddr(Selector Sel) { 5271360784Sdim CharUnits Align = CGM.getPointerAlign(); 5272296417Sdim 5273193326Sed llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; 5274193326Sed if (!Entry) { 5275198092Srdivacky llvm::Constant *Casted = 5276193326Sed llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), 5277193326Sed ObjCTypes.SelectorPtrTy); 5278280031Sdim Entry = CreateMetadataVar( 5279280031Sdim "OBJC_SELECTOR_REFERENCES_", Casted, 5280296417Sdim "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true); 5281249423Sdim Entry->setExternallyInitialized(true); 5282193326Sed } 5283193326Sed 5284296417Sdim return Address(Entry, Align); 5285193326Sed} 5286193326Sed 5287276479Sdimllvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) { 5288276479Sdim llvm::GlobalVariable *&Entry = ClassNames[RuntimeName]; 5289276479Sdim if (!Entry) 5290314564Sdim Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName); 5291276479Sdim return getConstantGEP(VMContext, Entry, 0, 0); 5292193326Sed} 5293193326Sed 5294212904Sdimllvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) { 5295212904Sdim llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator 5296212904Sdim I = MethodDefinitions.find(MD); 5297212904Sdim if (I != MethodDefinitions.end()) 5298212904Sdim return I->second; 5299212904Sdim 5300276479Sdim return nullptr; 5301212904Sdim} 5302212904Sdim 5303193326Sed/// GetIvarLayoutName - Returns a unique constant for the given 5304193326Sed/// ivar layout bitmap. 5305193326Sedllvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, 5306198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 5307193326Sed return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 5308193326Sed} 5309193326Sed 5310296417Sdimvoid IvarLayoutBuilder::visitRecord(const RecordType *RT, 5311296417Sdim CharUnits offset) { 5312193326Sed const RecordDecl *RD = RT->getDecl(); 5313198092Srdivacky 5314296417Sdim // If this is a union, remember that we had one, because it might mess 5315296417Sdim // up the ordering of layout entries. 5316296417Sdim if (RD->isUnion()) 5317296417Sdim IsDisordered = true; 5318296417Sdim 5319296417Sdim const ASTRecordLayout *recLayout = nullptr; 5320296417Sdim visitAggregate(RD->field_begin(), RD->field_end(), offset, 5321296417Sdim [&](const FieldDecl *field) -> CharUnits { 5322296417Sdim if (!recLayout) 5323296417Sdim recLayout = &CGM.getContext().getASTRecordLayout(RD); 5324296417Sdim auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex()); 5325296417Sdim return CGM.getContext().toCharUnitsFromBits(offsetInBits); 5326296417Sdim }); 5327193326Sed} 5328193326Sed 5329296417Sdimtemplate <class Iterator, class GetOffsetFn> 5330341825Sdimvoid IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end, 5331296417Sdim CharUnits aggregateOffset, 5332296417Sdim const GetOffsetFn &getOffset) { 5333296417Sdim for (; begin != end; ++begin) { 5334296417Sdim auto field = *begin; 5335198092Srdivacky 5336296417Sdim // Skip over bitfields. 5337296417Sdim if (field->isBitField()) { 5338193326Sed continue; 5339193326Sed } 5340193326Sed 5341296417Sdim // Compute the offset of the field within the aggregate. 5342296417Sdim CharUnits fieldOffset = aggregateOffset + getOffset(field); 5343193326Sed 5344296417Sdim visitField(field, fieldOffset); 5345296417Sdim } 5346296417Sdim} 5347198092Srdivacky 5348296417Sdim/// Collect layout information for the given fields into IvarsInfo. 5349296417Sdimvoid IvarLayoutBuilder::visitField(const FieldDecl *field, 5350296417Sdim CharUnits fieldOffset) { 5351296417Sdim QualType fieldType = field->getType(); 5352198092Srdivacky 5353296417Sdim // Drill down into arrays. 5354296417Sdim uint64_t numElts = 1; 5355327952Sdim if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) { 5356327952Sdim numElts = 0; 5357327952Sdim fieldType = arrayType->getElementType(); 5358327952Sdim } 5359327952Sdim // Unlike incomplete arrays, constant arrays can be nested. 5360296417Sdim while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) { 5361296417Sdim numElts *= arrayType->getSize().getZExtValue(); 5362296417Sdim fieldType = arrayType->getElementType(); 5363296417Sdim } 5364198092Srdivacky 5365296417Sdim assert(!fieldType->isArrayType() && "ivar of non-constant array type?"); 5366296417Sdim 5367296417Sdim // If we ended up with a zero-sized array, we've done what we can do within 5368296417Sdim // the limits of this layout encoding. 5369296417Sdim if (numElts == 0) return; 5370296417Sdim 5371296417Sdim // Recurse if the base element type is a record type. 5372296417Sdim if (auto recType = fieldType->getAs<RecordType>()) { 5373296417Sdim size_t oldEnd = IvarsInfo.size(); 5374296417Sdim 5375296417Sdim visitRecord(recType, fieldOffset); 5376296417Sdim 5377296417Sdim // If we have an array, replicate the first entry's layout information. 5378296417Sdim auto numEltEntries = IvarsInfo.size() - oldEnd; 5379296417Sdim if (numElts != 1 && numEltEntries != 0) { 5380296417Sdim CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType); 5381296417Sdim for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) { 5382296417Sdim // Copy the last numEltEntries onto the end of the array, adjusting 5383296417Sdim // each for the element size. 5384296417Sdim for (size_t i = 0; i != numEltEntries; ++i) { 5385296417Sdim auto firstEntry = IvarsInfo[oldEnd + i]; 5386296417Sdim IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize, 5387296417Sdim firstEntry.SizeInWords)); 5388193326Sed } 5389193326Sed } 5390193326Sed } 5391193326Sed 5392296417Sdim return; 5393193326Sed } 5394193326Sed 5395296417Sdim // Classify the element type. 5396296417Sdim Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType); 5397296417Sdim 5398296417Sdim // If it matches what we're looking for, add an entry. 5399296417Sdim if ((ForStrongLayout && GCAttr == Qualifiers::Strong) 5400296417Sdim || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) { 5401296417Sdim assert(CGM.getContext().getTypeSizeInChars(fieldType) 5402296417Sdim == CGM.getPointerSize()); 5403296417Sdim IvarsInfo.push_back(IvarInfo(fieldOffset, numElts)); 5404193326Sed } 5405193326Sed} 5406193326Sed 5407296417Sdim/// buildBitmap - This routine does the horsework of taking the offsets of 5408296417Sdim/// strong/weak references and creating a bitmap. The bitmap is also 5409296417Sdim/// returned in the given buffer, suitable for being passed to \c dump(). 5410296417Sdimllvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC, 5411296417Sdim llvm::SmallVectorImpl<unsigned char> &buffer) { 5412296417Sdim // The bitmap is a series of skip/scan instructions, aligned to word 5413296417Sdim // boundaries. The skip is performed first. 5414296417Sdim const unsigned char MaxNibble = 0xF; 5415296417Sdim const unsigned char SkipMask = 0xF0, SkipShift = 4; 5416296417Sdim const unsigned char ScanMask = 0x0F, ScanShift = 0; 5417296417Sdim 5418296417Sdim assert(!IvarsInfo.empty() && "generating bitmap for no data"); 5419296417Sdim 5420296417Sdim // Sort the ivar info on byte position in case we encounterred a 5421296417Sdim // union nested in the ivar list. 5422296417Sdim if (IsDisordered) { 5423296417Sdim // This isn't a stable sort, but our algorithm should handle it fine. 5424296417Sdim llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end()); 5425193326Sed } else { 5426296417Sdim assert(std::is_sorted(IvarsInfo.begin(), IvarsInfo.end())); 5427193326Sed } 5428296417Sdim assert(IvarsInfo.back().Offset < InstanceEnd); 5429296417Sdim 5430296417Sdim assert(buffer.empty()); 5431296417Sdim 5432296417Sdim // Skip the next N words. 5433296417Sdim auto skip = [&](unsigned numWords) { 5434296417Sdim assert(numWords > 0); 5435296417Sdim 5436296417Sdim // Try to merge into the previous byte. Since scans happen second, we 5437296417Sdim // can't do this if it includes a scan. 5438296417Sdim if (!buffer.empty() && !(buffer.back() & ScanMask)) { 5439296417Sdim unsigned lastSkip = buffer.back() >> SkipShift; 5440296417Sdim if (lastSkip < MaxNibble) { 5441296417Sdim unsigned claimed = std::min(MaxNibble - lastSkip, numWords); 5442296417Sdim numWords -= claimed; 5443296417Sdim lastSkip += claimed; 5444296417Sdim buffer.back() = (lastSkip << SkipShift); 5445296417Sdim } 5446193326Sed } 5447296417Sdim 5448296417Sdim while (numWords >= MaxNibble) { 5449296417Sdim buffer.push_back(MaxNibble << SkipShift); 5450296417Sdim numWords -= MaxNibble; 5451193326Sed } 5452296417Sdim if (numWords) { 5453296417Sdim buffer.push_back(numWords << SkipShift); 5454193326Sed } 5455296417Sdim }; 5456296417Sdim 5457296417Sdim // Scan the next N words. 5458296417Sdim auto scan = [&](unsigned numWords) { 5459296417Sdim assert(numWords > 0); 5460296417Sdim 5461296417Sdim // Try to merge into the previous byte. Since scans happen second, we can 5462296417Sdim // do this even if it includes a skip. 5463296417Sdim if (!buffer.empty()) { 5464296417Sdim unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift; 5465296417Sdim if (lastScan < MaxNibble) { 5466296417Sdim unsigned claimed = std::min(MaxNibble - lastScan, numWords); 5467296417Sdim numWords -= claimed; 5468296417Sdim lastScan += claimed; 5469296417Sdim buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift); 5470193326Sed } 5471193326Sed } 5472296417Sdim 5473296417Sdim while (numWords >= MaxNibble) { 5474296417Sdim buffer.push_back(MaxNibble << ScanShift); 5475296417Sdim numWords -= MaxNibble; 5476193326Sed } 5477296417Sdim if (numWords) { 5478296417Sdim buffer.push_back(numWords << ScanShift); 5479296417Sdim } 5480296417Sdim }; 5481296417Sdim 5482296417Sdim // One past the end of the last scan. 5483296417Sdim unsigned endOfLastScanInWords = 0; 5484296417Sdim const CharUnits WordSize = CGM.getPointerSize(); 5485296417Sdim 5486296417Sdim // Consider all the scan requests. 5487296417Sdim for (auto &request : IvarsInfo) { 5488296417Sdim CharUnits beginOfScan = request.Offset - InstanceBegin; 5489296417Sdim 5490296417Sdim // Ignore scan requests that don't start at an even multiple of the 5491296417Sdim // word size. We can't encode them. 5492296417Sdim if ((beginOfScan % WordSize) != 0) continue; 5493296417Sdim 5494296417Sdim // Ignore scan requests that start before the instance start. 5495296417Sdim // This assumes that scans never span that boundary. The boundary 5496296417Sdim // isn't the true start of the ivars, because in the fragile-ARC case 5497296417Sdim // it's rounded up to word alignment, but the test above should leave 5498296417Sdim // us ignoring that possibility. 5499296417Sdim if (beginOfScan.isNegative()) { 5500296417Sdim assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin); 5501296417Sdim continue; 5502296417Sdim } 5503296417Sdim 5504296417Sdim unsigned beginOfScanInWords = beginOfScan / WordSize; 5505296417Sdim unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords; 5506296417Sdim 5507296417Sdim // If the scan starts some number of words after the last one ended, 5508296417Sdim // skip forward. 5509296417Sdim if (beginOfScanInWords > endOfLastScanInWords) { 5510296417Sdim skip(beginOfScanInWords - endOfLastScanInWords); 5511296417Sdim 5512296417Sdim // Otherwise, start scanning where the last left off. 5513296417Sdim } else { 5514296417Sdim beginOfScanInWords = endOfLastScanInWords; 5515296417Sdim 5516296417Sdim // If that leaves us with nothing to scan, ignore this request. 5517296417Sdim if (beginOfScanInWords >= endOfScanInWords) continue; 5518296417Sdim } 5519296417Sdim 5520296417Sdim // Scan to the end of the request. 5521296417Sdim assert(beginOfScanInWords < endOfScanInWords); 5522296417Sdim scan(endOfScanInWords - beginOfScanInWords); 5523296417Sdim endOfLastScanInWords = endOfScanInWords; 5524193326Sed } 5525280031Sdim 5526296417Sdim if (buffer.empty()) 5527296417Sdim return llvm::ConstantPointerNull::get(CGM.Int8PtrTy); 5528296417Sdim 5529296417Sdim // For GC layouts, emit a skip to the end of the allocation so that we 5530296417Sdim // have precise information about the entire thing. This isn't useful 5531296417Sdim // or necessary for the ARC-style layout strings. 5532296417Sdim if (CGM.getLangOpts().getGC() != LangOptions::NonGC) { 5533296417Sdim unsigned lastOffsetInWords = 5534296417Sdim (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize; 5535296417Sdim if (lastOffsetInWords > endOfLastScanInWords) { 5536296417Sdim skip(lastOffsetInWords - endOfLastScanInWords); 5537296417Sdim } 5538296417Sdim } 5539296417Sdim 5540296417Sdim // Null terminate the string. 5541296417Sdim buffer.push_back(0); 5542296417Sdim 5543314564Sdim auto *Entry = CGObjC.CreateCStringLiteral( 5544314564Sdim reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName); 5545296417Sdim return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0); 5546212904Sdim} 5547198092Srdivacky 5548212904Sdim/// BuildIvarLayout - Builds ivar layout bitmap for the class 5549212904Sdim/// implementation for the __strong or __weak case. 5550212904Sdim/// The layout map displays which words in ivar list must be skipped 5551212904Sdim/// and which must be scanned by GC (see below). String is built of bytes. 5552212904Sdim/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count 5553212904Sdim/// of words to skip and right nibble is count of words to scan. So, each 5554212904Sdim/// nibble represents up to 15 workds to skip or scan. Skipping the rest is 5555212904Sdim/// represented by a 0x00 byte which also ends the string. 5556212904Sdim/// 1. when ForStrongLayout is true, following ivars are scanned: 5557212904Sdim/// - id, Class 5558212904Sdim/// - object * 5559212904Sdim/// - __strong anything 5560212904Sdim/// 5561212904Sdim/// 2. When ForStrongLayout is false, following ivars are scanned: 5562212904Sdim/// - __weak anything 5563212904Sdim/// 5564296417Sdimllvm::Constant * 5565296417SdimCGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD, 5566296417Sdim CharUnits beginOffset, CharUnits endOffset, 5567296417Sdim bool ForStrongLayout, bool HasMRCWeakIvars) { 5568296417Sdim // If this is MRC, and we're either building a strong layout or there 5569296417Sdim // are no weak ivars, bail out early. 5570234353Sdim llvm::Type *PtrTy = CGM.Int8PtrTy; 5571234353Sdim if (CGM.getLangOpts().getGC() == LangOptions::NonGC && 5572296417Sdim !CGM.getLangOpts().ObjCAutoRefCount && 5573296417Sdim (ForStrongLayout || !HasMRCWeakIvars)) 5574212904Sdim return llvm::Constant::getNullValue(PtrTy); 5575212904Sdim 5576226633Sdim const ObjCInterfaceDecl *OI = OMD->getClassInterface(); 5577296417Sdim SmallVector<const ObjCIvarDecl*, 32> ivars; 5578296417Sdim 5579296417Sdim // GC layout strings include the complete object layout, possibly 5580296417Sdim // inaccurately in the non-fragile ABI; the runtime knows how to fix this 5581296417Sdim // up. 5582296417Sdim // 5583296417Sdim // ARC layout strings only include the class's ivars. In non-fragile 5584296417Sdim // runtimes, that means starting at InstanceStart, rounded up to word 5585296417Sdim // alignment. In fragile runtimes, there's no InstanceStart, so it means 5586296417Sdim // starting at the offset of the first ivar, rounded up to word alignment. 5587296417Sdim // 5588296417Sdim // MRC weak layout strings follow the ARC style. 5589296417Sdim CharUnits baseOffset; 5590296417Sdim if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { 5591341825Sdim for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); 5592224145Sdim IVD; IVD = IVD->getNextIvar()) 5593296417Sdim ivars.push_back(IVD); 5594296417Sdim 5595296417Sdim if (isNonFragileABI()) { 5596296417Sdim baseOffset = beginOffset; // InstanceStart 5597296417Sdim } else if (!ivars.empty()) { 5598296417Sdim baseOffset = 5599296417Sdim CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0])); 5600296417Sdim } else { 5601296417Sdim baseOffset = CharUnits::Zero(); 5602296417Sdim } 5603296417Sdim 5604309124Sdim baseOffset = baseOffset.alignTo(CGM.getPointerAlign()); 5605224145Sdim } 5606224145Sdim else { 5607296417Sdim CGM.getContext().DeepCollectObjCIvars(OI, true, ivars); 5608212904Sdim 5609296417Sdim baseOffset = CharUnits::Zero(); 5610224145Sdim } 5611224145Sdim 5612296417Sdim if (ivars.empty()) 5613212904Sdim return llvm::Constant::getNullValue(PtrTy); 5614212904Sdim 5615296417Sdim IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout); 5616212904Sdim 5617296417Sdim builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(), 5618296417Sdim [&](const ObjCIvarDecl *ivar) -> CharUnits { 5619296417Sdim return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar)); 5620296417Sdim }); 5621296417Sdim 5622296417Sdim if (!builder.hasBitmapData()) 5623212904Sdim return llvm::Constant::getNullValue(PtrTy); 5624296417Sdim 5625296417Sdim llvm::SmallVector<unsigned char, 4> buffer; 5626296417Sdim llvm::Constant *C = builder.buildBitmap(*this, buffer); 5627341825Sdim 5628296417Sdim if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) { 5629198092Srdivacky printf("\n%s ivar layout for class '%s': ", 5630193326Sed ForStrongLayout ? "strong" : "weak", 5631276479Sdim OMD->getClassInterface()->getName().str().c_str()); 5632296417Sdim builder.dump(buffer); 5633193326Sed } 5634212904Sdim return C; 5635193326Sed} 5636193326Sed 5637193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) { 5638193326Sed llvm::GlobalVariable *&Entry = MethodVarNames[Sel]; 5639234353Sdim // FIXME: Avoid std::string in "Sel.getAsString()" 5640193326Sed if (!Entry) 5641314564Sdim Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName); 5642198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 5643193326Sed} 5644193326Sed 5645193326Sed// FIXME: Merge into a single cstring creation function. 5646193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) { 5647193326Sed return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID)); 5648193326Sed} 5649193326Sed 5650193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) { 5651193326Sed std::string TypeStr; 5652193326Sed CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field); 5653193326Sed 5654193326Sed llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; 5655193326Sed if (!Entry) 5656314564Sdim Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType); 5657198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 5658193326Sed} 5659193326Sed 5660234353Sdimllvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D, 5661234353Sdim bool Extended) { 5662314564Sdim std::string TypeStr = 5663314564Sdim CGM.getContext().getObjCEncodingForMethodDecl(D, Extended); 5664193326Sed 5665193326Sed llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; 5666193326Sed if (!Entry) 5667314564Sdim Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType); 5668198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 5669193326Sed} 5670193326Sed 5671193326Sed// FIXME: Merge into a single cstring creation function. 5672193326Sedllvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) { 5673193326Sed llvm::GlobalVariable *&Entry = PropertyNames[Ident]; 5674193326Sed if (!Entry) 5675314564Sdim Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName); 5676198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 5677193326Sed} 5678193326Sed 5679193326Sed// FIXME: Merge into a single cstring creation function. 5680193326Sed// FIXME: This Decl should be more precise. 5681193326Sedllvm::Constant * 5682198092SrdivackyCGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD, 5683198092Srdivacky const Decl *Container) { 5684314564Sdim std::string TypeStr = 5685314564Sdim CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container); 5686193326Sed return GetPropertyName(&CGM.getContext().Idents.get(TypeStr)); 5687193326Sed} 5688193326Sed 5689198092Srdivackyvoid CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D, 5690193326Sed const ObjCContainerDecl *CD, 5691360784Sdim SmallVectorImpl<char> &Name, 5692360784Sdim bool ignoreCategoryNamespace) { 5693198398Srdivacky llvm::raw_svector_ostream OS(Name); 5694193326Sed assert (CD && "Missing container decl in GetNameForMethod"); 5695198398Srdivacky OS << '\01' << (D->isInstanceMethod() ? '-' : '+') 5696198398Srdivacky << '[' << CD->getName(); 5697360784Sdim if (!ignoreCategoryNamespace) 5698360784Sdim if (const ObjCCategoryImplDecl *CID = 5699360784Sdim dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) 5700360784Sdim OS << '(' << *CID << ')'; 5701198398Srdivacky OS << ' ' << D->getSelector().getAsString() << ']'; 5702193326Sed} 5703193326Sed 5704193326Sedvoid CGObjCMac::FinishModule() { 5705193326Sed EmitModuleInfo(); 5706193326Sed 5707193326Sed // Emit the dummy bodies for any protocols which were referenced but 5708193326Sed // never defined. 5709314564Sdim for (auto &entry : Protocols) { 5710314564Sdim llvm::GlobalVariable *global = entry.second; 5711314564Sdim if (global->hasInitializer()) 5712193326Sed continue; 5713193326Sed 5714314564Sdim ConstantInitBuilder builder(CGM); 5715314564Sdim auto values = builder.beginStruct(ObjCTypes.ProtocolTy); 5716314564Sdim values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy); 5717314564Sdim values.add(GetClassName(entry.first->getName())); 5718314564Sdim values.addNullPointer(ObjCTypes.ProtocolListPtrTy); 5719314564Sdim values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy); 5720314564Sdim values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy); 5721314564Sdim values.finishAndSetAsInitializer(global); 5722314564Sdim CGM.addCompilerUsedGlobal(global); 5723193326Sed } 5724193326Sed 5725193326Sed // Add assembler directives to add lazy undefined symbol references 5726193326Sed // for classes which are referenced but not defined. This is 5727193326Sed // important for correct linker interaction. 5728198092Srdivacky // 5729198092Srdivacky // FIXME: It would be nice if we had an LLVM construct for this. 5730314564Sdim if ((!LazySymbols.empty() || !DefinedSymbols.empty()) && 5731314564Sdim CGM.getTriple().isOSBinFormatMachO()) { 5732234353Sdim SmallString<256> Asm; 5733198092Srdivacky Asm += CGM.getModule().getModuleInlineAsm(); 5734198092Srdivacky if (!Asm.empty() && Asm.back() != '\n') 5735198092Srdivacky Asm += '\n'; 5736193326Sed 5737198092Srdivacky llvm::raw_svector_ostream OS(Asm); 5738314564Sdim for (const auto *Sym : DefinedSymbols) 5739314564Sdim OS << "\t.objc_class_name_" << Sym->getName() << "=0\n" 5740314564Sdim << "\t.globl .objc_class_name_" << Sym->getName() << "\n"; 5741314564Sdim for (const auto *Sym : LazySymbols) 5742314564Sdim OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n"; 5743314564Sdim for (const auto &Category : DefinedCategoryNames) 5744314564Sdim OS << "\t.objc_category_name_" << Category << "=0\n" 5745314564Sdim << "\t.globl .objc_category_name_" << Category << "\n"; 5746210299Sed 5747198092Srdivacky CGM.getModule().setModuleInlineAsm(OS.str()); 5748193326Sed } 5749193326Sed} 5750193326Sed 5751198092SrdivackyCGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm) 5752309124Sdim : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr), 5753309124Sdim ObjCEmptyVtableVar(nullptr) { 5754193326Sed ObjCABI = 2; 5755193326Sed} 5756193326Sed 5757193326Sed/* *** */ 5758193326Sed 5759193326SedObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) 5760276479Sdim : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr) 5761234353Sdim{ 5762193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 5763193326Sed ASTContext &Ctx = CGM.getContext(); 5764198092Srdivacky 5765314564Sdim ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy)); 5766314564Sdim IntTy = CGM.IntTy; 5767314564Sdim LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy)); 5768234353Sdim Int8PtrTy = CGM.Int8PtrTy; 5769234353Sdim Int8PtrPtrTy = CGM.Int8PtrPtrTy; 5770198092Srdivacky 5771276479Sdim // arm64 targets use "int" ivar offset variables. All others, 5772276479Sdim // including OS X x86_64 and Windows x86_64, use "long" ivar offsets. 5773280031Sdim if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64) 5774276479Sdim IvarOffsetVarTy = IntTy; 5775276479Sdim else 5776276479Sdim IvarOffsetVarTy = LongTy; 5777276479Sdim 5778314564Sdim ObjectPtrTy = 5779314564Sdim cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType())); 5780314564Sdim PtrObjectPtrTy = 5781314564Sdim llvm::PointerType::getUnqual(ObjectPtrTy); 5782314564Sdim SelectorPtrTy = 5783314564Sdim cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType())); 5784198092Srdivacky 5785193326Sed // I'm not sure I like this. The implicit coordination is a bit 5786193326Sed // gross. We should solve this in a reasonable fashion because this 5787193326Sed // is a pretty common task (match some runtime data structure with 5788193326Sed // an LLVM data structure). 5789198092Srdivacky 5790193326Sed // FIXME: This is leaked. 5791193326Sed // FIXME: Merge with rewriter code? 5792198092Srdivacky 5793193326Sed // struct _objc_super { 5794193326Sed // id self; 5795193326Sed // Class cls; 5796193326Sed // } 5797208600Srdivacky RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, 5798207619Srdivacky Ctx.getTranslationUnitDecl(), 5799221345Sdim SourceLocation(), SourceLocation(), 5800198092Srdivacky &Ctx.Idents.get("_objc_super")); 5801276479Sdim RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 5802276479Sdim nullptr, Ctx.getObjCIdType(), nullptr, nullptr, 5803276479Sdim false, ICIS_NoInit)); 5804276479Sdim RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 5805276479Sdim nullptr, Ctx.getObjCClassType(), nullptr, 5806276479Sdim nullptr, false, ICIS_NoInit)); 5807203955Srdivacky RD->completeDefinition(); 5808198092Srdivacky 5809193326Sed SuperCTy = Ctx.getTagDeclType(RD); 5810193326Sed SuperPtrCTy = Ctx.getPointerType(SuperCTy); 5811198092Srdivacky 5812193326Sed SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy)); 5813198092Srdivacky SuperPtrTy = llvm::PointerType::getUnqual(SuperTy); 5814198092Srdivacky 5815193326Sed // struct _prop_t { 5816193326Sed // char *name; 5817198092Srdivacky // char *attributes; 5818193326Sed // } 5819321369Sdim PropertyTy = llvm::StructType::create("struct._prop_t", Int8PtrTy, Int8PtrTy); 5820198092Srdivacky 5821193326Sed // struct _prop_list_t { 5822193326Sed // uint32_t entsize; // sizeof(struct _prop_t) 5823193326Sed // uint32_t count_of_properties; 5824193326Sed // struct _prop_t prop_list[count_of_properties]; 5825193326Sed // } 5826321369Sdim PropertyListTy = llvm::StructType::create( 5827321369Sdim "struct._prop_list_t", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0)); 5828193326Sed // struct _prop_list_t * 5829193326Sed PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy); 5830198092Srdivacky 5831193326Sed // struct _objc_method { 5832193326Sed // SEL _cmd; 5833193326Sed // char *method_type; 5834193326Sed // char *_imp; 5835193326Sed // } 5836321369Sdim MethodTy = llvm::StructType::create("struct._objc_method", SelectorPtrTy, 5837321369Sdim Int8PtrTy, Int8PtrTy); 5838198092Srdivacky 5839193326Sed // struct _objc_cache * 5840226633Sdim CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache"); 5841193326Sed CachePtrTy = llvm::PointerType::getUnqual(CacheTy); 5842193326Sed} 5843193326Sed 5844198092SrdivackyObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) 5845198092Srdivacky : ObjCCommonTypesHelper(cgm) { 5846193326Sed // struct _objc_method_description { 5847193326Sed // SEL name; 5848193326Sed // char *types; 5849193326Sed // } 5850321369Sdim MethodDescriptionTy = llvm::StructType::create( 5851321369Sdim "struct._objc_method_description", SelectorPtrTy, Int8PtrTy); 5852193326Sed 5853193326Sed // struct _objc_method_description_list { 5854193326Sed // int count; 5855193326Sed // struct _objc_method_description[1]; 5856193326Sed // } 5857321369Sdim MethodDescriptionListTy = 5858321369Sdim llvm::StructType::create("struct._objc_method_description_list", IntTy, 5859321369Sdim llvm::ArrayType::get(MethodDescriptionTy, 0)); 5860198092Srdivacky 5861193326Sed // struct _objc_method_description_list * 5862198092Srdivacky MethodDescriptionListPtrTy = 5863193326Sed llvm::PointerType::getUnqual(MethodDescriptionListTy); 5864193326Sed 5865193326Sed // Protocol description structures 5866193326Sed 5867193326Sed // struct _objc_protocol_extension { 5868193326Sed // uint32_t size; // sizeof(struct _objc_protocol_extension) 5869193326Sed // struct _objc_method_description_list *optional_instance_methods; 5870193326Sed // struct _objc_method_description_list *optional_class_methods; 5871193326Sed // struct _objc_property_list *instance_properties; 5872234353Sdim // const char ** extendedMethodTypes; 5873309124Sdim // struct _objc_property_list *class_properties; 5874193326Sed // } 5875321369Sdim ProtocolExtensionTy = llvm::StructType::create( 5876321369Sdim "struct._objc_protocol_extension", IntTy, MethodDescriptionListPtrTy, 5877321369Sdim MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy, 5878321369Sdim PropertyListPtrTy); 5879198092Srdivacky 5880193326Sed // struct _objc_protocol_extension * 5881193326Sed ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy); 5882193326Sed 5883193326Sed // Handle recursive construction of Protocol and ProtocolList types 5884193326Sed 5885224145Sdim ProtocolTy = 5886226633Sdim llvm::StructType::create(VMContext, "struct._objc_protocol"); 5887193326Sed 5888224145Sdim ProtocolListTy = 5889226633Sdim llvm::StructType::create(VMContext, "struct._objc_protocol_list"); 5890321369Sdim ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), LongTy, 5891321369Sdim llvm::ArrayType::get(ProtocolTy, 0)); 5892193326Sed 5893193326Sed // struct _objc_protocol { 5894193326Sed // struct _objc_protocol_extension *isa; 5895193326Sed // char *protocol_name; 5896193326Sed // struct _objc_protocol **_objc_protocol_list; 5897193326Sed // struct _objc_method_description_list *instance_methods; 5898193326Sed // struct _objc_method_description_list *class_methods; 5899193326Sed // } 5900224145Sdim ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy, 5901224145Sdim llvm::PointerType::getUnqual(ProtocolListTy), 5902321369Sdim MethodDescriptionListPtrTy, MethodDescriptionListPtrTy); 5903193326Sed 5904193326Sed // struct _objc_protocol_list * 5905193326Sed ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy); 5906193326Sed 5907193326Sed ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy); 5908193326Sed 5909193326Sed // Class description structures 5910193326Sed 5911193326Sed // struct _objc_ivar { 5912193326Sed // char *ivar_name; 5913193326Sed // char *ivar_type; 5914193326Sed // int ivar_offset; 5915193326Sed // } 5916321369Sdim IvarTy = llvm::StructType::create("struct._objc_ivar", Int8PtrTy, Int8PtrTy, 5917321369Sdim IntTy); 5918193326Sed 5919193326Sed // struct _objc_ivar_list * 5920224145Sdim IvarListTy = 5921226633Sdim llvm::StructType::create(VMContext, "struct._objc_ivar_list"); 5922193326Sed IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy); 5923193326Sed 5924193326Sed // struct _objc_method_list * 5925224145Sdim MethodListTy = 5926226633Sdim llvm::StructType::create(VMContext, "struct._objc_method_list"); 5927193326Sed MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy); 5928193326Sed 5929193326Sed // struct _objc_class_extension * 5930321369Sdim ClassExtensionTy = llvm::StructType::create( 5931321369Sdim "struct._objc_class_extension", IntTy, Int8PtrTy, PropertyListPtrTy); 5932193326Sed ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy); 5933193326Sed 5934226633Sdim ClassTy = llvm::StructType::create(VMContext, "struct._objc_class"); 5935193326Sed 5936193326Sed // struct _objc_class { 5937193326Sed // Class isa; 5938193326Sed // Class super_class; 5939193326Sed // char *name; 5940193326Sed // long version; 5941193326Sed // long info; 5942193326Sed // long instance_size; 5943193326Sed // struct _objc_ivar_list *ivars; 5944193326Sed // struct _objc_method_list *methods; 5945193326Sed // struct _objc_cache *cache; 5946193326Sed // struct _objc_protocol_list *protocols; 5947193326Sed // char *ivar_layout; 5948193326Sed // struct _objc_class_ext *ext; 5949193326Sed // }; 5950224145Sdim ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy), 5951321369Sdim llvm::PointerType::getUnqual(ClassTy), Int8PtrTy, LongTy, 5952321369Sdim LongTy, LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy, 5953321369Sdim ProtocolListPtrTy, Int8PtrTy, ClassExtensionPtrTy); 5954198092Srdivacky 5955193326Sed ClassPtrTy = llvm::PointerType::getUnqual(ClassTy); 5956193326Sed 5957193326Sed // struct _objc_category { 5958193326Sed // char *category_name; 5959193326Sed // char *class_name; 5960193326Sed // struct _objc_method_list *instance_method; 5961193326Sed // struct _objc_method_list *class_method; 5962309124Sdim // struct _objc_protocol_list *protocols; 5963193326Sed // uint32_t size; // sizeof(struct _objc_category) 5964193326Sed // struct _objc_property_list *instance_properties;// category's @property 5965309124Sdim // struct _objc_property_list *class_properties; 5966193326Sed // } 5967321369Sdim CategoryTy = llvm::StructType::create( 5968321369Sdim "struct._objc_category", Int8PtrTy, Int8PtrTy, MethodListPtrTy, 5969321369Sdim MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy, 5970321369Sdim PropertyListPtrTy); 5971193326Sed 5972193326Sed // Global metadata structures 5973193326Sed 5974193326Sed // struct _objc_symtab { 5975193326Sed // long sel_ref_cnt; 5976193326Sed // SEL *refs; 5977193326Sed // short cls_def_cnt; 5978193326Sed // short cat_def_cnt; 5979193326Sed // char *defs[cls_def_cnt + cat_def_cnt]; 5980193326Sed // } 5981321369Sdim SymtabTy = llvm::StructType::create("struct._objc_symtab", LongTy, 5982321369Sdim SelectorPtrTy, ShortTy, ShortTy, 5983321369Sdim llvm::ArrayType::get(Int8PtrTy, 0)); 5984193326Sed SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy); 5985193326Sed 5986193326Sed // struct _objc_module { 5987193326Sed // long version; 5988193326Sed // long size; // sizeof(struct _objc_module) 5989193326Sed // char *name; 5990193326Sed // struct _objc_symtab* symtab; 5991193326Sed // } 5992321369Sdim ModuleTy = llvm::StructType::create("struct._objc_module", LongTy, LongTy, 5993321369Sdim Int8PtrTy, SymtabPtrTy); 5994193326Sed 5995193326Sed // FIXME: This is the size of the setjmp buffer and should be target 5996193326Sed // specific. 18 is what's used on 32-bit X86. 5997193326Sed uint64_t SetJmpBufferSize = 18; 5998198092Srdivacky 5999193326Sed // Exceptions 6000234353Sdim llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4); 6001198092Srdivacky 6002321369Sdim ExceptionDataTy = llvm::StructType::create( 6003321369Sdim "struct._objc_exception_data", 6004321369Sdim llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy); 6005193326Sed} 6006193326Sed 6007198092SrdivackyObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm) 6008198092Srdivacky : ObjCCommonTypesHelper(cgm) { 6009193326Sed // struct _method_list_t { 6010193326Sed // uint32_t entsize; // sizeof(struct _objc_method) 6011193326Sed // uint32_t method_count; 6012193326Sed // struct _objc_method method_list[method_count]; 6013193326Sed // } 6014224145Sdim MethodListnfABITy = 6015321369Sdim llvm::StructType::create("struct.__method_list_t", IntTy, IntTy, 6016321369Sdim llvm::ArrayType::get(MethodTy, 0)); 6017193326Sed // struct method_list_t * 6018193326Sed MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy); 6019198092Srdivacky 6020193326Sed // struct _protocol_t { 6021193326Sed // id isa; // NULL 6022193326Sed // const char * const protocol_name; 6023193326Sed // const struct _protocol_list_t * protocol_list; // super protocols 6024193326Sed // const struct method_list_t * const instance_methods; 6025193326Sed // const struct method_list_t * const class_methods; 6026193326Sed // const struct method_list_t *optionalInstanceMethods; 6027193326Sed // const struct method_list_t *optionalClassMethods; 6028193326Sed // const struct _prop_list_t * properties; 6029193326Sed // const uint32_t size; // sizeof(struct _protocol_t) 6030193326Sed // const uint32_t flags; // = 0 6031234353Sdim // const char ** extendedMethodTypes; 6032288943Sdim // const char *demangledName; 6033309124Sdim // const struct _prop_list_t * class_properties; 6034193326Sed // } 6035198092Srdivacky 6036193326Sed // Holder for struct _protocol_list_t * 6037224145Sdim ProtocolListnfABITy = 6038226633Sdim llvm::StructType::create(VMContext, "struct._objc_protocol_list"); 6039198092Srdivacky 6040321369Sdim ProtocolnfABITy = llvm::StructType::create( 6041321369Sdim "struct._protocol_t", ObjectPtrTy, Int8PtrTy, 6042321369Sdim llvm::PointerType::getUnqual(ProtocolListnfABITy), MethodListnfABIPtrTy, 6043321369Sdim MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy, 6044321369Sdim PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy, 6045321369Sdim PropertyListPtrTy); 6046193326Sed 6047193326Sed // struct _protocol_t* 6048193326Sed ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy); 6049198092Srdivacky 6050193326Sed // struct _protocol_list_t { 6051193326Sed // long protocol_count; // Note, this is 32/64 bit 6052193326Sed // struct _protocol_t *[protocol_count]; 6053193326Sed // } 6054224145Sdim ProtocolListnfABITy->setBody(LongTy, 6055321369Sdim llvm::ArrayType::get(ProtocolnfABIPtrTy, 0)); 6056198092Srdivacky 6057193326Sed // struct _objc_protocol_list* 6058193326Sed ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy); 6059198092Srdivacky 6060193326Sed // struct _ivar_t { 6061276479Sdim // unsigned [long] int *offset; // pointer to ivar offset location 6062193326Sed // char *name; 6063193326Sed // char *type; 6064193326Sed // uint32_t alignment; 6065193326Sed // uint32_t size; 6066193326Sed // } 6067276479Sdim IvarnfABITy = llvm::StructType::create( 6068276479Sdim "struct._ivar_t", llvm::PointerType::getUnqual(IvarOffsetVarTy), 6069321369Sdim Int8PtrTy, Int8PtrTy, IntTy, IntTy); 6070198092Srdivacky 6071193326Sed // struct _ivar_list_t { 6072193326Sed // uint32 entsize; // sizeof(struct _ivar_t) 6073193326Sed // uint32 count; 6074193326Sed // struct _iver_t list[count]; 6075193326Sed // } 6076224145Sdim IvarListnfABITy = 6077321369Sdim llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy, 6078321369Sdim llvm::ArrayType::get(IvarnfABITy, 0)); 6079198092Srdivacky 6080193326Sed IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy); 6081198092Srdivacky 6082193326Sed // struct _class_ro_t { 6083193326Sed // uint32_t const flags; 6084193326Sed // uint32_t const instanceStart; 6085193326Sed // uint32_t const instanceSize; 6086193326Sed // uint32_t const reserved; // only when building for 64bit targets 6087193326Sed // const uint8_t * const ivarLayout; 6088193326Sed // const char *const name; 6089193326Sed // const struct _method_list_t * const baseMethods; 6090193326Sed // const struct _objc_protocol_list *const baseProtocols; 6091193326Sed // const struct _ivar_list_t *const ivars; 6092193326Sed // const uint8_t * const weakIvarLayout; 6093193326Sed // const struct _prop_list_t * const properties; 6094193326Sed // } 6095198092Srdivacky 6096193326Sed // FIXME. Add 'reserved' field in 64bit abi mode! 6097321369Sdim ClassRonfABITy = llvm::StructType::create( 6098321369Sdim "struct._class_ro_t", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy, 6099321369Sdim MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy, 6100321369Sdim Int8PtrTy, PropertyListPtrTy); 6101198092Srdivacky 6102193326Sed // ImpnfABITy - LLVM for id (*)(id, SEL, ...) 6103224145Sdim llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; 6104223017Sdim ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false) 6105223017Sdim ->getPointerTo(); 6106198092Srdivacky 6107193326Sed // struct _class_t { 6108193326Sed // struct _class_t *isa; 6109193326Sed // struct _class_t * const superclass; 6110193326Sed // void *cache; 6111193326Sed // IMP *vtable; 6112193326Sed // struct class_ro_t *ro; 6113193326Sed // } 6114198092Srdivacky 6115226633Sdim ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t"); 6116224145Sdim ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy), 6117321369Sdim llvm::PointerType::getUnqual(ClassnfABITy), CachePtrTy, 6118224145Sdim llvm::PointerType::getUnqual(ImpnfABITy), 6119321369Sdim llvm::PointerType::getUnqual(ClassRonfABITy)); 6120193326Sed 6121193326Sed // LLVM for struct _class_t * 6122193326Sed ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy); 6123198092Srdivacky 6124193326Sed // struct _category_t { 6125193326Sed // const char * const name; 6126193326Sed // struct _class_t *const cls; 6127193326Sed // const struct _method_list_t * const instance_methods; 6128193326Sed // const struct _method_list_t * const class_methods; 6129193326Sed // const struct _protocol_list_t * const protocols; 6130193326Sed // const struct _prop_list_t * const properties; 6131309124Sdim // const struct _prop_list_t * const class_properties; 6132309124Sdim // const uint32_t size; 6133193326Sed // } 6134321369Sdim CategorynfABITy = llvm::StructType::create( 6135321369Sdim "struct._category_t", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy, 6136321369Sdim MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy, 6137321369Sdim PropertyListPtrTy, IntTy); 6138198092Srdivacky 6139193326Sed // New types for nonfragile abi messaging. 6140193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 6141193326Sed ASTContext &Ctx = CGM.getContext(); 6142198092Srdivacky 6143193326Sed // MessageRefTy - LLVM for: 6144193326Sed // struct _message_ref_t { 6145193326Sed // IMP messenger; 6146193326Sed // SEL name; 6147193326Sed // }; 6148198092Srdivacky 6149193326Sed // First the clang type for struct _message_ref_t 6150208600Srdivacky RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, 6151207619Srdivacky Ctx.getTranslationUnitDecl(), 6152221345Sdim SourceLocation(), SourceLocation(), 6153193326Sed &Ctx.Idents.get("_message_ref_t")); 6154276479Sdim RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 6155276479Sdim nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false, 6156239462Sdim ICIS_NoInit)); 6157276479Sdim RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 6158276479Sdim nullptr, Ctx.getObjCSelType(), nullptr, nullptr, 6159276479Sdim false, ICIS_NoInit)); 6160203955Srdivacky RD->completeDefinition(); 6161198092Srdivacky 6162193326Sed MessageRefCTy = Ctx.getTagDeclType(RD); 6163193326Sed MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy); 6164193326Sed MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy)); 6165198092Srdivacky 6166193326Sed // MessageRefPtrTy - LLVM for struct _message_ref_t* 6167193326Sed MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy); 6168198092Srdivacky 6169193326Sed // SuperMessageRefTy - LLVM for: 6170193326Sed // struct _super_message_ref_t { 6171193326Sed // SUPER_IMP messenger; 6172193326Sed // SEL name; 6173193326Sed // }; 6174321369Sdim SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t", 6175321369Sdim ImpnfABITy, SelectorPtrTy); 6176198092Srdivacky 6177193326Sed // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* 6178198092Srdivacky SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); 6179193326Sed 6180341825Sdim 6181193326Sed // struct objc_typeinfo { 6182193326Sed // const void** vtable; // objc_ehtype_vtable + 2 6183193326Sed // const char* name; // c++ typeinfo string 6184193326Sed // Class cls; 6185193326Sed // }; 6186321369Sdim EHTypeTy = llvm::StructType::create("struct._objc_typeinfo", 6187321369Sdim llvm::PointerType::getUnqual(Int8PtrTy), 6188321369Sdim Int8PtrTy, ClassnfABIPtrTy); 6189193326Sed EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy); 6190193326Sed} 6191193326Sed 6192198092Srdivackyllvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() { 6193193326Sed FinishNonFragileABIModule(); 6194198092Srdivacky 6195276479Sdim return nullptr; 6196193326Sed} 6197193326Sed 6198309124Sdimvoid CGObjCNonFragileABIMac::AddModuleClassList( 6199309124Sdim ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName, 6200309124Sdim StringRef SectionName) { 6201193326Sed unsigned NumClasses = Container.size(); 6202198092Srdivacky 6203193326Sed if (!NumClasses) 6204193326Sed return; 6205198092Srdivacky 6206234353Sdim SmallVector<llvm::Constant*, 8> Symbols(NumClasses); 6207193326Sed for (unsigned i=0; i<NumClasses; i++) 6208193326Sed Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i], 6209193326Sed ObjCTypes.Int8PtrTy); 6210234353Sdim llvm::Constant *Init = 6211193326Sed llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 6212234353Sdim Symbols.size()), 6213193326Sed Symbols); 6214198092Srdivacky 6215353358Sdim // Section name is obtained by calling GetSectionName, which returns 6216353358Sdim // sections in the __DATA segment on MachO. 6217353358Sdim assert((!CGM.getTriple().isOSBinFormatMachO() || 6218353358Sdim SectionName.startswith("__DATA")) && 6219353358Sdim "SectionName expected to start with __DATA on MachO"); 6220353358Sdim llvm::GlobalValue::LinkageTypes LT = 6221353358Sdim getLinkageTypeForObjCMetadata(CGM, SectionName); 6222193326Sed llvm::GlobalVariable *GV = 6223353358Sdim new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, LT, Init, 6224198092Srdivacky SymbolName); 6225360784Sdim GV->setAlignment( 6226360784Sdim llvm::Align(CGM.getDataLayout().getABITypeAlignment(Init->getType()))); 6227193326Sed GV->setSection(SectionName); 6228276479Sdim CGM.addCompilerUsedGlobal(GV); 6229193326Sed} 6230198092Srdivacky 6231193326Sedvoid CGObjCNonFragileABIMac::FinishNonFragileABIModule() { 6232193326Sed // nonfragile abi has no module definition. 6233198092Srdivacky 6234193326Sed // Build list of all implemented class addresses in array 6235193326Sed // L_OBJC_LABEL_CLASS_$. 6236276479Sdim 6237276479Sdim for (unsigned i=0, NumClasses=ImplementedClasses.size(); i<NumClasses; i++) { 6238276479Sdim const ObjCInterfaceDecl *ID = ImplementedClasses[i]; 6239276479Sdim assert(ID); 6240276479Sdim if (ObjCImplementationDecl *IMP = ID->getImplementation()) 6241276479Sdim // We are implementing a weak imported interface. Give it external linkage 6242276479Sdim if (ID->isWeakImported() && !IMP->isWeakImported()) { 6243276479Sdim DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage); 6244276479Sdim DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage); 6245276479Sdim } 6246276479Sdim } 6247280031Sdim 6248280031Sdim AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$", 6249321369Sdim GetSectionName("__objc_classlist", 6250321369Sdim "regular,no_dead_strip")); 6251276479Sdim 6252280031Sdim AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$", 6253321369Sdim GetSectionName("__objc_nlclslist", 6254321369Sdim "regular,no_dead_strip")); 6255198092Srdivacky 6256193326Sed // Build list of all implemented category addresses in array 6257193326Sed // L_OBJC_LABEL_CATEGORY_$. 6258280031Sdim AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$", 6259321369Sdim GetSectionName("__objc_catlist", 6260321369Sdim "regular,no_dead_strip")); 6261353358Sdim AddModuleClassList(DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$", 6262353358Sdim GetSectionName("__objc_catlist2", 6263353358Sdim "regular,no_dead_strip")); 6264280031Sdim AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$", 6265321369Sdim GetSectionName("__objc_nlcatlist", 6266321369Sdim "regular,no_dead_strip")); 6267198092Srdivacky 6268207619Srdivacky EmitImageInfo(); 6269193326Sed} 6270193326Sed 6271223017Sdim/// isVTableDispatchedSelector - Returns true if SEL is not in the list of 6272223017Sdim/// VTableDispatchMethods; false otherwise. What this means is that 6273198092Srdivacky/// except for the 19 selectors in the list, we generate 32bit-style 6274193326Sed/// message dispatch call for all the rest. 6275223017Sdimbool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) { 6276223017Sdim // At various points we've experimented with using vtable-based 6277223017Sdim // dispatch for all methods. 6278207619Srdivacky switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) { 6279207619Srdivacky case CodeGenOptions::Legacy: 6280223017Sdim return false; 6281223017Sdim case CodeGenOptions::NonLegacy: 6282203955Srdivacky return true; 6283207619Srdivacky case CodeGenOptions::Mixed: 6284207619Srdivacky break; 6285207619Srdivacky } 6286203955Srdivacky 6287207619Srdivacky // If so, see whether this selector is in the white-list of things which must 6288207619Srdivacky // use the new dispatch convention. We lazily build a dense set for this. 6289223017Sdim if (VTableDispatchMethods.empty()) { 6290223017Sdim VTableDispatchMethods.insert(GetNullarySelector("alloc")); 6291223017Sdim VTableDispatchMethods.insert(GetNullarySelector("class")); 6292223017Sdim VTableDispatchMethods.insert(GetNullarySelector("self")); 6293223017Sdim VTableDispatchMethods.insert(GetNullarySelector("isFlipped")); 6294223017Sdim VTableDispatchMethods.insert(GetNullarySelector("length")); 6295223017Sdim VTableDispatchMethods.insert(GetNullarySelector("count")); 6296198092Srdivacky 6297223017Sdim // These are vtable-based if GC is disabled. 6298223017Sdim // Optimistically use vtable dispatch for hybrid compiles. 6299234353Sdim if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) { 6300223017Sdim VTableDispatchMethods.insert(GetNullarySelector("retain")); 6301223017Sdim VTableDispatchMethods.insert(GetNullarySelector("release")); 6302223017Sdim VTableDispatchMethods.insert(GetNullarySelector("autorelease")); 6303223017Sdim } 6304223017Sdim 6305223017Sdim VTableDispatchMethods.insert(GetUnarySelector("allocWithZone")); 6306223017Sdim VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass")); 6307223017Sdim VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector")); 6308223017Sdim VTableDispatchMethods.insert(GetUnarySelector("objectForKey")); 6309223017Sdim VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex")); 6310223017Sdim VTableDispatchMethods.insert(GetUnarySelector("isEqualToString")); 6311223017Sdim VTableDispatchMethods.insert(GetUnarySelector("isEqual")); 6312223017Sdim 6313223017Sdim // These are vtable-based if GC is enabled. 6314223017Sdim // Optimistically use vtable dispatch for hybrid compiles. 6315234353Sdim if (CGM.getLangOpts().getGC() != LangOptions::NonGC) { 6316223017Sdim VTableDispatchMethods.insert(GetNullarySelector("hash")); 6317223017Sdim VTableDispatchMethods.insert(GetUnarySelector("addObject")); 6318341825Sdim 6319223017Sdim // "countByEnumeratingWithState:objects:count" 6320223017Sdim IdentifierInfo *KeyIdents[] = { 6321223017Sdim &CGM.getContext().Idents.get("countByEnumeratingWithState"), 6322223017Sdim &CGM.getContext().Idents.get("objects"), 6323223017Sdim &CGM.getContext().Idents.get("count") 6324223017Sdim }; 6325223017Sdim VTableDispatchMethods.insert( 6326223017Sdim CGM.getContext().Selectors.getSelector(3, KeyIdents)); 6327223017Sdim } 6328193326Sed } 6329207619Srdivacky 6330223017Sdim return VTableDispatchMethods.count(Sel); 6331193326Sed} 6332193326Sed 6333193326Sed/// BuildClassRoTInitializer - generate meta-data for: 6334193326Sed/// struct _class_ro_t { 6335193326Sed/// uint32_t const flags; 6336193326Sed/// uint32_t const instanceStart; 6337193326Sed/// uint32_t const instanceSize; 6338193326Sed/// uint32_t const reserved; // only when building for 64bit targets 6339193326Sed/// const uint8_t * const ivarLayout; 6340193326Sed/// const char *const name; 6341193326Sed/// const struct _method_list_t * const baseMethods; 6342193326Sed/// const struct _protocol_list_t *const baseProtocols; 6343193326Sed/// const struct _ivar_list_t *const ivars; 6344193326Sed/// const uint8_t * const weakIvarLayout; 6345193326Sed/// const struct _prop_list_t * const properties; 6346193326Sed/// } 6347193326Sed/// 6348193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( 6349198092Srdivacky unsigned flags, 6350198092Srdivacky unsigned InstanceStart, 6351198092Srdivacky unsigned InstanceSize, 6352198092Srdivacky const ObjCImplementationDecl *ID) { 6353276479Sdim std::string ClassName = ID->getObjCRuntimeNameAsString(); 6354224145Sdim 6355296417Sdim CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart); 6356296417Sdim CharUnits endInstance = CharUnits::fromQuantity(InstanceSize); 6357296417Sdim 6358296417Sdim bool hasMRCWeak = false; 6359234353Sdim if (CGM.getLangOpts().ObjCAutoRefCount) 6360243830Sdim flags |= NonFragileABI_Class_CompiledByARC; 6361296417Sdim else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID))) 6362296417Sdim flags |= NonFragileABI_Class_HasMRCWeakIvars; 6363224145Sdim 6364314564Sdim ConstantInitBuilder builder(CGM); 6365314564Sdim auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy); 6366314564Sdim 6367314564Sdim values.addInt(ObjCTypes.IntTy, flags); 6368314564Sdim values.addInt(ObjCTypes.IntTy, InstanceStart); 6369314564Sdim values.addInt(ObjCTypes.IntTy, InstanceSize); 6370314564Sdim values.add((flags & NonFragileABI_Class_Meta) 6371314564Sdim ? GetIvarLayoutName(nullptr, ObjCTypes) 6372314564Sdim : BuildStrongIvarLayout(ID, beginInstance, endInstance)); 6373314564Sdim values.add(GetClassName(ID->getObjCRuntimeNameAsString())); 6374314564Sdim 6375193326Sed // const struct _method_list_t * const baseMethods; 6376314564Sdim SmallVector<const ObjCMethodDecl*, 16> methods; 6377243830Sdim if (flags & NonFragileABI_Class_Meta) { 6378314564Sdim for (const auto *MD : ID->class_methods()) 6379360784Sdim if (!MD->isDirectMethod()) 6380360784Sdim methods.push_back(MD); 6381193326Sed } else { 6382314564Sdim for (const auto *MD : ID->instance_methods()) 6383360784Sdim if (!MD->isDirectMethod()) 6384360784Sdim methods.push_back(MD); 6385193326Sed } 6386198092Srdivacky 6387314564Sdim values.add(emitMethodList(ID->getObjCRuntimeNameAsString(), 6388314564Sdim (flags & NonFragileABI_Class_Meta) 6389314564Sdim ? MethodListType::ClassMethods 6390314564Sdim : MethodListType::InstanceMethods, 6391314564Sdim methods)); 6392314564Sdim 6393193326Sed const ObjCInterfaceDecl *OID = ID->getClassInterface(); 6394193326Sed assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer"); 6395353358Sdim values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_" 6396276479Sdim + OID->getObjCRuntimeNameAsString(), 6397314564Sdim OID->all_referenced_protocol_begin(), 6398314564Sdim OID->all_referenced_protocol_end())); 6399198092Srdivacky 6400243830Sdim if (flags & NonFragileABI_Class_Meta) { 6401314564Sdim values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy); 6402314564Sdim values.add(GetIvarLayoutName(nullptr, ObjCTypes)); 6403314564Sdim values.add(EmitPropertyList( 6404353358Sdim "_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), 6405314564Sdim ID, ID->getClassInterface(), ObjCTypes, true)); 6406243830Sdim } else { 6407314564Sdim values.add(EmitIvarList(ID)); 6408314564Sdim values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak)); 6409314564Sdim values.add(EmitPropertyList( 6410353358Sdim "_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), 6411314564Sdim ID, ID->getClassInterface(), ObjCTypes, false)); 6412243830Sdim } 6413314564Sdim 6414314564Sdim llvm::SmallString<64> roLabel; 6415314564Sdim llvm::raw_svector_ostream(roLabel) 6416353358Sdim << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_" 6417353358Sdim : "_OBJC_CLASS_RO_$_") 6418314564Sdim << ClassName; 6419314564Sdim 6420353358Sdim return finishAndCreateGlobal(values, roLabel, CGM); 6421193326Sed} 6422193326Sed 6423314564Sdim/// Build the metaclass object for a class. 6424314564Sdim/// 6425193326Sed/// struct _class_t { 6426193326Sed/// struct _class_t *isa; 6427193326Sed/// struct _class_t * const superclass; 6428193326Sed/// void *cache; 6429193326Sed/// IMP *vtable; 6430193326Sed/// struct class_ro_t *ro; 6431193326Sed/// } 6432193326Sed/// 6433314564Sdimllvm::GlobalVariable * 6434314564SdimCGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI, 6435314564Sdim bool isMetaclass, 6436314564Sdim llvm::Constant *IsAGV, 6437314564Sdim llvm::Constant *SuperClassGV, 6438314564Sdim llvm::Constant *ClassRoGV, 6439314564Sdim bool HiddenVisibility) { 6440314564Sdim ConstantInitBuilder builder(CGM); 6441314564Sdim auto values = builder.beginStruct(ObjCTypes.ClassnfABITy); 6442314564Sdim values.add(IsAGV); 6443314564Sdim if (SuperClassGV) { 6444314564Sdim values.add(SuperClassGV); 6445314564Sdim } else { 6446314564Sdim values.addNullPointer(ObjCTypes.ClassnfABIPtrTy); 6447314564Sdim } 6448314564Sdim values.add(ObjCEmptyCacheVar); 6449314564Sdim values.add(ObjCEmptyVtableVar); 6450314564Sdim values.add(ClassRoGV); 6451314564Sdim 6452314564Sdim llvm::GlobalVariable *GV = 6453314564Sdim cast<llvm::GlobalVariable>(GetClassGlobal(CI, isMetaclass, ForDefinition)); 6454314564Sdim values.finishAndSetAsInitializer(GV); 6455314564Sdim 6456314564Sdim if (CGM.getTriple().isOSBinFormatMachO()) 6457314564Sdim GV->setSection("__DATA, __objc_data"); 6458360784Sdim GV->setAlignment(llvm::Align( 6459360784Sdim CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy))); 6460309124Sdim if (!CGM.getTriple().isOSBinFormatCOFF()) 6461309124Sdim if (HiddenVisibility) 6462309124Sdim GV->setVisibility(llvm::GlobalValue::HiddenVisibility); 6463193326Sed return GV; 6464193326Sed} 6465193326Sed 6466353358Sdimbool CGObjCNonFragileABIMac::ImplementationIsNonLazy( 6467353358Sdim const ObjCImplDecl *OD) const { 6468353358Sdim return OD->getClassMethod(GetNullarySelector("load")) != nullptr || 6469353358Sdim OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() || 6470353358Sdim OD->hasAttr<ObjCNonLazyClassAttr>(); 6471193326Sed} 6472193326Sed 6473193326Sedvoid CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, 6474193326Sed uint32_t &InstanceStart, 6475193326Sed uint32_t &InstanceSize) { 6476198092Srdivacky const ASTRecordLayout &RL = 6477193326Sed CGM.getContext().getASTObjCImplementationLayout(OID); 6478198092Srdivacky 6479193326Sed // InstanceSize is really instance end. 6480218893Sdim InstanceSize = RL.getDataSize().getQuantity(); 6481193326Sed 6482193326Sed // If there are no fields, the start is the same as the end. 6483193326Sed if (!RL.getFieldCount()) 6484193326Sed InstanceStart = InstanceSize; 6485193326Sed else 6486221345Sdim InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth(); 6487193326Sed} 6488193326Sed 6489309124Sdimstatic llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM, 6490309124Sdim StringRef Name) { 6491309124Sdim IdentifierInfo &II = CGM.getContext().Idents.get(Name); 6492309124Sdim TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl(); 6493309124Sdim DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); 6494309124Sdim 6495309124Sdim const VarDecl *VD = nullptr; 6496309124Sdim for (const auto &Result : DC->lookup(&II)) 6497309124Sdim if ((VD = dyn_cast<VarDecl>(Result))) 6498309124Sdim break; 6499309124Sdim 6500309124Sdim if (!VD) 6501309124Sdim return llvm::GlobalValue::DLLImportStorageClass; 6502309124Sdim if (VD->hasAttr<DLLExportAttr>()) 6503309124Sdim return llvm::GlobalValue::DLLExportStorageClass; 6504309124Sdim if (VD->hasAttr<DLLImportAttr>()) 6505309124Sdim return llvm::GlobalValue::DLLImportStorageClass; 6506309124Sdim return llvm::GlobalValue::DefaultStorageClass; 6507309124Sdim} 6508309124Sdim 6509193326Sedvoid CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { 6510193326Sed if (!ObjCEmptyCacheVar) { 6511309124Sdim ObjCEmptyCacheVar = 6512309124Sdim new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false, 6513309124Sdim llvm::GlobalValue::ExternalLinkage, nullptr, 6514309124Sdim "_objc_empty_cache"); 6515309124Sdim if (CGM.getTriple().isOSBinFormatCOFF()) 6516309124Sdim ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache")); 6517276479Sdim 6518309124Sdim // Only OS X with deployment version <10.9 use the empty vtable symbol 6519261991Sdim const llvm::Triple &Triple = CGM.getTarget().getTriple(); 6520309124Sdim if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9)) 6521309124Sdim ObjCEmptyVtableVar = 6522309124Sdim new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false, 6523309124Sdim llvm::GlobalValue::ExternalLinkage, nullptr, 6524309124Sdim "_objc_empty_vtable"); 6525314564Sdim else 6526314564Sdim ObjCEmptyVtableVar = 6527314564Sdim llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo()); 6528193326Sed } 6529309124Sdim 6530193326Sed // FIXME: Is this correct (that meta class size is never computed)? 6531198092Srdivacky uint32_t InstanceStart = 6532243830Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy); 6533193326Sed uint32_t InstanceSize = InstanceStart; 6534243830Sdim uint32_t flags = NonFragileABI_Class_Meta; 6535198092Srdivacky 6536314564Sdim llvm::Constant *SuperClassGV, *IsAGV; 6537198092Srdivacky 6538309124Sdim const auto *CI = ID->getClassInterface(); 6539309124Sdim assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0"); 6540309124Sdim 6541243830Sdim // Build the flags for the metaclass. 6542309124Sdim bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF()) 6543309124Sdim ? !CI->hasAttr<DLLExportAttr>() 6544309124Sdim : CI->getVisibility() == HiddenVisibility; 6545193326Sed if (classIsHidden) 6546243830Sdim flags |= NonFragileABI_Class_Hidden; 6547243830Sdim 6548243830Sdim // FIXME: why is this flag set on the metaclass? 6549243830Sdim // ObjC metaclasses have no fields and don't really get constructed. 6550243830Sdim if (ID->hasNonZeroConstructors() || ID->hasDestructors()) { 6551243830Sdim flags |= NonFragileABI_Class_HasCXXStructors; 6552243830Sdim if (!ID->hasNonZeroConstructors()) 6553309124Sdim flags |= NonFragileABI_Class_HasCXXDestructorOnly; 6554243830Sdim } 6555243830Sdim 6556309124Sdim if (!CI->getSuperClass()) { 6557193326Sed // class is root 6558243830Sdim flags |= NonFragileABI_Class_Root; 6559309124Sdim 6560314564Sdim SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition); 6561314564Sdim IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition); 6562193326Sed } else { 6563193326Sed // Has a root. Current class is not a root. 6564193326Sed const ObjCInterfaceDecl *Root = ID->getClassInterface(); 6565193326Sed while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) 6566193326Sed Root = Super; 6567309124Sdim 6568309124Sdim const auto *Super = CI->getSuperClass(); 6569314564Sdim IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition); 6570314564Sdim SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition); 6571193326Sed } 6572309124Sdim 6573309124Sdim llvm::GlobalVariable *CLASS_RO_GV = 6574309124Sdim BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID); 6575309124Sdim 6576309124Sdim llvm::GlobalVariable *MetaTClass = 6577314564Sdim BuildClassObject(CI, /*metaclass*/ true, 6578314564Sdim IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden); 6579341825Sdim CGM.setGVProperties(MetaTClass, CI); 6580199482Srdivacky DefinedMetaClasses.push_back(MetaTClass); 6581193326Sed 6582193326Sed // Metadata for the class 6583243830Sdim flags = 0; 6584193326Sed if (classIsHidden) 6585243830Sdim flags |= NonFragileABI_Class_Hidden; 6586193326Sed 6587243830Sdim if (ID->hasNonZeroConstructors() || ID->hasDestructors()) { 6588243830Sdim flags |= NonFragileABI_Class_HasCXXStructors; 6589243830Sdim 6590243830Sdim // Set a flag to enable a runtime optimization when a class has 6591243830Sdim // fields that require destruction but which don't require 6592243830Sdim // anything except zero-initialization during construction. This 6593243830Sdim // is most notably true of __strong and __weak types, but you can 6594243830Sdim // also imagine there being C++ types with non-trivial default 6595243830Sdim // constructors that merely set all fields to null. 6596243830Sdim if (!ID->hasNonZeroConstructors()) 6597243830Sdim flags |= NonFragileABI_Class_HasCXXDestructorOnly; 6598243830Sdim } 6599243830Sdim 6600309124Sdim if (hasObjCExceptionAttribute(CGM.getContext(), CI)) 6601243830Sdim flags |= NonFragileABI_Class_Exception; 6602193326Sed 6603309124Sdim if (!CI->getSuperClass()) { 6604243830Sdim flags |= NonFragileABI_Class_Root; 6605276479Sdim SuperClassGV = nullptr; 6606193326Sed } else { 6607193326Sed // Has a root. Current class is not a root. 6608309124Sdim const auto *Super = CI->getSuperClass(); 6609314564Sdim SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition); 6610193326Sed } 6611309124Sdim 6612193326Sed GetClassSizeInfo(ID, InstanceStart, InstanceSize); 6613309124Sdim CLASS_RO_GV = 6614309124Sdim BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID); 6615198092Srdivacky 6616198092Srdivacky llvm::GlobalVariable *ClassMD = 6617314564Sdim BuildClassObject(CI, /*metaclass*/ false, 6618314564Sdim MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden); 6619341825Sdim CGM.setGVProperties(ClassMD, CI); 6620193326Sed DefinedClasses.push_back(ClassMD); 6621309124Sdim ImplementedClasses.push_back(CI); 6622193326Sed 6623193326Sed // Determine if this class is also "non-lazy". 6624193326Sed if (ImplementationIsNonLazy(ID)) 6625193326Sed DefinedNonLazyClasses.push_back(ClassMD); 6626193326Sed 6627193326Sed // Force the definition of the EHType if necessary. 6628243830Sdim if (flags & NonFragileABI_Class_Exception) 6629314564Sdim (void) GetInterfaceEHType(CI, ForDefinition); 6630221345Sdim // Make sure method definition entries are all clear for next implementation. 6631221345Sdim MethodDefinitions.clear(); 6632193326Sed} 6633193326Sed 6634193326Sed/// GenerateProtocolRef - This routine is called to generate code for 6635193326Sed/// a protocol reference expression; as in: 6636193326Sed/// @code 6637193326Sed/// @protocol(Proto1); 6638193326Sed/// @endcode 6639193326Sed/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1 6640193326Sed/// which will hold address of the protocol meta-data. 6641193326Sed/// 6642249423Sdimllvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, 6643198092Srdivacky const ObjCProtocolDecl *PD) { 6644198092Srdivacky 6645193326Sed // This routine is called for @protocol only. So, we must build definition 6646193326Sed // of protocol's meta-data (not a reference to it!) 6647193326Sed // 6648198092Srdivacky llvm::Constant *Init = 6649198092Srdivacky llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD), 6650234353Sdim ObjCTypes.getExternalProtocolPtrTy()); 6651198092Srdivacky 6652353358Sdim std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_"); 6653276479Sdim ProtocolName += PD->getObjCRuntimeNameAsString(); 6654198092Srdivacky 6655296417Sdim CharUnits Align = CGF.getPointerAlign(); 6656296417Sdim 6657193326Sed llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName); 6658193326Sed if (PTGV) 6659296417Sdim return CGF.Builder.CreateAlignedLoad(PTGV, Align); 6660321369Sdim PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 6661321369Sdim llvm::GlobalValue::WeakAnyLinkage, Init, 6662321369Sdim ProtocolName); 6663321369Sdim PTGV->setSection(GetSectionName("__objc_protorefs", 6664321369Sdim "coalesced,no_dead_strip")); 6665193326Sed PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 6666360784Sdim PTGV->setAlignment(Align.getAsAlign()); 6667321369Sdim if (!CGM.getTriple().isOSBinFormatMachO()) 6668321369Sdim PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName)); 6669341825Sdim CGM.addUsedGlobal(PTGV); 6670296417Sdim return CGF.Builder.CreateAlignedLoad(PTGV, Align); 6671193326Sed} 6672193326Sed 6673193326Sed/// GenerateCategory - Build metadata for a category implementation. 6674193326Sed/// struct _category_t { 6675193326Sed/// const char * const name; 6676193326Sed/// struct _class_t *const cls; 6677193326Sed/// const struct _method_list_t * const instance_methods; 6678193326Sed/// const struct _method_list_t * const class_methods; 6679193326Sed/// const struct _protocol_list_t * const protocols; 6680193326Sed/// const struct _prop_list_t * const properties; 6681309124Sdim/// const struct _prop_list_t * const class_properties; 6682309124Sdim/// const uint32_t size; 6683193326Sed/// } 6684193326Sed/// 6685193326Sedvoid CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 6686193326Sed const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); 6687353358Sdim const char *Prefix = "_OBJC_$_CATEGORY_"; 6688341825Sdim 6689276479Sdim llvm::SmallString<64> ExtCatName(Prefix); 6690276479Sdim ExtCatName += Interface->getObjCRuntimeNameAsString(); 6691276479Sdim ExtCatName += "_$_"; 6692276479Sdim ExtCatName += OCD->getNameAsString(); 6693341825Sdim 6694314564Sdim ConstantInitBuilder builder(CGM); 6695314564Sdim auto values = builder.beginStruct(ObjCTypes.CategorynfABITy); 6696314564Sdim values.add(GetClassName(OCD->getIdentifier()->getName())); 6697193326Sed // meta-class entry symbol 6698314564Sdim values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition)); 6699314564Sdim std::string listName = 6700314564Sdim (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str(); 6701276479Sdim 6702314564Sdim SmallVector<const ObjCMethodDecl *, 16> instanceMethods; 6703314564Sdim SmallVector<const ObjCMethodDecl *, 8> classMethods; 6704314564Sdim for (const auto *MD : OCD->methods()) { 6705360784Sdim if (MD->isDirectMethod()) 6706360784Sdim continue; 6707314564Sdim if (MD->isInstanceMethod()) { 6708314564Sdim instanceMethods.push_back(MD); 6709314564Sdim } else { 6710314564Sdim classMethods.push_back(MD); 6711314564Sdim } 6712314564Sdim } 6713198092Srdivacky 6714314564Sdim values.add(emitMethodList(listName, MethodListType::CategoryInstanceMethods, 6715314564Sdim instanceMethods)); 6716314564Sdim values.add(emitMethodList(listName, MethodListType::CategoryClassMethods, 6717314564Sdim classMethods)); 6718198092Srdivacky 6719198092Srdivacky const ObjCCategoryDecl *Category = 6720193326Sed Interface->FindCategoryDeclaration(OCD->getIdentifier()); 6721193326Sed if (Category) { 6722234353Sdim SmallString<256> ExtName; 6723276479Sdim llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_" 6724198398Srdivacky << OCD->getName(); 6725353358Sdim values.add(EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_" 6726276479Sdim + Interface->getObjCRuntimeNameAsString() + "_$_" 6727276479Sdim + Category->getName(), 6728314564Sdim Category->protocol_begin(), 6729314564Sdim Category->protocol_end())); 6730353358Sdim values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(), 6731314564Sdim OCD, Category, ObjCTypes, false)); 6732353358Sdim values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), 6733314564Sdim OCD, Category, ObjCTypes, true)); 6734198092Srdivacky } else { 6735314564Sdim values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy); 6736314564Sdim values.addNullPointer(ObjCTypes.PropertyListPtrTy); 6737314564Sdim values.addNullPointer(ObjCTypes.PropertyListPtrTy); 6738193326Sed } 6739198092Srdivacky 6740309124Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy); 6741314564Sdim values.addInt(ObjCTypes.IntTy, Size); 6742309124Sdim 6743314564Sdim llvm::GlobalVariable *GCATV = 6744353358Sdim finishAndCreateGlobal(values, ExtCatName.str(), CGM); 6745276479Sdim CGM.addCompilerUsedGlobal(GCATV); 6746353358Sdim if (Interface->hasAttr<ObjCClassStubAttr>()) 6747353358Sdim DefinedStubCategories.push_back(GCATV); 6748353358Sdim else 6749353358Sdim DefinedCategories.push_back(GCATV); 6750193326Sed 6751193326Sed // Determine if this category is also "non-lazy". 6752193326Sed if (ImplementationIsNonLazy(OCD)) 6753193326Sed DefinedNonLazyCategories.push_back(GCATV); 6754221345Sdim // method definition entries must be clear for next implementation. 6755221345Sdim MethodDefinitions.clear(); 6756193326Sed} 6757193326Sed 6758314564Sdim/// emitMethodConstant - Return a struct objc_method constant. If 6759314564Sdim/// forProtocol is true, the implementation will be null; otherwise, 6760314564Sdim/// the method must have a definition registered with the runtime. 6761314564Sdim/// 6762314564Sdim/// struct _objc_method { 6763314564Sdim/// SEL _cmd; 6764314564Sdim/// char *method_type; 6765314564Sdim/// char *_imp; 6766314564Sdim/// } 6767314564Sdimvoid CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder, 6768314564Sdim const ObjCMethodDecl *MD, 6769314564Sdim bool forProtocol) { 6770314564Sdim auto method = builder.beginStruct(ObjCTypes.MethodTy); 6771314564Sdim method.addBitCast(GetMethodVarName(MD->getSelector()), 6772314564Sdim ObjCTypes.SelectorPtrTy); 6773314564Sdim method.add(GetMethodVarType(MD)); 6774198092Srdivacky 6775314564Sdim if (forProtocol) { 6776314564Sdim // Protocol methods have no implementation. So, this entry is always NULL. 6777314564Sdim method.addNullPointer(ObjCTypes.Int8PtrTy); 6778314564Sdim } else { 6779314564Sdim llvm::Function *fn = GetMethodDefinition(MD); 6780314564Sdim assert(fn && "no definition for method?"); 6781314564Sdim method.addBitCast(fn, ObjCTypes.Int8PtrTy); 6782314564Sdim } 6783314564Sdim 6784314564Sdim method.finishAndAddTo(builder); 6785193326Sed} 6786193326Sed 6787314564Sdim/// Build meta-data for method declarations. 6788314564Sdim/// 6789193326Sed/// struct _method_list_t { 6790193326Sed/// uint32_t entsize; // sizeof(struct _objc_method) 6791193326Sed/// uint32_t method_count; 6792193326Sed/// struct _objc_method method_list[method_count]; 6793193326Sed/// } 6794193326Sed/// 6795234353Sdimllvm::Constant * 6796314564SdimCGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind, 6797314564Sdim ArrayRef<const ObjCMethodDecl *> methods) { 6798193326Sed // Return null for empty list. 6799314564Sdim if (methods.empty()) 6800193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy); 6801198092Srdivacky 6802314564Sdim StringRef prefix; 6803314564Sdim bool forProtocol; 6804314564Sdim switch (kind) { 6805314564Sdim case MethodListType::CategoryInstanceMethods: 6806353358Sdim prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_"; 6807314564Sdim forProtocol = false; 6808314564Sdim break; 6809314564Sdim case MethodListType::CategoryClassMethods: 6810353358Sdim prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_"; 6811314564Sdim forProtocol = false; 6812314564Sdim break; 6813314564Sdim case MethodListType::InstanceMethods: 6814353358Sdim prefix = "_OBJC_$_INSTANCE_METHODS_"; 6815314564Sdim forProtocol = false; 6816314564Sdim break; 6817314564Sdim case MethodListType::ClassMethods: 6818353358Sdim prefix = "_OBJC_$_CLASS_METHODS_"; 6819314564Sdim forProtocol = false; 6820314564Sdim break; 6821314564Sdim 6822314564Sdim case MethodListType::ProtocolInstanceMethods: 6823353358Sdim prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_"; 6824314564Sdim forProtocol = true; 6825314564Sdim break; 6826314564Sdim case MethodListType::ProtocolClassMethods: 6827353358Sdim prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_"; 6828314564Sdim forProtocol = true; 6829314564Sdim break; 6830314564Sdim case MethodListType::OptionalProtocolInstanceMethods: 6831353358Sdim prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"; 6832314564Sdim forProtocol = true; 6833314564Sdim break; 6834314564Sdim case MethodListType::OptionalProtocolClassMethods: 6835353358Sdim prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"; 6836314564Sdim forProtocol = true; 6837314564Sdim break; 6838314564Sdim } 6839314564Sdim 6840314564Sdim ConstantInitBuilder builder(CGM); 6841314564Sdim auto values = builder.beginStruct(); 6842314564Sdim 6843193326Sed // sizeof(struct _objc_method) 6844243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy); 6845314564Sdim values.addInt(ObjCTypes.IntTy, Size); 6846193326Sed // method_count 6847314564Sdim values.addInt(ObjCTypes.IntTy, methods.size()); 6848314564Sdim auto methodArray = values.beginArray(ObjCTypes.MethodTy); 6849360784Sdim for (auto MD : methods) 6850314564Sdim emitMethodConstant(methodArray, MD, forProtocol); 6851314564Sdim methodArray.finishAndAddTo(values); 6852198092Srdivacky 6853353358Sdim llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM); 6854276479Sdim CGM.addCompilerUsedGlobal(GV); 6855224145Sdim return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy); 6856193326Sed} 6857193326Sed 6858193326Sed/// ObjCIvarOffsetVariable - Returns the ivar offset variable for 6859193326Sed/// the given ivar. 6860206125Srdivackyllvm::GlobalVariable * 6861206125SrdivackyCGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, 6862206125Srdivacky const ObjCIvarDecl *Ivar) { 6863206125Srdivacky const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); 6864276479Sdim llvm::SmallString<64> Name("OBJC_IVAR_$_"); 6865276479Sdim Name += Container->getObjCRuntimeNameAsString(); 6866276479Sdim Name += "."; 6867276479Sdim Name += Ivar->getName(); 6868309124Sdim llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name); 6869309124Sdim if (!IvarOffsetGV) { 6870309124Sdim IvarOffsetGV = 6871309124Sdim new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy, 6872309124Sdim false, llvm::GlobalValue::ExternalLinkage, 6873309124Sdim nullptr, Name.str()); 6874309124Sdim if (CGM.getTriple().isOSBinFormatCOFF()) { 6875309124Sdim bool IsPrivateOrPackage = 6876309124Sdim Ivar->getAccessControl() == ObjCIvarDecl::Private || 6877309124Sdim Ivar->getAccessControl() == ObjCIvarDecl::Package; 6878309124Sdim 6879327952Sdim const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface(); 6880327952Sdim 6881327952Sdim if (ContainingID->hasAttr<DLLImportAttr>()) 6882327952Sdim IvarOffsetGV 6883327952Sdim ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); 6884327952Sdim else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage) 6885327952Sdim IvarOffsetGV 6886327952Sdim ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); 6887309124Sdim } 6888309124Sdim } 6889193326Sed return IvarOffsetGV; 6890193326Sed} 6891193326Sed 6892206125Srdivackyllvm::Constant * 6893206125SrdivackyCGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, 6894206125Srdivacky const ObjCIvarDecl *Ivar, 6895206125Srdivacky unsigned long int Offset) { 6896193326Sed llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar); 6897276479Sdim IvarOffsetGV->setInitializer( 6898276479Sdim llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset)); 6899360784Sdim IvarOffsetGV->setAlignment(llvm::Align( 6900360784Sdim CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy))); 6901193326Sed 6902309124Sdim if (!CGM.getTriple().isOSBinFormatCOFF()) { 6903309124Sdim // FIXME: This matches gcc, but shouldn't the visibility be set on the use 6904309124Sdim // as well (i.e., in ObjCIvarOffsetVariable). 6905309124Sdim if (Ivar->getAccessControl() == ObjCIvarDecl::Private || 6906309124Sdim Ivar->getAccessControl() == ObjCIvarDecl::Package || 6907309124Sdim ID->getVisibility() == HiddenVisibility) 6908309124Sdim IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 6909309124Sdim else 6910309124Sdim IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); 6911309124Sdim } 6912309124Sdim 6913353358Sdim // If ID's layout is known, then make the global constant. This serves as a 6914353358Sdim // useful assertion: we'll never use this variable to calculate ivar offsets, 6915353358Sdim // so if the runtime tries to patch it then we should crash. 6916353358Sdim if (isClassLayoutKnownStatically(ID)) 6917353358Sdim IvarOffsetGV->setConstant(true); 6918353358Sdim 6919314564Sdim if (CGM.getTriple().isOSBinFormatMachO()) 6920314564Sdim IvarOffsetGV->setSection("__DATA, __objc_ivar"); 6921193326Sed return IvarOffsetGV; 6922193326Sed} 6923193326Sed 6924193326Sed/// EmitIvarList - Emit the ivar list for the given 6925193326Sed/// implementation. The return value has type 6926193326Sed/// IvarListnfABIPtrTy. 6927193326Sed/// struct _ivar_t { 6928276479Sdim/// unsigned [long] int *offset; // pointer to ivar offset location 6929193326Sed/// char *name; 6930193326Sed/// char *type; 6931193326Sed/// uint32_t alignment; 6932193326Sed/// uint32_t size; 6933193326Sed/// } 6934193326Sed/// struct _ivar_list_t { 6935193326Sed/// uint32 entsize; // sizeof(struct _ivar_t) 6936193326Sed/// uint32 count; 6937193326Sed/// struct _iver_t list[count]; 6938193326Sed/// } 6939193326Sed/// 6940193326Sed 6941193326Sedllvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( 6942198092Srdivacky const ObjCImplementationDecl *ID) { 6943198092Srdivacky 6944314564Sdim ConstantInitBuilder builder(CGM); 6945314564Sdim auto ivarList = builder.beginStruct(); 6946314564Sdim ivarList.addInt(ObjCTypes.IntTy, 6947314564Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy)); 6948314564Sdim auto ivarCountSlot = ivarList.addPlaceholder(); 6949314564Sdim auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy); 6950198092Srdivacky 6951226633Sdim const ObjCInterfaceDecl *OID = ID->getClassInterface(); 6952193326Sed assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface"); 6953198092Srdivacky 6954193326Sed // FIXME. Consolidate this with similar code in GenerateClass. 6955198092Srdivacky 6956341825Sdim for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); 6957224145Sdim IVD; IVD = IVD->getNextIvar()) { 6958193576Sed // Ignore unnamed bit-fields. 6959193576Sed if (!IVD->getDeclName()) 6960193576Sed continue; 6961314564Sdim 6962314564Sdim auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy); 6963314564Sdim ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD, 6964314564Sdim ComputeIvarBaseOffset(CGM, ID, IVD))); 6965314564Sdim ivar.add(GetMethodVarName(IVD->getIdentifier())); 6966314564Sdim ivar.add(GetMethodVarType(IVD)); 6967226633Sdim llvm::Type *FieldTy = 6968193326Sed CGM.getTypes().ConvertTypeForMem(IVD->getType()); 6969243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy); 6970193326Sed unsigned Align = CGM.getContext().getPreferredTypeAlign( 6971198092Srdivacky IVD->getType().getTypePtr()) >> 3; 6972193326Sed Align = llvm::Log2_32(Align); 6973314564Sdim ivar.addInt(ObjCTypes.IntTy, Align); 6974193326Sed // NOTE. Size of a bitfield does not match gcc's, because of the 6975193326Sed // way bitfields are treated special in each. But I am told that 6976193326Sed // 'size' for bitfield ivars is ignored by the runtime so it does 6977193326Sed // not matter. If it matters, there is enough info to get the 6978193326Sed // bitfield right! 6979314564Sdim ivar.addInt(ObjCTypes.IntTy, Size); 6980314564Sdim ivar.finishAndAddTo(ivars); 6981193326Sed } 6982193326Sed // Return null for empty list. 6983314564Sdim if (ivars.empty()) { 6984314564Sdim ivars.abandon(); 6985314564Sdim ivarList.abandon(); 6986193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); 6987314564Sdim } 6988224145Sdim 6989314564Sdim auto ivarCount = ivars.size(); 6990314564Sdim ivars.finishAndAddTo(ivarList); 6991314564Sdim ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount); 6992314564Sdim 6993353358Sdim const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_"; 6994353358Sdim llvm::GlobalVariable *GV = finishAndCreateGlobal( 6995353358Sdim ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM); 6996276479Sdim CGM.addCompilerUsedGlobal(GV); 6997198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy); 6998193326Sed} 6999193326Sed 7000193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( 7001198092Srdivacky const ObjCProtocolDecl *PD) { 7002193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 7003198092Srdivacky 7004314564Sdim if (!Entry) { 7005193326Sed // We use the initializer as a marker of whether this is a forward 7006193326Sed // reference or not. At module finalization we add the empty 7007193326Sed // contents for protocols which were referenced but never defined. 7008314564Sdim llvm::SmallString<64> Protocol; 7009353358Sdim llvm::raw_svector_ostream(Protocol) << "_OBJC_PROTOCOL_$_" 7010314564Sdim << PD->getObjCRuntimeNameAsString(); 7011198092Srdivacky 7012314564Sdim Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, 7013314564Sdim false, llvm::GlobalValue::ExternalLinkage, 7014314564Sdim nullptr, Protocol); 7015314564Sdim if (!CGM.getTriple().isOSBinFormatMachO()) 7016314564Sdim Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol)); 7017314564Sdim } 7018314564Sdim 7019193326Sed return Entry; 7020193326Sed} 7021193326Sed 7022193326Sed/// GetOrEmitProtocol - Generate the protocol meta-data: 7023193326Sed/// @code 7024193326Sed/// struct _protocol_t { 7025193326Sed/// id isa; // NULL 7026193326Sed/// const char * const protocol_name; 7027193326Sed/// const struct _protocol_list_t * protocol_list; // super protocols 7028193326Sed/// const struct method_list_t * const instance_methods; 7029193326Sed/// const struct method_list_t * const class_methods; 7030193326Sed/// const struct method_list_t *optionalInstanceMethods; 7031193326Sed/// const struct method_list_t *optionalClassMethods; 7032193326Sed/// const struct _prop_list_t * properties; 7033193326Sed/// const uint32_t size; // sizeof(struct _protocol_t) 7034193326Sed/// const uint32_t flags; // = 0 7035234353Sdim/// const char ** extendedMethodTypes; 7036288943Sdim/// const char *demangledName; 7037309124Sdim/// const struct _prop_list_t * class_properties; 7038193326Sed/// } 7039193326Sed/// @endcode 7040193326Sed/// 7041193326Sed 7042193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( 7043198092Srdivacky const ObjCProtocolDecl *PD) { 7044234353Sdim llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()]; 7045198092Srdivacky 7046193326Sed // Early exit if a defining object has already been generated. 7047193326Sed if (Entry && Entry->hasInitializer()) 7048193326Sed return Entry; 7049193326Sed 7050234353Sdim // Use the protocol definition, if there is one. 7051344779Sdim assert(PD->hasDefinition() && 7052344779Sdim "emitting protocol metadata without definition"); 7053344779Sdim PD = PD->getDefinition(); 7054341825Sdim 7055314564Sdim auto methodLists = ProtocolMethodLists::get(PD); 7056198092Srdivacky 7057314564Sdim ConstantInitBuilder builder(CGM); 7058314564Sdim auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy); 7059223017Sdim 7060193326Sed // isa is NULL 7061314564Sdim values.addNullPointer(ObjCTypes.ObjectPtrTy); 7062314564Sdim values.add(GetClassName(PD->getObjCRuntimeNameAsString())); 7063353358Sdim values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_" 7064314564Sdim + PD->getObjCRuntimeNameAsString(), 7065198398Srdivacky PD->protocol_begin(), 7066314564Sdim PD->protocol_end())); 7067314564Sdim values.add(methodLists.emitMethodList(this, PD, 7068314564Sdim ProtocolMethodLists::RequiredInstanceMethods)); 7069314564Sdim values.add(methodLists.emitMethodList(this, PD, 7070314564Sdim ProtocolMethodLists::RequiredClassMethods)); 7071314564Sdim values.add(methodLists.emitMethodList(this, PD, 7072314564Sdim ProtocolMethodLists::OptionalInstanceMethods)); 7073314564Sdim values.add(methodLists.emitMethodList(this, PD, 7074314564Sdim ProtocolMethodLists::OptionalClassMethods)); 7075314564Sdim values.add(EmitPropertyList( 7076353358Sdim "_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), 7077314564Sdim nullptr, PD, ObjCTypes, false)); 7078198092Srdivacky uint32_t Size = 7079243830Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); 7080314564Sdim values.addInt(ObjCTypes.IntTy, Size); 7081314564Sdim values.addInt(ObjCTypes.IntTy, 0); 7082353358Sdim values.add(EmitProtocolMethodTypes("_OBJC_$_PROTOCOL_METHOD_TYPES_" 7083276479Sdim + PD->getObjCRuntimeNameAsString(), 7084314564Sdim methodLists.emitExtendedTypesArray(this), 7085314564Sdim ObjCTypes)); 7086314564Sdim 7087288943Sdim // const char *demangledName; 7088314564Sdim values.addNullPointer(ObjCTypes.Int8PtrTy); 7089309124Sdim 7090314564Sdim values.add(EmitPropertyList( 7091353358Sdim "_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), 7092314564Sdim nullptr, PD, ObjCTypes, true)); 7093341825Sdim 7094193326Sed if (Entry) { 7095280031Sdim // Already created, fix the linkage and update the initializer. 7096280031Sdim Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 7097314564Sdim values.finishAndSetAsInitializer(Entry); 7098193326Sed } else { 7099314564Sdim llvm::SmallString<64> symbolName; 7100314564Sdim llvm::raw_svector_ostream(symbolName) 7101353358Sdim << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString(); 7102234353Sdim 7103314564Sdim Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(), 7104314564Sdim /*constant*/ false, 7105314564Sdim llvm::GlobalValue::WeakAnyLinkage); 7106314564Sdim if (!CGM.getTriple().isOSBinFormatMachO()) 7107314564Sdim Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName)); 7108314564Sdim 7109234353Sdim Protocols[PD->getIdentifier()] = Entry; 7110193326Sed } 7111193326Sed Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); 7112341825Sdim CGM.addUsedGlobal(Entry); 7113198092Srdivacky 7114193326Sed // Use this protocol meta-data to build protocol list table in section 7115193326Sed // __DATA, __objc_protolist 7116314564Sdim llvm::SmallString<64> ProtocolRef; 7117353358Sdim llvm::raw_svector_ostream(ProtocolRef) << "_OBJC_LABEL_PROTOCOL_$_" 7118314564Sdim << PD->getObjCRuntimeNameAsString(); 7119314564Sdim 7120198398Srdivacky llvm::GlobalVariable *PTGV = 7121198398Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, 7122198398Srdivacky false, llvm::GlobalValue::WeakAnyLinkage, Entry, 7123314564Sdim ProtocolRef); 7124314564Sdim if (!CGM.getTriple().isOSBinFormatMachO()) 7125314564Sdim PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef)); 7126360784Sdim PTGV->setAlignment(llvm::Align( 7127360784Sdim CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy))); 7128321369Sdim PTGV->setSection(GetSectionName("__objc_protolist", 7129321369Sdim "coalesced,no_dead_strip")); 7130193326Sed PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 7131341825Sdim CGM.addUsedGlobal(PTGV); 7132193326Sed return Entry; 7133193326Sed} 7134193326Sed 7135193326Sed/// EmitProtocolList - Generate protocol list meta-data: 7136193326Sed/// @code 7137193326Sed/// struct _protocol_list_t { 7138193326Sed/// long protocol_count; // Note, this is 32/64 bit 7139193326Sed/// struct _protocol_t[protocol_count]; 7140193326Sed/// } 7141193326Sed/// @endcode 7142193326Sed/// 7143193326Sedllvm::Constant * 7144226633SdimCGObjCNonFragileABIMac::EmitProtocolList(Twine Name, 7145198398Srdivacky ObjCProtocolDecl::protocol_iterator begin, 7146198398Srdivacky ObjCProtocolDecl::protocol_iterator end) { 7147249423Sdim SmallVector<llvm::Constant *, 16> ProtocolRefs; 7148198092Srdivacky 7149193326Sed // Just return null for empty protocol lists 7150198092Srdivacky if (begin == end) 7151193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); 7152198092Srdivacky 7153193326Sed // FIXME: We shouldn't need to do this lookup here, should we? 7154234353Sdim SmallString<256> TmpName; 7155198398Srdivacky Name.toVector(TmpName); 7156198398Srdivacky llvm::GlobalVariable *GV = 7157198398Srdivacky CGM.getModule().getGlobalVariable(TmpName.str(), true); 7158193326Sed if (GV) 7159198398Srdivacky return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy); 7160198092Srdivacky 7161314564Sdim ConstantInitBuilder builder(CGM); 7162314564Sdim auto values = builder.beginStruct(); 7163314564Sdim auto countSlot = values.addPlaceholder(); 7164314564Sdim 7165314564Sdim // A null-terminated array of protocols. 7166314564Sdim auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy); 7167193326Sed for (; begin != end; ++begin) 7168314564Sdim array.add(GetProtocolRef(*begin)); // Implemented??? 7169314564Sdim auto count = array.size(); 7170314564Sdim array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy); 7171193326Sed 7172314564Sdim array.finishAndAddTo(values); 7173314564Sdim values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count); 7174198092Srdivacky 7175353358Sdim GV = finishAndCreateGlobal(values, Name, CGM); 7176276479Sdim CGM.addCompilerUsedGlobal(GV); 7177198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, 7178193326Sed ObjCTypes.ProtocolListnfABIPtrTy); 7179193326Sed} 7180193326Sed 7181193326Sed/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference. 7182193326Sed/// This code gen. amounts to generating code for: 7183193326Sed/// @code 7184193326Sed/// (type *)((char *)base + _OBJC_IVAR_$_.ivar; 7185193326Sed/// @encode 7186198092Srdivacky/// 7187193326SedLValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( 7188208600Srdivacky CodeGen::CodeGenFunction &CGF, 7189208600Srdivacky QualType ObjectTy, 7190208600Srdivacky llvm::Value *BaseValue, 7191208600Srdivacky const ObjCIvarDecl *Ivar, 7192208600Srdivacky unsigned CVRQualifiers) { 7193360784Sdim ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface(); 7194234353Sdim llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar); 7195193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 7196234353Sdim Offset); 7197193326Sed} 7198193326Sed 7199353358Sdimllvm::Value * 7200353358SdimCGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 7201353358Sdim const ObjCInterfaceDecl *Interface, 7202353358Sdim const ObjCIvarDecl *Ivar) { 7203353358Sdim llvm::Value *IvarOffsetValue; 7204353358Sdim if (isClassLayoutKnownStatically(Interface)) { 7205353358Sdim IvarOffsetValue = llvm::ConstantInt::get( 7206353358Sdim ObjCTypes.IvarOffsetVarTy, 7207353358Sdim ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar)); 7208353358Sdim } else { 7209353358Sdim llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar); 7210353358Sdim IvarOffsetValue = 7211353358Sdim CGF.Builder.CreateAlignedLoad(GV, CGF.getSizeAlign(), "ivar"); 7212353358Sdim if (IsIvarOffsetKnownIdempotent(CGF, Ivar)) 7213353358Sdim cast<llvm::LoadInst>(IvarOffsetValue) 7214353358Sdim ->setMetadata(CGM.getModule().getMDKindID("invariant.load"), 7215353358Sdim llvm::MDNode::get(VMContext, None)); 7216353358Sdim } 7217276479Sdim 7218276479Sdim // This could be 32bit int or 64bit integer depending on the architecture. 7219276479Sdim // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value 7220341825Sdim // as this is what caller always expects. 7221276479Sdim if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy) 7222276479Sdim IvarOffsetValue = CGF.Builder.CreateIntCast( 7223276479Sdim IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv"); 7224276479Sdim return IvarOffsetValue; 7225193326Sed} 7226193326Sed 7227223017Sdimstatic void appendSelectorForMessageRefTable(std::string &buffer, 7228223017Sdim Selector selector) { 7229223017Sdim if (selector.isUnarySelector()) { 7230223017Sdim buffer += selector.getNameForSlot(0); 7231223017Sdim return; 7232223017Sdim } 7233198092Srdivacky 7234223017Sdim for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) { 7235223017Sdim buffer += selector.getNameForSlot(i); 7236223017Sdim buffer += '_'; 7237223017Sdim } 7238223017Sdim} 7239223017Sdim 7240309124Sdim/// Emit a "vtable" message send. We emit a weak hidden-visibility 7241223017Sdim/// struct, initially containing the selector pointer and a pointer to 7242223017Sdim/// a "fixup" variant of the appropriate objc_msgSend. To call, we 7243223017Sdim/// load and call the function pointer, passing the address of the 7244223017Sdim/// struct as the second parameter. The runtime determines whether 7245223017Sdim/// the selector is currently emitted using vtable dispatch; if so, it 7246223017Sdim/// substitutes a stub function which simply tail-calls through the 7247223017Sdim/// appropriate vtable slot, and if not, it substitues a stub function 7248223017Sdim/// which tail-calls objc_msgSend. Both stubs adjust the selector 7249223017Sdim/// argument to correctly point to the selector. 7250223017SdimRValue 7251223017SdimCGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, 7252223017Sdim ReturnValueSlot returnSlot, 7253223017Sdim QualType resultType, 7254223017Sdim Selector selector, 7255223017Sdim llvm::Value *arg0, 7256223017Sdim QualType arg0Type, 7257223017Sdim bool isSuper, 7258223017Sdim const CallArgList &formalArgs, 7259223017Sdim const ObjCMethodDecl *method) { 7260223017Sdim // Compute the actual arguments. 7261223017Sdim CallArgList args; 7262223017Sdim 7263223017Sdim // First argument: the receiver / super-call structure. 7264223017Sdim if (!isSuper) 7265223017Sdim arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy); 7266223017Sdim args.add(RValue::get(arg0), arg0Type); 7267223017Sdim 7268223017Sdim // Second argument: a pointer to the message ref structure. Leave 7269223017Sdim // the actual argument value blank for now. 7270276479Sdim args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy); 7271223017Sdim 7272223017Sdim args.insert(args.end(), formalArgs.begin(), formalArgs.end()); 7273223017Sdim 7274234353Sdim MessageSendInfo MSI = getMessageSendInfo(method, resultType, args); 7275223017Sdim 7276223017Sdim NullReturnState nullReturn; 7277223017Sdim 7278223017Sdim // Find the function to call and the mangled name for the message 7279223017Sdim // ref structure. Using a different mangled name wouldn't actually 7280223017Sdim // be a problem; it would just be a waste. 7281223017Sdim // 7282223017Sdim // The runtime currently never uses vtable dispatch for anything 7283223017Sdim // except normal, non-super message-sends. 7284223017Sdim // FIXME: don't use this for that. 7285353358Sdim llvm::FunctionCallee fn = nullptr; 7286353358Sdim std::string messageRefName("_"); 7287276479Sdim if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) { 7288223017Sdim if (isSuper) { 7289223017Sdim fn = ObjCTypes.getMessageSendSuper2StretFixupFn(); 7290223017Sdim messageRefName += "objc_msgSendSuper2_stret_fixup"; 7291212904Sdim } else { 7292223017Sdim nullReturn.init(CGF, arg0); 7293223017Sdim fn = ObjCTypes.getMessageSendStretFixupFn(); 7294223017Sdim messageRefName += "objc_msgSend_stret_fixup"; 7295212904Sdim } 7296223017Sdim } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) { 7297223017Sdim fn = ObjCTypes.getMessageSendFpretFixupFn(); 7298223017Sdim messageRefName += "objc_msgSend_fpret_fixup"; 7299198092Srdivacky } else { 7300223017Sdim if (isSuper) { 7301223017Sdim fn = ObjCTypes.getMessageSendSuper2FixupFn(); 7302223017Sdim messageRefName += "objc_msgSendSuper2_fixup"; 7303212904Sdim } else { 7304223017Sdim fn = ObjCTypes.getMessageSendFixupFn(); 7305223017Sdim messageRefName += "objc_msgSend_fixup"; 7306212904Sdim } 7307193326Sed } 7308223017Sdim assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend"); 7309223017Sdim messageRefName += '_'; 7310223017Sdim 7311223017Sdim // Append the selector name, except use underscores anywhere we 7312223017Sdim // would have used colons. 7313223017Sdim appendSelectorForMessageRefTable(messageRefName, selector); 7314223017Sdim 7315223017Sdim llvm::GlobalVariable *messageRef 7316223017Sdim = CGM.getModule().getGlobalVariable(messageRefName); 7317223017Sdim if (!messageRef) { 7318223017Sdim // Build the message ref structure. 7319314564Sdim ConstantInitBuilder builder(CGM); 7320314564Sdim auto values = builder.beginStruct(); 7321353358Sdim values.add(cast<llvm::Constant>(fn.getCallee())); 7322314564Sdim values.add(GetMethodVarName(selector)); 7323314564Sdim messageRef = values.finishAndCreateGlobal(messageRefName, 7324314564Sdim CharUnits::fromQuantity(16), 7325314564Sdim /*constant*/ false, 7326314564Sdim llvm::GlobalValue::WeakAnyLinkage); 7327223017Sdim messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility); 7328321369Sdim messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced")); 7329193326Sed } 7330341825Sdim 7331234353Sdim bool requiresnullCheck = false; 7332234353Sdim if (CGM.getLangOpts().ObjCAutoRefCount && method) 7333309124Sdim for (const auto *ParamDecl : method->parameters()) { 7334234353Sdim if (ParamDecl->hasAttr<NSConsumedAttr>()) { 7335234353Sdim if (!nullReturn.NullBB) 7336234353Sdim nullReturn.init(CGF, arg0); 7337234353Sdim requiresnullCheck = true; 7338234353Sdim break; 7339234353Sdim } 7340234353Sdim } 7341341825Sdim 7342296417Sdim Address mref = 7343296417Sdim Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy), 7344296417Sdim CGF.getPointerAlign()); 7345198092Srdivacky 7346223017Sdim // Update the message ref argument. 7347341825Sdim args[1].setRValue(RValue::get(mref.getPointer())); 7348223017Sdim 7349223017Sdim // Load the function to call from the message ref table. 7350353358Sdim Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0); 7351314564Sdim llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn"); 7352223017Sdim 7353314564Sdim calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType); 7354314564Sdim CGCallee callee(CGCalleeInfo(), calleePtr); 7355223017Sdim 7356234353Sdim RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args); 7357321369Sdim return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs, 7358276479Sdim requiresnullCheck ? method : nullptr); 7359193326Sed} 7360193326Sed 7361193326Sed/// Generate code for a message send expression in the nonfragile abi. 7362198092SrdivackyCodeGen::RValue 7363198092SrdivackyCGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 7364208600Srdivacky ReturnValueSlot Return, 7365198092Srdivacky QualType ResultType, 7366198092Srdivacky Selector Sel, 7367198092Srdivacky llvm::Value *Receiver, 7368198092Srdivacky const CallArgList &CallArgs, 7369207619Srdivacky const ObjCInterfaceDecl *Class, 7370198092Srdivacky const ObjCMethodDecl *Method) { 7371223017Sdim return isVTableDispatchedSelector(Sel) 7372223017Sdim ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, 7373198092Srdivacky Receiver, CGF.getContext().getObjCIdType(), 7374223017Sdim false, CallArgs, Method) 7375360784Sdim : EmitMessageSend(CGF, Return, ResultType, Sel, 7376198092Srdivacky Receiver, CGF.getContext().getObjCIdType(), 7377296417Sdim false, CallArgs, Method, Class, ObjCTypes); 7378193326Sed} 7379193326Sed 7380314564Sdimllvm::Constant * 7381314564SdimCGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID, 7382314564Sdim bool metaclass, 7383314564Sdim ForDefinition_t isForDefinition) { 7384314564Sdim auto prefix = 7385314564Sdim (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix()); 7386314564Sdim return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(), 7387314564Sdim isForDefinition, 7388314564Sdim ID->isWeakImported(), 7389314564Sdim !isForDefinition 7390314564Sdim && CGM.getTriple().isOSBinFormatCOFF() 7391314564Sdim && ID->hasAttr<DLLImportAttr>()); 7392314564Sdim} 7393314564Sdim 7394314564Sdimllvm::Constant * 7395314564SdimCGObjCNonFragileABIMac::GetClassGlobal(StringRef Name, 7396314564Sdim ForDefinition_t IsForDefinition, 7397314564Sdim bool Weak, bool DLLImport) { 7398276479Sdim llvm::GlobalValue::LinkageTypes L = 7399276479Sdim Weak ? llvm::GlobalValue::ExternalWeakLinkage 7400276479Sdim : llvm::GlobalValue::ExternalLinkage; 7401276479Sdim 7402193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 7403344779Sdim if (!GV || GV->getType() != ObjCTypes.ClassnfABITy->getPointerTo()) { 7404344779Sdim auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L, 7405344779Sdim nullptr, Name); 7406193326Sed 7407314564Sdim if (DLLImport) 7408344779Sdim NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); 7409344779Sdim 7410344779Sdim if (GV) { 7411344779Sdim GV->replaceAllUsesWith( 7412344779Sdim llvm::ConstantExpr::getBitCast(NewGV, GV->getType())); 7413344779Sdim GV->eraseFromParent(); 7414344779Sdim } 7415344779Sdim GV = NewGV; 7416344779Sdim CGM.getModule().getGlobalList().push_back(GV); 7417314564Sdim } 7418314564Sdim 7419276479Sdim assert(GV->getLinkage() == L); 7420193326Sed return GV; 7421193326Sed} 7422193326Sed 7423353358Sdimllvm::Constant * 7424353358SdimCGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) { 7425353358Sdim llvm::Constant *ClassGV = GetClassGlobal(ID, /*metaclass*/ false, 7426353358Sdim NotForDefinition); 7427353358Sdim 7428353358Sdim if (!ID->hasAttr<ObjCClassStubAttr>()) 7429353358Sdim return ClassGV; 7430353358Sdim 7431353358Sdim ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy); 7432353358Sdim 7433353358Sdim // Stub classes are pointer-aligned. Classrefs pointing at stub classes 7434353358Sdim // must set the least significant bit set to 1. 7435353358Sdim auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1); 7436353358Sdim return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx); 7437353358Sdim} 7438353358Sdim 7439314564Sdimllvm::Value * 7440353358SdimCGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF, 7441353358Sdim const ObjCInterfaceDecl *ID, 7442353358Sdim llvm::GlobalVariable *Entry) { 7443353358Sdim if (ID && ID->hasAttr<ObjCClassStubAttr>()) { 7444353358Sdim // Classrefs pointing at Objective-C stub classes must be loaded by calling 7445353358Sdim // a special runtime function. 7446353358Sdim return CGF.EmitRuntimeCall( 7447353358Sdim ObjCTypes.getLoadClassrefFn(), Entry, "load_classref_result"); 7448353358Sdim } 7449353358Sdim 7450353358Sdim CharUnits Align = CGF.getPointerAlign(); 7451353358Sdim return CGF.Builder.CreateAlignedLoad(Entry, Align); 7452353358Sdim} 7453353358Sdim 7454353358Sdimllvm::Value * 7455314564SdimCGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, 7456314564Sdim IdentifierInfo *II, 7457314564Sdim const ObjCInterfaceDecl *ID) { 7458224145Sdim llvm::GlobalVariable *&Entry = ClassReferences[II]; 7459341825Sdim 7460193326Sed if (!Entry) { 7461314564Sdim llvm::Constant *ClassGV; 7462314564Sdim if (ID) { 7463353358Sdim ClassGV = GetClassGlobalForClassRef(ID); 7464314564Sdim } else { 7465314564Sdim ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(), 7466314564Sdim NotForDefinition); 7467353358Sdim assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy && 7468353358Sdim "classref was emitted with the wrong type?"); 7469314564Sdim } 7470314564Sdim 7471353358Sdim std::string SectionName = 7472353358Sdim GetSectionName("__objc_classrefs", "regular,no_dead_strip"); 7473353358Sdim Entry = new llvm::GlobalVariable( 7474353358Sdim CGM.getModule(), ClassGV->getType(), false, 7475353358Sdim getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV, 7476353358Sdim "OBJC_CLASSLIST_REFERENCES_$_"); 7477360784Sdim Entry->setAlignment(CGF.getPointerAlign().getAsAlign()); 7478353358Sdim if (!ID || !ID->hasAttr<ObjCClassStubAttr>()) 7479353358Sdim Entry->setSection(SectionName); 7480353358Sdim 7481276479Sdim CGM.addCompilerUsedGlobal(Entry); 7482193326Sed } 7483353358Sdim 7484353358Sdim return EmitLoadOfClassRef(CGF, ID, Entry); 7485193326Sed} 7486193326Sed 7487249423Sdimllvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF, 7488224145Sdim const ObjCInterfaceDecl *ID) { 7489309124Sdim // If the class has the objc_runtime_visible attribute, we need to 7490309124Sdim // use the Objective-C runtime to get the class. 7491309124Sdim if (ID->hasAttr<ObjCRuntimeVisibleAttr>()) 7492309124Sdim return EmitClassRefViaRuntime(CGF, ID, ObjCTypes); 7493309124Sdim 7494314564Sdim return EmitClassRefFromId(CGF, ID->getIdentifier(), ID); 7495224145Sdim} 7496224145Sdim 7497224145Sdimllvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef( 7498249423Sdim CodeGenFunction &CGF) { 7499224145Sdim IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool"); 7500314564Sdim return EmitClassRefFromId(CGF, II, nullptr); 7501224145Sdim} 7502224145Sdim 7503193326Sedllvm::Value * 7504249423SdimCGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF, 7505193326Sed const ObjCInterfaceDecl *ID) { 7506193326Sed llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()]; 7507198092Srdivacky 7508193326Sed if (!Entry) { 7509353358Sdim llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID); 7510353358Sdim std::string SectionName = 7511353358Sdim GetSectionName("__objc_superrefs", "regular,no_dead_strip"); 7512353358Sdim Entry = new llvm::GlobalVariable( 7513353358Sdim CGM.getModule(), ClassGV->getType(), false, 7514353358Sdim getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV, 7515353358Sdim "OBJC_CLASSLIST_SUP_REFS_$_"); 7516360784Sdim Entry->setAlignment(CGF.getPointerAlign().getAsAlign()); 7517353358Sdim Entry->setSection(SectionName); 7518276479Sdim CGM.addCompilerUsedGlobal(Entry); 7519193326Sed } 7520353358Sdim 7521353358Sdim return EmitLoadOfClassRef(CGF, ID, Entry); 7522193326Sed} 7523193326Sed 7524193326Sed/// EmitMetaClassRef - Return a Value * of the address of _class_t 7525193326Sed/// meta-data 7526193326Sed/// 7527249423Sdimllvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF, 7528276479Sdim const ObjCInterfaceDecl *ID, 7529276479Sdim bool Weak) { 7530296417Sdim CharUnits Align = CGF.getPointerAlign(); 7531193326Sed llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; 7532276479Sdim if (!Entry) { 7533314564Sdim auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition); 7534353358Sdim std::string SectionName = 7535353358Sdim GetSectionName("__objc_superrefs", "regular,no_dead_strip"); 7536353358Sdim Entry = new llvm::GlobalVariable( 7537353358Sdim CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false, 7538353358Sdim getLinkageTypeForObjCMetadata(CGM, SectionName), MetaClassGV, 7539353358Sdim "OBJC_CLASSLIST_SUP_REFS_$_"); 7540360784Sdim Entry->setAlignment(Align.getAsAlign()); 7541353358Sdim Entry->setSection(SectionName); 7542276479Sdim CGM.addCompilerUsedGlobal(Entry); 7543276479Sdim } 7544198092Srdivacky 7545296417Sdim return CGF.Builder.CreateAlignedLoad(Entry, Align); 7546193326Sed} 7547193326Sed 7548193326Sed/// GetClass - Return a reference to the class for the given interface 7549193326Sed/// decl. 7550249423Sdimllvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF, 7551193326Sed const ObjCInterfaceDecl *ID) { 7552221345Sdim if (ID->isWeakImported()) { 7553314564Sdim auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition); 7554276479Sdim (void)ClassGV; 7555314564Sdim assert(!isa<llvm::GlobalVariable>(ClassGV) || 7556314564Sdim cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage()); 7557199482Srdivacky } 7558341825Sdim 7559249423Sdim return EmitClassRef(CGF, ID); 7560193326Sed} 7561193326Sed 7562193326Sed/// Generates a message send where the super is the receiver. This is 7563193326Sed/// a message send to self with special delivery semantics indicating 7564193326Sed/// which class's method should be called. 7565193326SedCodeGen::RValue 7566193326SedCGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 7567208600Srdivacky ReturnValueSlot Return, 7568198092Srdivacky QualType ResultType, 7569198092Srdivacky Selector Sel, 7570198092Srdivacky const ObjCInterfaceDecl *Class, 7571198092Srdivacky bool isCategoryImpl, 7572198092Srdivacky llvm::Value *Receiver, 7573198092Srdivacky bool IsClassMessage, 7574198092Srdivacky const CodeGen::CallArgList &CallArgs, 7575198092Srdivacky const ObjCMethodDecl *Method) { 7576193326Sed // ... 7577193326Sed // Create and init a super structure; this is a (receiver, class) 7578193326Sed // pair we will pass to objc_msgSendSuper. 7579296417Sdim Address ObjCSuper = 7580296417Sdim CGF.CreateTempAlloca(ObjCTypes.SuperTy, CGF.getPointerAlign(), 7581296417Sdim "objc_super"); 7582198092Srdivacky 7583193326Sed llvm::Value *ReceiverAsObject = 7584193326Sed CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); 7585353358Sdim CGF.Builder.CreateStore(ReceiverAsObject, 7586353358Sdim CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 7587198092Srdivacky 7588193326Sed // If this is a class message the metaclass is passed as the target. 7589193326Sed llvm::Value *Target; 7590243830Sdim if (IsClassMessage) 7591280031Sdim Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported()); 7592243830Sdim else 7593249423Sdim Target = EmitSuperClassRef(CGF, Class); 7594198092Srdivacky 7595193326Sed // FIXME: We shouldn't need to do this cast, rectify the ASTContext and 7596193326Sed // ObjCTypes types. 7597226633Sdim llvm::Type *ClassTy = 7598193326Sed CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); 7599193326Sed Target = CGF.Builder.CreateBitCast(Target, ClassTy); 7600353358Sdim CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 7601198092Srdivacky 7602223017Sdim return (isVTableDispatchedSelector(Sel)) 7603223017Sdim ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, 7604296417Sdim ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy, 7605223017Sdim true, CallArgs, Method) 7606360784Sdim : EmitMessageSend(CGF, Return, ResultType, Sel, 7607296417Sdim ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy, 7608296417Sdim true, CallArgs, Method, Class, ObjCTypes); 7609193326Sed} 7610193326Sed 7611249423Sdimllvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF, 7612296417Sdim Selector Sel) { 7613360784Sdim Address Addr = EmitSelectorAddr(Sel); 7614296417Sdim 7615296417Sdim llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr); 7616341825Sdim LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"), 7617296417Sdim llvm::MDNode::get(VMContext, None)); 7618296417Sdim return LI; 7619296417Sdim} 7620296417Sdim 7621360784SdimAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { 7622193326Sed llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; 7623360784Sdim CharUnits Align = CGM.getPointerAlign(); 7624193326Sed if (!Entry) { 7625198092Srdivacky llvm::Constant *Casted = 7626198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), 7627198092Srdivacky ObjCTypes.SelectorPtrTy); 7628353358Sdim std::string SectionName = 7629353358Sdim GetSectionName("__objc_selrefs", "literal_pointers,no_dead_strip"); 7630353358Sdim Entry = new llvm::GlobalVariable( 7631353358Sdim CGM.getModule(), ObjCTypes.SelectorPtrTy, false, 7632353358Sdim getLinkageTypeForObjCMetadata(CGM, SectionName), Casted, 7633353358Sdim "OBJC_SELECTOR_REFERENCES_"); 7634249423Sdim Entry->setExternallyInitialized(true); 7635353358Sdim Entry->setSection(SectionName); 7636360784Sdim Entry->setAlignment(Align.getAsAlign()); 7637276479Sdim CGM.addCompilerUsedGlobal(Entry); 7638193326Sed } 7639198092Srdivacky 7640296417Sdim return Address(Entry, Align); 7641193326Sed} 7642296417Sdim 7643193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. 7644198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t) 7645193326Sed/// 7646193326Sedvoid CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 7647198092Srdivacky llvm::Value *src, 7648296417Sdim Address dst, 7649198092Srdivacky llvm::Value *ivarOffset) { 7650226633Sdim llvm::Type * SrcTy = src->getType(); 7651193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 7652243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 7653193326Sed assert(Size <= 8 && "does not support size > 8"); 7654193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 7655193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 7656193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 7657193326Sed } 7658193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 7659193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 7660296417Sdim llvm::Value *args[] = { src, dst.getPointer(), ivarOffset }; 7661249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); 7662193326Sed} 7663193326Sed 7664193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. 7665193326Sed/// objc_assign_strongCast (id src, id *dst) 7666193326Sed/// 7667193326Sedvoid CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( 7668198092Srdivacky CodeGen::CodeGenFunction &CGF, 7669296417Sdim llvm::Value *src, Address dst) { 7670226633Sdim llvm::Type * SrcTy = src->getType(); 7671193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 7672243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 7673193326Sed assert(Size <= 8 && "does not support size > 8"); 7674193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 7675198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 7676193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 7677193326Sed } 7678193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 7679193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 7680296417Sdim llvm::Value *args[] = { src, dst.getPointer() }; 7681249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), 7682249423Sdim args, "weakassign"); 7683193326Sed} 7684193326Sed 7685198092Srdivackyvoid CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( 7686198092Srdivacky CodeGen::CodeGenFunction &CGF, 7687296417Sdim Address DestPtr, 7688296417Sdim Address SrcPtr, 7689210299Sed llvm::Value *Size) { 7690198092Srdivacky SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); 7691198092Srdivacky DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); 7692296417Sdim llvm::Value *args[] = { DestPtr.getPointer(), SrcPtr.getPointer(), Size }; 7693249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); 7694198092Srdivacky} 7695198092Srdivacky 7696193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak 7697193326Sed/// object: objc_read_weak (id *src) 7698193326Sed/// 7699193326Sedllvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( 7700198092Srdivacky CodeGen::CodeGenFunction &CGF, 7701296417Sdim Address AddrWeakObj) { 7702296417Sdim llvm::Type *DestTy = AddrWeakObj.getElementType(); 7703198092Srdivacky AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy); 7704249423Sdim llvm::Value *read_weak = 7705249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), 7706296417Sdim AddrWeakObj.getPointer(), "weakread"); 7707193326Sed read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); 7708193326Sed return read_weak; 7709193326Sed} 7710193326Sed 7711193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. 7712193326Sed/// objc_assign_weak (id src, id *dst) 7713193326Sed/// 7714193326Sedvoid CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 7715296417Sdim llvm::Value *src, Address dst) { 7716226633Sdim llvm::Type * SrcTy = src->getType(); 7717193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 7718243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 7719193326Sed assert(Size <= 8 && "does not support size > 8"); 7720193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 7721193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 7722193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 7723193326Sed } 7724193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 7725193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 7726296417Sdim llvm::Value *args[] = { src, dst.getPointer() }; 7727249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), 7728249423Sdim args, "weakassign"); 7729193326Sed} 7730193326Sed 7731193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. 7732193326Sed/// objc_assign_global (id src, id *dst) 7733193326Sed/// 7734193326Sedvoid CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 7735296417Sdim llvm::Value *src, Address dst, 7736212904Sdim bool threadlocal) { 7737226633Sdim llvm::Type * SrcTy = src->getType(); 7738193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 7739243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 7740193326Sed assert(Size <= 8 && "does not support size > 8"); 7741193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 7742193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 7743193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 7744193326Sed } 7745193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 7746193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 7747296417Sdim llvm::Value *args[] = { src, dst.getPointer() }; 7748212904Sdim if (!threadlocal) 7749249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), 7750249423Sdim args, "globalassign"); 7751212904Sdim else 7752249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), 7753249423Sdim args, "threadlocalassign"); 7754193326Sed} 7755193326Sed 7756198092Srdivackyvoid 7757210299SedCGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 7758210299Sed const ObjCAtSynchronizedStmt &S) { 7759353358Sdim EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(), 7760353358Sdim ObjCTypes.getSyncExitFn()); 7761210299Sed} 7762193326Sed 7763212904Sdimllvm::Constant * 7764212904SdimCGObjCNonFragileABIMac::GetEHType(QualType T) { 7765212904Sdim // There's a particular fixed type info for 'id'. 7766309124Sdim if (T->isObjCIdType() || T->isObjCQualifiedIdType()) { 7767309124Sdim auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id"); 7768309124Sdim if (!IDEHType) { 7769212904Sdim IDEHType = 7770309124Sdim new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, 7771309124Sdim llvm::GlobalValue::ExternalLinkage, nullptr, 7772309124Sdim "OBJC_EHTYPE_id"); 7773309124Sdim if (CGM.getTriple().isOSBinFormatCOFF()) 7774309124Sdim IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id")); 7775309124Sdim } 7776212904Sdim return IDEHType; 7777212904Sdim } 7778212904Sdim 7779212904Sdim // All other types should be Objective-C interface pointer types. 7780309124Sdim const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>(); 7781212904Sdim assert(PT && "Invalid @catch type."); 7782309124Sdim 7783212904Sdim const ObjCInterfaceType *IT = PT->getInterfaceType(); 7784212904Sdim assert(IT && "Invalid @catch type."); 7785309124Sdim 7786314564Sdim return GetInterfaceEHType(IT->getDecl(), NotForDefinition); 7787309124Sdim} 7788212904Sdim 7789210299Sedvoid CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF, 7790210299Sed const ObjCAtTryStmt &S) { 7791353358Sdim EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(), 7792353358Sdim ObjCTypes.getObjCEndCatchFn(), 7793353358Sdim ObjCTypes.getExceptionRethrowFn()); 7794193326Sed} 7795193326Sed 7796193326Sed/// EmitThrowStmt - Generate code for a throw statement. 7797193326Sedvoid CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 7798249423Sdim const ObjCAtThrowStmt &S, 7799249423Sdim bool ClearInsertionPoint) { 7800193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 7801226633Sdim llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr); 7802226633Sdim Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy); 7803353358Sdim llvm::CallBase *Call = 7804353358Sdim CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception); 7805353358Sdim Call->setDoesNotReturn(); 7806193326Sed } else { 7807353358Sdim llvm::CallBase *Call = 7808353358Sdim CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn()); 7809353358Sdim Call->setDoesNotReturn(); 7810193326Sed } 7811193326Sed 7812218893Sdim CGF.Builder.CreateUnreachable(); 7813249423Sdim if (ClearInsertionPoint) 7814249423Sdim CGF.Builder.ClearInsertionPoint(); 7815193326Sed} 7816193326Sed 7817212904Sdimllvm::Constant * 7818198092SrdivackyCGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, 7819314564Sdim ForDefinition_t IsForDefinition) { 7820193326Sed llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()]; 7821309124Sdim StringRef ClassName = ID->getObjCRuntimeNameAsString(); 7822193326Sed 7823193326Sed // If we don't need a definition, return the entry if found or check 7824193326Sed // if we use an external reference. 7825314564Sdim if (!IsForDefinition) { 7826193326Sed if (Entry) 7827193326Sed return Entry; 7828193326Sed 7829193326Sed // If this type (or a super class) has the __objc_exception__ 7830193326Sed // attribute, emit an external reference. 7831309124Sdim if (hasObjCExceptionAttribute(CGM.getContext(), ID)) { 7832309124Sdim std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str(); 7833309124Sdim Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, 7834309124Sdim false, llvm::GlobalValue::ExternalLinkage, 7835309124Sdim nullptr, EHTypeName); 7836341825Sdim CGM.setGVProperties(Entry, ID); 7837309124Sdim return Entry; 7838309124Sdim } 7839193326Sed } 7840198092Srdivacky 7841309124Sdim // Otherwise we need to either make a new entry or fill in the initializer. 7842193326Sed assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition"); 7843309124Sdim 7844193326Sed std::string VTableName = "objc_ehtype_vtable"; 7845309124Sdim auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName); 7846309124Sdim if (!VTableGV) { 7847309124Sdim VTableGV = 7848309124Sdim new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false, 7849309124Sdim llvm::GlobalValue::ExternalLinkage, nullptr, 7850309124Sdim VTableName); 7851309124Sdim if (CGM.getTriple().isOSBinFormatCOFF()) 7852309124Sdim VTableGV->setDLLStorageClass(getStorage(CGM, VTableName)); 7853309124Sdim } 7854193326Sed 7855234353Sdim llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2); 7856314564Sdim ConstantInitBuilder builder(CGM); 7857314564Sdim auto values = builder.beginStruct(ObjCTypes.EHTypeTy); 7858327952Sdim values.add( 7859327952Sdim llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(), 7860327952Sdim VTableGV, VTableIdx)); 7861314564Sdim values.add(GetClassName(ClassName)); 7862314564Sdim values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition)); 7863193326Sed 7864314564Sdim llvm::GlobalValue::LinkageTypes L = IsForDefinition 7865276479Sdim ? llvm::GlobalValue::ExternalLinkage 7866276479Sdim : llvm::GlobalValue::WeakAnyLinkage; 7867193326Sed if (Entry) { 7868314564Sdim values.finishAndSetAsInitializer(Entry); 7869360784Sdim Entry->setAlignment(CGM.getPointerAlign().getAsAlign()); 7870193326Sed } else { 7871314564Sdim Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName, 7872314564Sdim CGM.getPointerAlign(), 7873314564Sdim /*constant*/ false, 7874314564Sdim L); 7875341825Sdim if (hasObjCExceptionAttribute(CGM.getContext(), ID)) 7876341825Sdim CGM.setGVProperties(Entry, ID); 7877193326Sed } 7878276479Sdim assert(Entry->getLinkage() == L); 7879193326Sed 7880309124Sdim if (!CGM.getTriple().isOSBinFormatCOFF()) 7881309124Sdim if (ID->getVisibility() == HiddenVisibility) 7882309124Sdim Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); 7883193326Sed 7884314564Sdim if (IsForDefinition) 7885314564Sdim if (CGM.getTriple().isOSBinFormatMachO()) 7886314564Sdim Entry->setSection("__DATA,__objc_const"); 7887309124Sdim 7888193326Sed return Entry; 7889193326Sed} 7890198092Srdivacky 7891193326Sed/* *** */ 7892193326Sed 7893193326SedCodeGen::CGObjCRuntime * 7894193326SedCodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) { 7895239462Sdim switch (CGM.getLangOpts().ObjCRuntime.getKind()) { 7896239462Sdim case ObjCRuntime::FragileMacOSX: 7897239462Sdim return new CGObjCMac(CGM); 7898239462Sdim 7899239462Sdim case ObjCRuntime::MacOSX: 7900239462Sdim case ObjCRuntime::iOS: 7901296417Sdim case ObjCRuntime::WatchOS: 7902221345Sdim return new CGObjCNonFragileABIMac(CGM); 7903239462Sdim 7904239462Sdim case ObjCRuntime::GNUstep: 7905239462Sdim case ObjCRuntime::GCC: 7906239462Sdim case ObjCRuntime::ObjFW: 7907239462Sdim llvm_unreachable("these runtimes are not Mac runtimes"); 7908239462Sdim } 7909239462Sdim llvm_unreachable("bad runtime"); 7910193326Sed} 7911