1193326Sed//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10221345Sdim// This provides Objective-C code generation targeting the Apple runtime. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14193326Sed#include "CGObjCRuntime.h" 15249423Sdim#include "CGBlocks.h" 16249423Sdim#include "CGCleanup.h" 17206084Srdivacky#include "CGRecordLayout.h" 18249423Sdim#include "CodeGenFunction.h" 19193326Sed#include "CodeGenModule.h" 20193326Sed#include "clang/AST/ASTContext.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" 25193326Sed#include "clang/Basic/LangOptions.h" 26263508Sdim#include "clang/CodeGen/CGFunctionInfo.h" 27210299Sed#include "clang/Frontend/CodeGenOptions.h" 28193326Sed#include "llvm/ADT/DenseSet.h" 29198092Srdivacky#include "llvm/ADT/SetVector.h" 30249423Sdim#include "llvm/ADT/SmallPtrSet.h" 31198092Srdivacky#include "llvm/ADT/SmallString.h" 32249423Sdim#include "llvm/IR/DataLayout.h" 33249423Sdim#include "llvm/IR/InlineAsm.h" 34249423Sdim#include "llvm/IR/IntrinsicInst.h" 35249423Sdim#include "llvm/IR/LLVMContext.h" 36249423Sdim#include "llvm/IR/Module.h" 37210299Sed#include "llvm/Support/CallSite.h" 38198092Srdivacky#include "llvm/Support/raw_ostream.h" 39198092Srdivacky#include <cstdio> 40193326Sed 41193326Sedusing namespace clang; 42193326Sedusing namespace CodeGen; 43193326Sed 44193326Sednamespace { 45193326Sed 46198092Srdivacky// FIXME: We should find a nicer way to make the labels for metadata, string 47198092Srdivacky// concatenation is lame. 48193326Sed 49193326Sedclass ObjCCommonTypesHelper { 50198092Srdivackyprotected: 51198092Srdivacky llvm::LLVMContext &VMContext; 52198092Srdivacky 53193326Sedprivate: 54223017Sdim // The types of these functions don't really matter because we 55223017Sdim // should always bitcast before calling them. 56223017Sdim 57223017Sdim /// id objc_msgSend (id, SEL, ...) 58223017Sdim /// 59223017Sdim /// The default messenger, used for sends whose ABI is unchanged from 60223017Sdim /// the all-integer/pointer case. 61193326Sed llvm::Constant *getMessageSendFn() const { 62224145Sdim // Add the non-lazy-bind attribute, since objc_msgSend is likely to 63224145Sdim // be called a lot. 64224145Sdim llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; 65249423Sdim return 66249423Sdim CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 67249423Sdim params, true), 68249423Sdim "objc_msgSend", 69249423Sdim llvm::AttributeSet::get(CGM.getLLVMContext(), 70249423Sdim llvm::AttributeSet::FunctionIndex, 71249423Sdim 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. 79193326Sed llvm::Constant *getMessageSendStretFn() const { 80224145Sdim llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; 81223017Sdim return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, 82223017Sdim params, true), 83223017Sdim "objc_msgSend_stret"); 84198092Srdivacky 85193326Sed } 86198092Srdivacky 87223017Sdim /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...) 88223017Sdim /// 89223017Sdim /// The messenger used when the return value is returned on the x87 90223017Sdim /// floating-point stack; without a special entrypoint, the nil case 91223017Sdim /// would be unbalanced. 92193326Sed llvm::Constant *getMessageSendFpretFn() const { 93224145Sdim llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; 94234353Sdim return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy, 95234353Sdim params, true), 96223017Sdim "objc_msgSend_fpret"); 97198092Srdivacky 98193326Sed } 99198092Srdivacky 100234353Sdim /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...) 101234353Sdim /// 102234353Sdim /// The messenger used when the return value is returned in two values on the 103234353Sdim /// x87 floating point stack; without a special entrypoint, the nil case 104234353Sdim /// would be unbalanced. Only used on 64-bit X86. 105234353Sdim llvm::Constant *getMessageSendFp2retFn() const { 106234353Sdim llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; 107234353Sdim llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext); 108234353Sdim llvm::Type *resultType = 109234353Sdim llvm::StructType::get(longDoubleType, longDoubleType, NULL); 110234353Sdim 111234353Sdim return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType, 112234353Sdim params, true), 113234353Sdim "objc_msgSend_fp2ret"); 114234353Sdim } 115234353Sdim 116223017Sdim /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...) 117223017Sdim /// 118223017Sdim /// The messenger used for super calls, which have different dispatch 119223017Sdim /// semantics. The class passed is the superclass of the current 120223017Sdim /// class. 121193326Sed llvm::Constant *getMessageSendSuperFn() const { 122224145Sdim llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy }; 123193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 124223017Sdim params, true), 125223017Sdim "objc_msgSendSuper"); 126193326Sed } 127198092Srdivacky 128223017Sdim /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...) 129223017Sdim /// 130223017Sdim /// A slightly different messenger used for super calls. The class 131223017Sdim /// passed is the current class. 132193326Sed llvm::Constant *getMessageSendSuperFn2() const { 133224145Sdim llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy }; 134193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 135223017Sdim params, true), 136223017Sdim "objc_msgSendSuper2"); 137193326Sed } 138198092Srdivacky 139223017Sdim /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super, 140223017Sdim /// SEL op, ...) 141223017Sdim /// 142223017Sdim /// The messenger used for super calls which return an aggregate indirectly. 143193326Sed llvm::Constant *getMessageSendSuperStretFn() const { 144224145Sdim llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy }; 145198092Srdivacky return CGM.CreateRuntimeFunction( 146223017Sdim llvm::FunctionType::get(CGM.VoidTy, params, true), 147198092Srdivacky "objc_msgSendSuper_stret"); 148193326Sed } 149198092Srdivacky 150223017Sdim /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super, 151223017Sdim /// SEL op, ...) 152223017Sdim /// 153223017Sdim /// objc_msgSendSuper_stret with the super2 semantics. 154193326Sed llvm::Constant *getMessageSendSuperStretFn2() const { 155224145Sdim llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy }; 156198092Srdivacky return CGM.CreateRuntimeFunction( 157223017Sdim llvm::FunctionType::get(CGM.VoidTy, params, true), 158198092Srdivacky "objc_msgSendSuper2_stret"); 159193326Sed } 160198092Srdivacky 161193326Sed llvm::Constant *getMessageSendSuperFpretFn() const { 162193326Sed // There is no objc_msgSendSuper_fpret? How can that work? 163193326Sed return getMessageSendSuperFn(); 164193326Sed } 165198092Srdivacky 166193326Sed llvm::Constant *getMessageSendSuperFpretFn2() const { 167193326Sed // There is no objc_msgSendSuper_fpret? How can that work? 168193326Sed return getMessageSendSuperFn2(); 169193326Sed } 170198092Srdivacky 171193326Sedprotected: 172193326Sed CodeGen::CodeGenModule &CGM; 173198092Srdivacky 174193326Sedpublic: 175224145Sdim llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy; 176234353Sdim llvm::Type *Int8PtrTy, *Int8PtrPtrTy; 177198092Srdivacky 178193326Sed /// ObjectPtrTy - LLVM type for object handles (typeof(id)) 179224145Sdim llvm::Type *ObjectPtrTy; 180198092Srdivacky 181193326Sed /// PtrObjectPtrTy - LLVM type for id * 182224145Sdim llvm::Type *PtrObjectPtrTy; 183198092Srdivacky 184193326Sed /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL)) 185224145Sdim llvm::Type *SelectorPtrTy; 186234353Sdim 187234353Sdimprivate: 188193326Sed /// ProtocolPtrTy - LLVM type for external protocol handles 189193326Sed /// (typeof(Protocol)) 190224145Sdim llvm::Type *ExternalProtocolPtrTy; 191234353Sdim 192234353Sdimpublic: 193234353Sdim llvm::Type *getExternalProtocolPtrTy() { 194234353Sdim if (!ExternalProtocolPtrTy) { 195234353Sdim // FIXME: It would be nice to unify this with the opaque type, so that the 196234353Sdim // IR comes out a bit cleaner. 197234353Sdim CodeGen::CodeGenTypes &Types = CGM.getTypes(); 198234353Sdim ASTContext &Ctx = CGM.getContext(); 199234353Sdim llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType()); 200234353Sdim ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T); 201234353Sdim } 202234353Sdim 203234353Sdim return ExternalProtocolPtrTy; 204234353Sdim } 205234353Sdim 206193326Sed // SuperCTy - clang type for struct objc_super. 207193326Sed QualType SuperCTy; 208193326Sed // SuperPtrCTy - clang type for struct objc_super *. 209193326Sed QualType SuperPtrCTy; 210198092Srdivacky 211193326Sed /// SuperTy - LLVM type for struct objc_super. 212224145Sdim llvm::StructType *SuperTy; 213193326Sed /// SuperPtrTy - LLVM type for struct objc_super *. 214224145Sdim llvm::Type *SuperPtrTy; 215198092Srdivacky 216193326Sed /// PropertyTy - LLVM type for struct objc_property (struct _prop_t 217193326Sed /// in GCC parlance). 218224145Sdim llvm::StructType *PropertyTy; 219198092Srdivacky 220193326Sed /// PropertyListTy - LLVM type for struct objc_property_list 221193326Sed /// (_prop_list_t in GCC parlance). 222224145Sdim llvm::StructType *PropertyListTy; 223193326Sed /// PropertyListPtrTy - LLVM type for struct objc_property_list*. 224224145Sdim llvm::Type *PropertyListPtrTy; 225198092Srdivacky 226193326Sed // MethodTy - LLVM type for struct objc_method. 227224145Sdim llvm::StructType *MethodTy; 228198092Srdivacky 229193326Sed /// CacheTy - LLVM type for struct objc_cache. 230224145Sdim llvm::Type *CacheTy; 231193326Sed /// CachePtrTy - LLVM type for struct objc_cache *. 232224145Sdim llvm::Type *CachePtrTy; 233224145Sdim 234193326Sed llvm::Constant *getGetPropertyFn() { 235193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 236193326Sed ASTContext &Ctx = CGM.getContext(); 237193326Sed // id objc_getProperty (id, SEL, ptrdiff_t, bool) 238226633Sdim SmallVector<CanQualType,4> Params; 239204643Srdivacky CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); 240204643Srdivacky CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); 241193326Sed Params.push_back(IdType); 242193326Sed Params.push_back(SelType); 243221345Sdim Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified()); 244193326Sed Params.push_back(Ctx.BoolTy); 245226633Sdim llvm::FunctionType *FTy = 246239462Sdim Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(IdType, Params, 247239462Sdim FunctionType::ExtInfo(), 248239462Sdim RequiredArgs::All)); 249193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_getProperty"); 250193326Sed } 251198092Srdivacky 252193326Sed llvm::Constant *getSetPropertyFn() { 253193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 254193326Sed ASTContext &Ctx = CGM.getContext(); 255193326Sed // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) 256226633Sdim SmallVector<CanQualType,6> Params; 257204643Srdivacky CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); 258204643Srdivacky CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); 259193326Sed Params.push_back(IdType); 260193326Sed Params.push_back(SelType); 261221345Sdim Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified()); 262193326Sed Params.push_back(IdType); 263193326Sed Params.push_back(Ctx.BoolTy); 264193326Sed Params.push_back(Ctx.BoolTy); 265226633Sdim llvm::FunctionType *FTy = 266239462Sdim Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params, 267239462Sdim FunctionType::ExtInfo(), 268239462Sdim RequiredArgs::All)); 269193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_setProperty"); 270193326Sed } 271198092Srdivacky 272234353Sdim llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) { 273234353Sdim CodeGen::CodeGenTypes &Types = CGM.getTypes(); 274234353Sdim ASTContext &Ctx = CGM.getContext(); 275234353Sdim // void objc_setProperty_atomic(id self, SEL _cmd, 276234353Sdim // id newValue, ptrdiff_t offset); 277234353Sdim // void objc_setProperty_nonatomic(id self, SEL _cmd, 278234353Sdim // id newValue, ptrdiff_t offset); 279234353Sdim // void objc_setProperty_atomic_copy(id self, SEL _cmd, 280234353Sdim // id newValue, ptrdiff_t offset); 281234353Sdim // void objc_setProperty_nonatomic_copy(id self, SEL _cmd, 282234353Sdim // id newValue, ptrdiff_t offset); 283234353Sdim 284234353Sdim SmallVector<CanQualType,4> Params; 285234353Sdim CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); 286234353Sdim CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); 287234353Sdim Params.push_back(IdType); 288234353Sdim Params.push_back(SelType); 289234353Sdim Params.push_back(IdType); 290234353Sdim Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified()); 291234353Sdim llvm::FunctionType *FTy = 292239462Sdim Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params, 293239462Sdim FunctionType::ExtInfo(), 294239462Sdim RequiredArgs::All)); 295234353Sdim const char *name; 296234353Sdim if (atomic && copy) 297234353Sdim name = "objc_setProperty_atomic_copy"; 298234353Sdim else if (atomic && !copy) 299234353Sdim name = "objc_setProperty_atomic"; 300234353Sdim else if (!atomic && copy) 301234353Sdim name = "objc_setProperty_nonatomic_copy"; 302234353Sdim else 303234353Sdim name = "objc_setProperty_nonatomic"; 304234353Sdim 305234353Sdim return CGM.CreateRuntimeFunction(FTy, name); 306234353Sdim } 307207619Srdivacky 308207619Srdivacky llvm::Constant *getCopyStructFn() { 309207619Srdivacky CodeGen::CodeGenTypes &Types = CGM.getTypes(); 310207619Srdivacky ASTContext &Ctx = CGM.getContext(); 311207619Srdivacky // void objc_copyStruct (void *, const void *, size_t, bool, bool) 312226633Sdim SmallVector<CanQualType,5> Params; 313207619Srdivacky Params.push_back(Ctx.VoidPtrTy); 314207619Srdivacky Params.push_back(Ctx.VoidPtrTy); 315207619Srdivacky Params.push_back(Ctx.LongTy); 316207619Srdivacky Params.push_back(Ctx.BoolTy); 317207619Srdivacky Params.push_back(Ctx.BoolTy); 318226633Sdim llvm::FunctionType *FTy = 319239462Sdim Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params, 320239462Sdim FunctionType::ExtInfo(), 321239462Sdim RequiredArgs::All)); 322207619Srdivacky return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct"); 323207619Srdivacky } 324207619Srdivacky 325234353Sdim /// This routine declares and returns address of: 326234353Sdim /// void objc_copyCppObjectAtomic( 327234353Sdim /// void *dest, const void *src, 328234353Sdim /// void (*copyHelper) (void *dest, const void *source)); 329234353Sdim llvm::Constant *getCppAtomicObjectFunction() { 330234353Sdim CodeGen::CodeGenTypes &Types = CGM.getTypes(); 331234353Sdim ASTContext &Ctx = CGM.getContext(); 332234353Sdim /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper); 333234353Sdim SmallVector<CanQualType,3> Params; 334234353Sdim Params.push_back(Ctx.VoidPtrTy); 335234353Sdim Params.push_back(Ctx.VoidPtrTy); 336234353Sdim Params.push_back(Ctx.VoidPtrTy); 337234353Sdim llvm::FunctionType *FTy = 338239462Sdim Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params, 339239462Sdim FunctionType::ExtInfo(), 340239462Sdim RequiredArgs::All)); 341234353Sdim return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic"); 342234353Sdim } 343234353Sdim 344193326Sed llvm::Constant *getEnumerationMutationFn() { 345198092Srdivacky CodeGen::CodeGenTypes &Types = CGM.getTypes(); 346198092Srdivacky ASTContext &Ctx = CGM.getContext(); 347193326Sed // void objc_enumerationMutation (id) 348226633Sdim SmallVector<CanQualType,1> Params; 349204643Srdivacky Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType())); 350226633Sdim llvm::FunctionType *FTy = 351239462Sdim Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params, 352234353Sdim FunctionType::ExtInfo(), 353234353Sdim RequiredArgs::All)); 354193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); 355193326Sed } 356198092Srdivacky 357193326Sed /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function. 358193326Sed llvm::Constant *getGcReadWeakFn() { 359193326Sed // id objc_read_weak (id *) 360224145Sdim llvm::Type *args[] = { ObjectPtrTy->getPointerTo() }; 361198092Srdivacky llvm::FunctionType *FTy = 362223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 363193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); 364198092Srdivacky } 365198092Srdivacky 366193326Sed /// GcAssignWeakFn -- LLVM objc_assign_weak function. 367193326Sed llvm::Constant *getGcAssignWeakFn() { 368193326Sed // id objc_assign_weak (id, id *) 369224145Sdim llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; 370193326Sed llvm::FunctionType *FTy = 371223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 372193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); 373193326Sed } 374198092Srdivacky 375193326Sed /// GcAssignGlobalFn -- LLVM objc_assign_global function. 376193326Sed llvm::Constant *getGcAssignGlobalFn() { 377193326Sed // id objc_assign_global(id, id *) 378224145Sdim llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; 379198092Srdivacky llvm::FunctionType *FTy = 380223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 381193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); 382193326Sed } 383198092Srdivacky 384212904Sdim /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function. 385212904Sdim llvm::Constant *getGcAssignThreadLocalFn() { 386212904Sdim // id objc_assign_threadlocal(id src, id * dest) 387224145Sdim llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; 388212904Sdim llvm::FunctionType *FTy = 389223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 390212904Sdim return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal"); 391212904Sdim } 392212904Sdim 393193326Sed /// GcAssignIvarFn -- LLVM objc_assign_ivar function. 394193326Sed llvm::Constant *getGcAssignIvarFn() { 395198092Srdivacky // id objc_assign_ivar(id, id *, ptrdiff_t) 396224145Sdim llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(), 397224145Sdim CGM.PtrDiffTy }; 398198092Srdivacky llvm::FunctionType *FTy = 399223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 400193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); 401193326Sed } 402198092Srdivacky 403198092Srdivacky /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function. 404198092Srdivacky llvm::Constant *GcMemmoveCollectableFn() { 405198092Srdivacky // void *objc_memmove_collectable(void *dst, const void *src, size_t size) 406224145Sdim llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy }; 407223017Sdim llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false); 408198092Srdivacky return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); 409198092Srdivacky } 410198092Srdivacky 411193326Sed /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function. 412193326Sed llvm::Constant *getGcAssignStrongCastFn() { 413212904Sdim // id objc_assign_strongCast(id, id *) 414224145Sdim llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() }; 415198092Srdivacky llvm::FunctionType *FTy = 416223017Sdim llvm::FunctionType::get(ObjectPtrTy, args, false); 417193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); 418193326Sed } 419193326Sed 420193326Sed /// ExceptionThrowFn - LLVM objc_exception_throw function. 421193326Sed llvm::Constant *getExceptionThrowFn() { 422193326Sed // void objc_exception_throw(id) 423224145Sdim llvm::Type *args[] = { ObjectPtrTy }; 424193326Sed llvm::FunctionType *FTy = 425223017Sdim llvm::FunctionType::get(CGM.VoidTy, args, false); 426193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); 427193326Sed } 428198092Srdivacky 429210299Sed /// ExceptionRethrowFn - LLVM objc_exception_rethrow function. 430210299Sed llvm::Constant *getExceptionRethrowFn() { 431210299Sed // void objc_exception_rethrow(void) 432223017Sdim llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false); 433210299Sed return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow"); 434210299Sed } 435210299Sed 436193326Sed /// SyncEnterFn - LLVM object_sync_enter function. 437193326Sed llvm::Constant *getSyncEnterFn() { 438243830Sdim // int objc_sync_enter (id) 439224145Sdim llvm::Type *args[] = { ObjectPtrTy }; 440193326Sed llvm::FunctionType *FTy = 441243830Sdim llvm::FunctionType::get(CGM.IntTy, args, false); 442193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); 443193326Sed } 444198092Srdivacky 445193326Sed /// SyncExitFn - LLVM object_sync_exit function. 446193326Sed llvm::Constant *getSyncExitFn() { 447243830Sdim // int objc_sync_exit (id) 448224145Sdim llvm::Type *args[] = { ObjectPtrTy }; 449193326Sed llvm::FunctionType *FTy = 450243830Sdim llvm::FunctionType::get(CGM.IntTy, args, false); 451193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); 452193326Sed } 453198092Srdivacky 454193326Sed llvm::Constant *getSendFn(bool IsSuper) const { 455193326Sed return IsSuper ? getMessageSendSuperFn() : getMessageSendFn(); 456193326Sed } 457198092Srdivacky 458193326Sed llvm::Constant *getSendFn2(bool IsSuper) const { 459193326Sed return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn(); 460193326Sed } 461198092Srdivacky 462193326Sed llvm::Constant *getSendStretFn(bool IsSuper) const { 463193326Sed return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn(); 464193326Sed } 465198092Srdivacky 466193326Sed llvm::Constant *getSendStretFn2(bool IsSuper) const { 467193326Sed return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn(); 468193326Sed } 469198092Srdivacky 470193326Sed llvm::Constant *getSendFpretFn(bool IsSuper) const { 471193326Sed return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn(); 472193326Sed } 473198092Srdivacky 474193326Sed llvm::Constant *getSendFpretFn2(bool IsSuper) const { 475193326Sed return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn(); 476193326Sed } 477198092Srdivacky 478234353Sdim llvm::Constant *getSendFp2retFn(bool IsSuper) const { 479234353Sdim return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn(); 480234353Sdim } 481234353Sdim 482234353Sdim llvm::Constant *getSendFp2RetFn2(bool IsSuper) const { 483234353Sdim return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn(); 484234353Sdim } 485234353Sdim 486193326Sed ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm); 487193326Sed ~ObjCCommonTypesHelper(){} 488193326Sed}; 489193326Sed 490193326Sed/// ObjCTypesHelper - Helper class that encapsulates lazy 491193326Sed/// construction of varies types used during ObjC generation. 492193326Sedclass ObjCTypesHelper : public ObjCCommonTypesHelper { 493193326Sedpublic: 494193326Sed /// SymtabTy - LLVM type for struct objc_symtab. 495224145Sdim llvm::StructType *SymtabTy; 496193326Sed /// SymtabPtrTy - LLVM type for struct objc_symtab *. 497224145Sdim llvm::Type *SymtabPtrTy; 498193326Sed /// ModuleTy - LLVM type for struct objc_module. 499224145Sdim llvm::StructType *ModuleTy; 500193326Sed 501193326Sed /// ProtocolTy - LLVM type for struct objc_protocol. 502224145Sdim llvm::StructType *ProtocolTy; 503193326Sed /// ProtocolPtrTy - LLVM type for struct objc_protocol *. 504224145Sdim llvm::Type *ProtocolPtrTy; 505193326Sed /// ProtocolExtensionTy - LLVM type for struct 506193326Sed /// objc_protocol_extension. 507224145Sdim llvm::StructType *ProtocolExtensionTy; 508193326Sed /// ProtocolExtensionTy - LLVM type for struct 509193326Sed /// objc_protocol_extension *. 510224145Sdim llvm::Type *ProtocolExtensionPtrTy; 511193326Sed /// MethodDescriptionTy - LLVM type for struct 512193326Sed /// objc_method_description. 513224145Sdim llvm::StructType *MethodDescriptionTy; 514193326Sed /// MethodDescriptionListTy - LLVM type for struct 515193326Sed /// objc_method_description_list. 516224145Sdim llvm::StructType *MethodDescriptionListTy; 517193326Sed /// MethodDescriptionListPtrTy - LLVM type for struct 518193326Sed /// objc_method_description_list *. 519224145Sdim llvm::Type *MethodDescriptionListPtrTy; 520193326Sed /// ProtocolListTy - LLVM type for struct objc_property_list. 521224145Sdim llvm::StructType *ProtocolListTy; 522193326Sed /// ProtocolListPtrTy - LLVM type for struct objc_property_list*. 523224145Sdim llvm::Type *ProtocolListPtrTy; 524193326Sed /// CategoryTy - LLVM type for struct objc_category. 525224145Sdim llvm::StructType *CategoryTy; 526193326Sed /// ClassTy - LLVM type for struct objc_class. 527224145Sdim llvm::StructType *ClassTy; 528193326Sed /// ClassPtrTy - LLVM type for struct objc_class *. 529224145Sdim llvm::Type *ClassPtrTy; 530193326Sed /// ClassExtensionTy - LLVM type for struct objc_class_ext. 531224145Sdim llvm::StructType *ClassExtensionTy; 532193326Sed /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *. 533224145Sdim llvm::Type *ClassExtensionPtrTy; 534193326Sed // IvarTy - LLVM type for struct objc_ivar. 535224145Sdim llvm::StructType *IvarTy; 536193326Sed /// IvarListTy - LLVM type for struct objc_ivar_list. 537224145Sdim llvm::Type *IvarListTy; 538193326Sed /// IvarListPtrTy - LLVM type for struct objc_ivar_list *. 539224145Sdim llvm::Type *IvarListPtrTy; 540193326Sed /// MethodListTy - LLVM type for struct objc_method_list. 541224145Sdim llvm::Type *MethodListTy; 542193326Sed /// MethodListPtrTy - LLVM type for struct objc_method_list *. 543224145Sdim llvm::Type *MethodListPtrTy; 544198092Srdivacky 545193326Sed /// ExceptionDataTy - LLVM type for struct _objc_exception_data. 546224145Sdim llvm::Type *ExceptionDataTy; 547224145Sdim 548193326Sed /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function. 549193326Sed llvm::Constant *getExceptionTryEnterFn() { 550224145Sdim llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; 551198092Srdivacky return CGM.CreateRuntimeFunction( 552223017Sdim llvm::FunctionType::get(CGM.VoidTy, params, false), 553198092Srdivacky "objc_exception_try_enter"); 554193326Sed } 555193326Sed 556193326Sed /// ExceptionTryExitFn - LLVM objc_exception_try_exit function. 557193326Sed llvm::Constant *getExceptionTryExitFn() { 558224145Sdim llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; 559198092Srdivacky return CGM.CreateRuntimeFunction( 560223017Sdim llvm::FunctionType::get(CGM.VoidTy, params, false), 561198092Srdivacky "objc_exception_try_exit"); 562193326Sed } 563193326Sed 564193326Sed /// ExceptionExtractFn - LLVM objc_exception_extract function. 565193326Sed llvm::Constant *getExceptionExtractFn() { 566224145Sdim llvm::Type *params[] = { ExceptionDataTy->getPointerTo() }; 567193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 568223017Sdim params, false), 569193326Sed "objc_exception_extract"); 570193326Sed } 571198092Srdivacky 572193326Sed /// ExceptionMatchFn - LLVM objc_exception_match function. 573193326Sed llvm::Constant *getExceptionMatchFn() { 574224145Sdim llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy }; 575198092Srdivacky return CGM.CreateRuntimeFunction( 576223017Sdim llvm::FunctionType::get(CGM.Int32Ty, params, false), 577198092Srdivacky "objc_exception_match"); 578198092Srdivacky 579193326Sed } 580198092Srdivacky 581193326Sed /// SetJmpFn - LLVM _setjmp function. 582193326Sed llvm::Constant *getSetJmpFn() { 583223017Sdim // This is specifically the prototype for x86. 584224145Sdim llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() }; 585249423Sdim return 586249423Sdim CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty, 587249423Sdim params, false), 588249423Sdim "_setjmp", 589249423Sdim llvm::AttributeSet::get(CGM.getLLVMContext(), 590249423Sdim llvm::AttributeSet::FunctionIndex, 591249423Sdim llvm::Attribute::NonLazyBind)); 592193326Sed } 593198092Srdivacky 594193326Sedpublic: 595193326Sed ObjCTypesHelper(CodeGen::CodeGenModule &cgm); 596193326Sed ~ObjCTypesHelper() {} 597193326Sed}; 598193326Sed 599193326Sed/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's 600193326Sed/// modern abi 601193326Sedclass ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper { 602193326Sedpublic: 603198092Srdivacky 604193326Sed // MethodListnfABITy - LLVM for struct _method_list_t 605224145Sdim llvm::StructType *MethodListnfABITy; 606198092Srdivacky 607193326Sed // MethodListnfABIPtrTy - LLVM for struct _method_list_t* 608224145Sdim llvm::Type *MethodListnfABIPtrTy; 609198092Srdivacky 610193326Sed // ProtocolnfABITy = LLVM for struct _protocol_t 611224145Sdim llvm::StructType *ProtocolnfABITy; 612198092Srdivacky 613193326Sed // ProtocolnfABIPtrTy = LLVM for struct _protocol_t* 614224145Sdim llvm::Type *ProtocolnfABIPtrTy; 615193326Sed 616193326Sed // ProtocolListnfABITy - LLVM for struct _objc_protocol_list 617224145Sdim llvm::StructType *ProtocolListnfABITy; 618198092Srdivacky 619193326Sed // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list* 620224145Sdim llvm::Type *ProtocolListnfABIPtrTy; 621198092Srdivacky 622193326Sed // ClassnfABITy - LLVM for struct _class_t 623224145Sdim llvm::StructType *ClassnfABITy; 624198092Srdivacky 625193326Sed // ClassnfABIPtrTy - LLVM for struct _class_t* 626224145Sdim llvm::Type *ClassnfABIPtrTy; 627198092Srdivacky 628193326Sed // IvarnfABITy - LLVM for struct _ivar_t 629224145Sdim llvm::StructType *IvarnfABITy; 630198092Srdivacky 631193326Sed // IvarListnfABITy - LLVM for struct _ivar_list_t 632224145Sdim llvm::StructType *IvarListnfABITy; 633198092Srdivacky 634193326Sed // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t* 635224145Sdim llvm::Type *IvarListnfABIPtrTy; 636198092Srdivacky 637193326Sed // ClassRonfABITy - LLVM for struct _class_ro_t 638224145Sdim llvm::StructType *ClassRonfABITy; 639198092Srdivacky 640193326Sed // ImpnfABITy - LLVM for id (*)(id, SEL, ...) 641224145Sdim llvm::Type *ImpnfABITy; 642198092Srdivacky 643193326Sed // CategorynfABITy - LLVM for struct _category_t 644224145Sdim llvm::StructType *CategorynfABITy; 645198092Srdivacky 646193326Sed // New types for nonfragile abi messaging. 647198092Srdivacky 648193326Sed // MessageRefTy - LLVM for: 649193326Sed // struct _message_ref_t { 650193326Sed // IMP messenger; 651193326Sed // SEL name; 652193326Sed // }; 653224145Sdim llvm::StructType *MessageRefTy; 654193326Sed // MessageRefCTy - clang type for struct _message_ref_t 655193326Sed QualType MessageRefCTy; 656198092Srdivacky 657193326Sed // MessageRefPtrTy - LLVM for struct _message_ref_t* 658224145Sdim llvm::Type *MessageRefPtrTy; 659193326Sed // MessageRefCPtrTy - clang type for struct _message_ref_t* 660193326Sed QualType MessageRefCPtrTy; 661198092Srdivacky 662193326Sed // MessengerTy - Type of the messenger (shown as IMP above) 663224145Sdim llvm::FunctionType *MessengerTy; 664198092Srdivacky 665193326Sed // SuperMessageRefTy - LLVM for: 666193326Sed // struct _super_message_ref_t { 667193326Sed // SUPER_IMP messenger; 668193326Sed // SEL name; 669193326Sed // }; 670224145Sdim llvm::StructType *SuperMessageRefTy; 671198092Srdivacky 672193326Sed // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* 673224145Sdim llvm::Type *SuperMessageRefPtrTy; 674193326Sed 675193326Sed llvm::Constant *getMessageSendFixupFn() { 676193326Sed // id objc_msgSend_fixup(id, struct message_ref_t*, ...) 677224145Sdim llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; 678193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 679223017Sdim params, true), 680193326Sed "objc_msgSend_fixup"); 681193326Sed } 682198092Srdivacky 683193326Sed llvm::Constant *getMessageSendFpretFixupFn() { 684193326Sed // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...) 685224145Sdim llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; 686193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 687223017Sdim params, true), 688193326Sed "objc_msgSend_fpret_fixup"); 689193326Sed } 690198092Srdivacky 691193326Sed llvm::Constant *getMessageSendStretFixupFn() { 692193326Sed // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...) 693224145Sdim llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; 694193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 695223017Sdim params, true), 696193326Sed "objc_msgSend_stret_fixup"); 697193326Sed } 698198092Srdivacky 699193326Sed llvm::Constant *getMessageSendSuper2FixupFn() { 700198092Srdivacky // id objc_msgSendSuper2_fixup (struct objc_super *, 701193326Sed // struct _super_message_ref_t*, ...) 702224145Sdim llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy }; 703193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 704223017Sdim params, true), 705193326Sed "objc_msgSendSuper2_fixup"); 706193326Sed } 707198092Srdivacky 708193326Sed llvm::Constant *getMessageSendSuper2StretFixupFn() { 709198092Srdivacky // id objc_msgSendSuper2_stret_fixup(struct objc_super *, 710193326Sed // struct _super_message_ref_t*, ...) 711224145Sdim llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy }; 712193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 713223017Sdim params, true), 714193326Sed "objc_msgSendSuper2_stret_fixup"); 715193326Sed } 716198092Srdivacky 717193326Sed llvm::Constant *getObjCEndCatchFn() { 718223017Sdim return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false), 719193326Sed "objc_end_catch"); 720198092Srdivacky 721193326Sed } 722198092Srdivacky 723193326Sed llvm::Constant *getObjCBeginCatchFn() { 724224145Sdim llvm::Type *params[] = { Int8PtrTy }; 725193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy, 726223017Sdim params, false), 727193326Sed "objc_begin_catch"); 728193326Sed } 729193326Sed 730224145Sdim llvm::StructType *EHTypeTy; 731224145Sdim llvm::Type *EHTypePtrTy; 732224145Sdim 733193326Sed ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm); 734193326Sed ~ObjCNonFragileABITypesHelper(){} 735193326Sed}; 736198092Srdivacky 737193326Sedclass CGObjCCommonMac : public CodeGen::CGObjCRuntime { 738193326Sedpublic: 739193326Sed // FIXME - accessibility 740193326Sed class GC_IVAR { 741193326Sed public: 742193326Sed unsigned ivar_bytepos; 743193326Sed unsigned ivar_size; 744193326Sed GC_IVAR(unsigned bytepos = 0, unsigned size = 0) 745198092Srdivacky : ivar_bytepos(bytepos), ivar_size(size) {} 746193326Sed 747193326Sed // Allow sorting based on byte pos. 748193326Sed bool operator<(const GC_IVAR &b) const { 749193326Sed return ivar_bytepos < b.ivar_bytepos; 750193326Sed } 751193326Sed }; 752198092Srdivacky 753193326Sed class SKIP_SCAN { 754193326Sed public: 755193326Sed unsigned skip; 756193326Sed unsigned scan; 757198092Srdivacky SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0) 758193326Sed : skip(_skip), scan(_scan) {} 759193326Sed }; 760198092Srdivacky 761243830Sdim /// opcode for captured block variables layout 'instructions'. 762243830Sdim /// In the following descriptions, 'I' is the value of the immediate field. 763243830Sdim /// (field following the opcode). 764243830Sdim /// 765243830Sdim enum BLOCK_LAYOUT_OPCODE { 766243830Sdim /// An operator which affects how the following layout should be 767243830Sdim /// interpreted. 768243830Sdim /// I == 0: Halt interpretation and treat everything else as 769243830Sdim /// a non-pointer. Note that this instruction is equal 770243830Sdim /// to '\0'. 771243830Sdim /// I != 0: Currently unused. 772243830Sdim BLOCK_LAYOUT_OPERATOR = 0, 773243830Sdim 774243830Sdim /// The next I+1 bytes do not contain a value of object pointer type. 775243830Sdim /// Note that this can leave the stream unaligned, meaning that 776243830Sdim /// subsequent word-size instructions do not begin at a multiple of 777243830Sdim /// the pointer size. 778243830Sdim BLOCK_LAYOUT_NON_OBJECT_BYTES = 1, 779243830Sdim 780243830Sdim /// The next I+1 words do not contain a value of object pointer type. 781243830Sdim /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for 782243830Sdim /// when the required skip quantity is a multiple of the pointer size. 783243830Sdim BLOCK_LAYOUT_NON_OBJECT_WORDS = 2, 784243830Sdim 785243830Sdim /// The next I+1 words are __strong pointers to Objective-C 786243830Sdim /// objects or blocks. 787243830Sdim BLOCK_LAYOUT_STRONG = 3, 788243830Sdim 789243830Sdim /// The next I+1 words are pointers to __block variables. 790243830Sdim BLOCK_LAYOUT_BYREF = 4, 791243830Sdim 792243830Sdim /// The next I+1 words are __weak pointers to Objective-C 793243830Sdim /// objects or blocks. 794243830Sdim BLOCK_LAYOUT_WEAK = 5, 795243830Sdim 796243830Sdim /// The next I+1 words are __unsafe_unretained pointers to 797243830Sdim /// Objective-C objects or blocks. 798243830Sdim BLOCK_LAYOUT_UNRETAINED = 6 799243830Sdim 800243830Sdim /// The next I+1 words are block or object pointers with some 801243830Sdim /// as-yet-unspecified ownership semantics. If we add more 802243830Sdim /// flavors of ownership semantics, values will be taken from 803243830Sdim /// this range. 804243830Sdim /// 805243830Sdim /// This is included so that older tools can at least continue 806243830Sdim /// processing the layout past such things. 807243830Sdim //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10, 808243830Sdim 809243830Sdim /// All other opcodes are reserved. Halt interpretation and 810243830Sdim /// treat everything else as opaque. 811243830Sdim }; 812243830Sdim 813243830Sdim class RUN_SKIP { 814243830Sdim public: 815243830Sdim enum BLOCK_LAYOUT_OPCODE opcode; 816243830Sdim CharUnits block_var_bytepos; 817243830Sdim CharUnits block_var_size; 818243830Sdim RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR, 819243830Sdim CharUnits BytePos = CharUnits::Zero(), 820243830Sdim CharUnits Size = CharUnits::Zero()) 821243830Sdim : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {} 822243830Sdim 823243830Sdim // Allow sorting based on byte pos. 824243830Sdim bool operator<(const RUN_SKIP &b) const { 825243830Sdim return block_var_bytepos < b.block_var_bytepos; 826243830Sdim } 827243830Sdim }; 828243830Sdim 829193326Sedprotected: 830198092Srdivacky llvm::LLVMContext &VMContext; 831193326Sed // FIXME! May not be needing this after all. 832193326Sed unsigned ObjCABI; 833198092Srdivacky 834193326Sed // gc ivar layout bitmap calculation helper caches. 835226633Sdim SmallVector<GC_IVAR, 16> SkipIvars; 836226633Sdim SmallVector<GC_IVAR, 16> IvarsInfo; 837243830Sdim 838243830Sdim // arc/mrr layout of captured block literal variables. 839243830Sdim SmallVector<RUN_SKIP, 16> RunSkipBlockVars; 840198092Srdivacky 841193326Sed /// LazySymbols - Symbols to generate a lazy reference for. See 842193326Sed /// DefinedSymbols and FinishModule(). 843198092Srdivacky llvm::SetVector<IdentifierInfo*> LazySymbols; 844198092Srdivacky 845193326Sed /// DefinedSymbols - External symbols which are defined by this 846193326Sed /// module. The symbols in this list and LazySymbols are used to add 847193326Sed /// special linker symbols which ensure that Objective-C modules are 848193326Sed /// linked properly. 849198092Srdivacky llvm::SetVector<IdentifierInfo*> DefinedSymbols; 850198092Srdivacky 851193326Sed /// ClassNames - uniqued class names. 852193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames; 853198092Srdivacky 854193326Sed /// MethodVarNames - uniqued method variable names. 855193326Sed llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames; 856198092Srdivacky 857210299Sed /// DefinedCategoryNames - list of category names in form Class_Category. 858210299Sed llvm::SetVector<std::string> DefinedCategoryNames; 859210299Sed 860193326Sed /// MethodVarTypes - uniqued method type signatures. We have to use 861193326Sed /// a StringMap here because have no other unique reference. 862193326Sed llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes; 863198092Srdivacky 864193326Sed /// MethodDefinitions - map of methods which have been defined in 865193326Sed /// this translation unit. 866193326Sed llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions; 867198092Srdivacky 868193326Sed /// PropertyNames - uniqued method variable names. 869193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames; 870198092Srdivacky 871193326Sed /// ClassReferences - uniqued class references. 872193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences; 873198092Srdivacky 874193326Sed /// SelectorReferences - uniqued selector references. 875193326Sed llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences; 876198092Srdivacky 877193326Sed /// Protocols - Protocols for which an objc_protocol structure has 878193326Sed /// been emitted. Forward declarations are handled by creating an 879193326Sed /// empty structure whose initializer is filled in when/if defined. 880193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols; 881198092Srdivacky 882193326Sed /// DefinedProtocols - Protocols which have actually been 883193326Sed /// defined. We should not need this, see FIXME in GenerateProtocol. 884193326Sed llvm::DenseSet<IdentifierInfo*> DefinedProtocols; 885198092Srdivacky 886193326Sed /// DefinedClasses - List of defined classes. 887249423Sdim SmallVector<llvm::GlobalValue*, 16> DefinedClasses; 888193326Sed 889193326Sed /// DefinedNonLazyClasses - List of defined "non-lazy" classes. 890249423Sdim SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses; 891198092Srdivacky 892193326Sed /// DefinedCategories - List of defined categories. 893249423Sdim SmallVector<llvm::GlobalValue*, 16> DefinedCategories; 894198092Srdivacky 895193326Sed /// DefinedNonLazyCategories - List of defined "non-lazy" categories. 896249423Sdim SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories; 897193326Sed 898193326Sed /// GetNameForMethod - Return a name for the given method. 899193326Sed /// \param[out] NameOut - The return value. 900193326Sed void GetNameForMethod(const ObjCMethodDecl *OMD, 901193326Sed const ObjCContainerDecl *CD, 902226633Sdim SmallVectorImpl<char> &NameOut); 903198092Srdivacky 904193326Sed /// GetMethodVarName - Return a unique constant for the given 905193326Sed /// selector's name. The return value has type char *. 906193326Sed llvm::Constant *GetMethodVarName(Selector Sel); 907193326Sed llvm::Constant *GetMethodVarName(IdentifierInfo *Ident); 908198092Srdivacky 909193326Sed /// GetMethodVarType - Return a unique constant for the given 910234353Sdim /// method's type encoding string. The return value has type char *. 911198092Srdivacky 912193326Sed // FIXME: This is a horrible name. 913234353Sdim llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D, 914234353Sdim bool Extended = false); 915193326Sed llvm::Constant *GetMethodVarType(const FieldDecl *D); 916198092Srdivacky 917193326Sed /// GetPropertyName - Return a unique constant for the given 918193326Sed /// name. The return value has type char *. 919193326Sed llvm::Constant *GetPropertyName(IdentifierInfo *Ident); 920198092Srdivacky 921193326Sed // FIXME: This can be dropped once string functions are unified. 922193326Sed llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD, 923193326Sed const Decl *Container); 924198092Srdivacky 925193326Sed /// GetClassName - Return a unique constant for the given selector's 926193326Sed /// name. The return value has type char *. 927193326Sed llvm::Constant *GetClassName(IdentifierInfo *Ident); 928198092Srdivacky 929212904Sdim llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD); 930212904Sdim 931193326Sed /// BuildIvarLayout - Builds ivar layout bitmap for the class 932193326Sed /// implementation for the __strong or __weak case. 933193326Sed /// 934193326Sed llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI, 935193326Sed bool ForStrongLayout); 936212904Sdim 937212904Sdim llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap); 938198092Srdivacky 939193326Sed void BuildAggrIvarRecordLayout(const RecordType *RT, 940198092Srdivacky unsigned int BytePos, bool ForStrongLayout, 941198092Srdivacky bool &HasUnion); 942193326Sed void BuildAggrIvarLayout(const ObjCImplementationDecl *OI, 943193326Sed const llvm::StructLayout *Layout, 944193326Sed const RecordDecl *RD, 945234353Sdim ArrayRef<const FieldDecl*> RecFields, 946193326Sed unsigned int BytePos, bool ForStrongLayout, 947193326Sed bool &HasUnion); 948243830Sdim 949249423Sdim Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout); 950243830Sdim 951243830Sdim void UpdateRunSkipBlockVars(bool IsByref, 952243830Sdim Qualifiers::ObjCLifetime LifeTime, 953243830Sdim CharUnits FieldOffset, 954243830Sdim CharUnits FieldSize); 955243830Sdim 956243830Sdim void BuildRCBlockVarRecordLayout(const RecordType *RT, 957249423Sdim CharUnits BytePos, bool &HasUnion, 958249423Sdim bool ByrefLayout=false); 959243830Sdim 960243830Sdim void BuildRCRecordLayout(const llvm::StructLayout *RecLayout, 961243830Sdim const RecordDecl *RD, 962243830Sdim ArrayRef<const FieldDecl*> RecFields, 963249423Sdim CharUnits BytePos, bool &HasUnion, 964249423Sdim bool ByrefLayout); 965243830Sdim 966243830Sdim uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout); 967243830Sdim 968249423Sdim llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout); 969249423Sdim 970193326Sed 971193326Sed /// GetIvarLayoutName - Returns a unique constant for the given 972193326Sed /// ivar layout bitmap. 973193326Sed llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident, 974193326Sed const ObjCCommonTypesHelper &ObjCTypes); 975198092Srdivacky 976193326Sed /// EmitPropertyList - Emit the given property list. The return 977193326Sed /// value has type PropertyListPtrTy. 978226633Sdim llvm::Constant *EmitPropertyList(Twine Name, 979198092Srdivacky const Decl *Container, 980193326Sed const ObjCContainerDecl *OCD, 981193326Sed const ObjCCommonTypesHelper &ObjCTypes); 982198092Srdivacky 983234353Sdim /// EmitProtocolMethodTypes - Generate the array of extended method type 984234353Sdim /// strings. The return value has type Int8PtrPtrTy. 985234353Sdim llvm::Constant *EmitProtocolMethodTypes(Twine Name, 986234353Sdim ArrayRef<llvm::Constant*> MethodTypes, 987234353Sdim const ObjCCommonTypesHelper &ObjCTypes); 988234353Sdim 989200583Srdivacky /// PushProtocolProperties - Push protocol's property on the input stack. 990234353Sdim void PushProtocolProperties( 991234353Sdim llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet, 992249423Sdim SmallVectorImpl<llvm::Constant*> &Properties, 993234353Sdim const Decl *Container, 994234353Sdim const ObjCProtocolDecl *PROTO, 995234353Sdim const ObjCCommonTypesHelper &ObjCTypes); 996200583Srdivacky 997193326Sed /// GetProtocolRef - Return a reference to the internal protocol 998193326Sed /// description, creating an empty one if it has not been 999193326Sed /// defined. The return value has type ProtocolPtrTy. 1000193326Sed llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD); 1001193326Sed 1002193326Sed /// CreateMetadataVar - Create a global variable with internal 1003193326Sed /// linkage for use by the Objective-C runtime. 1004193326Sed /// 1005193326Sed /// This is a convenience wrapper which not only creates the 1006193326Sed /// variable, but also sets the section and alignment and adds the 1007198092Srdivacky /// global to the "llvm.used" list. 1008193326Sed /// 1009193326Sed /// \param Name - The variable name. 1010193326Sed /// \param Init - The variable initializer; this is also used to 1011193326Sed /// define the type of the variable. 1012193326Sed /// \param Section - The section the variable should go into, or 0. 1013193326Sed /// \param Align - The alignment for the variable, or 0. 1014193326Sed /// \param AddToUsed - Whether the variable should be added to 1015193326Sed /// "llvm.used". 1016226633Sdim llvm::GlobalVariable *CreateMetadataVar(Twine Name, 1017193326Sed llvm::Constant *Init, 1018193326Sed const char *Section, 1019193326Sed unsigned Align, 1020193326Sed bool AddToUsed); 1021193326Sed 1022223017Sdim CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, 1023223017Sdim ReturnValueSlot Return, 1024223017Sdim QualType ResultType, 1025223017Sdim llvm::Value *Sel, 1026223017Sdim llvm::Value *Arg0, 1027223017Sdim QualType Arg0Ty, 1028223017Sdim bool IsSuper, 1029223017Sdim const CallArgList &CallArgs, 1030223017Sdim const ObjCMethodDecl *OMD, 1031223017Sdim const ObjCCommonTypesHelper &ObjCTypes); 1032193326Sed 1033207619Srdivacky /// EmitImageInfo - Emit the image info marker used to encode some module 1034207619Srdivacky /// level information. 1035207619Srdivacky void EmitImageInfo(); 1036207619Srdivacky 1037198092Srdivackypublic: 1038198092Srdivacky CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : 1039234353Sdim CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { } 1040195099Sed 1041202879Srdivacky virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL); 1042234353Sdim 1043193326Sed virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, 1044193326Sed const ObjCContainerDecl *CD=0); 1045198092Srdivacky 1046193326Sed virtual void GenerateProtocol(const ObjCProtocolDecl *PD); 1047198092Srdivacky 1048193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1049193326Sed /// declaration, emitting it if necessary. The return value has type 1050193326Sed /// ProtocolPtrTy. 1051193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0; 1052198092Srdivacky 1053193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1054193326Sed /// object for the given declaration, emitting it if needed. These 1055193326Sed /// forward references will be filled in with empty bodies if no 1056193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1057193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0; 1058218893Sdim virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, 1059218893Sdim const CGBlockInfo &blockInfo); 1060243830Sdim virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, 1061243830Sdim const CGBlockInfo &blockInfo); 1062212904Sdim 1063249423Sdim virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM, 1064249423Sdim QualType T); 1065193326Sed}; 1066198092Srdivacky 1067193326Sedclass CGObjCMac : public CGObjCCommonMac { 1068193326Sedprivate: 1069193326Sed ObjCTypesHelper ObjCTypes; 1070193326Sed 1071193326Sed /// EmitModuleInfo - Another marker encoding module level 1072198092Srdivacky /// information. 1073193326Sed void EmitModuleInfo(); 1074193326Sed 1075193326Sed /// EmitModuleSymols - Emit module symbols, the list of defined 1076193326Sed /// classes and categories. The result has type SymtabPtrTy. 1077193326Sed llvm::Constant *EmitModuleSymbols(); 1078193326Sed 1079193326Sed /// FinishModule - Write out global data structures at the end of 1080193326Sed /// processing a translation unit. 1081193326Sed void FinishModule(); 1082193326Sed 1083193326Sed /// EmitClassExtension - Generate the class extension structure used 1084193326Sed /// to store the weak ivar layout and properties. The return value 1085193326Sed /// has type ClassExtensionPtrTy. 1086193326Sed llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID); 1087193326Sed 1088193326Sed /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1089193326Sed /// for the given class. 1090249423Sdim llvm::Value *EmitClassRef(CodeGenFunction &CGF, 1091193326Sed const ObjCInterfaceDecl *ID); 1092199482Srdivacky 1093249423Sdim llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, 1094224145Sdim IdentifierInfo *II); 1095224145Sdim 1096249423Sdim llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF); 1097224145Sdim 1098199482Srdivacky /// EmitSuperClassRef - Emits reference to class's main metadata class. 1099199482Srdivacky llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID); 1100193326Sed 1101193326Sed /// EmitIvarList - Emit the ivar list for the given 1102193326Sed /// implementation. If ForClass is true the list of class ivars 1103193326Sed /// (i.e. metaclass ivars) is emitted, otherwise the list of 1104193326Sed /// interface ivars will be emitted. The return value has type 1105193326Sed /// IvarListPtrTy. 1106193326Sed llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID, 1107193326Sed bool ForClass); 1108198092Srdivacky 1109193326Sed /// EmitMetaClass - Emit a forward reference to the class structure 1110193326Sed /// for the metaclass of the given interface. The return value has 1111193326Sed /// type ClassPtrTy. 1112193326Sed llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID); 1113193326Sed 1114193326Sed /// EmitMetaClass - Emit a class structure for the metaclass of the 1115193326Sed /// given implementation. The return value has type ClassPtrTy. 1116193326Sed llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID, 1117193326Sed llvm::Constant *Protocols, 1118234353Sdim ArrayRef<llvm::Constant*> Methods); 1119198092Srdivacky 1120193326Sed llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); 1121198092Srdivacky 1122193326Sed llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD); 1123193326Sed 1124193326Sed /// EmitMethodList - Emit the method list for the given 1125193326Sed /// implementation. The return value has type MethodListPtrTy. 1126226633Sdim llvm::Constant *EmitMethodList(Twine Name, 1127193326Sed const char *Section, 1128234353Sdim ArrayRef<llvm::Constant*> Methods); 1129193326Sed 1130193326Sed /// EmitMethodDescList - Emit a method description list for a list of 1131198092Srdivacky /// method declarations. 1132193326Sed /// - TypeName: The name for the type containing the methods. 1133193326Sed /// - IsProtocol: True iff these methods are for a protocol. 1134193326Sed /// - ClassMethds: True iff these are class methods. 1135193326Sed /// - Required: When true, only "required" methods are 1136193326Sed /// listed. Similarly, when false only "optional" methods are 1137193326Sed /// listed. For classes this should always be true. 1138193326Sed /// - begin, end: The method list to output. 1139193326Sed /// 1140193326Sed /// The return value has type MethodDescriptionListPtrTy. 1141226633Sdim llvm::Constant *EmitMethodDescList(Twine Name, 1142193326Sed const char *Section, 1143234353Sdim ArrayRef<llvm::Constant*> Methods); 1144193326Sed 1145193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1146193326Sed /// declaration, emitting it if necessary. The return value has type 1147193326Sed /// ProtocolPtrTy. 1148193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD); 1149193326Sed 1150193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1151193326Sed /// object for the given declaration, emitting it if needed. These 1152193326Sed /// forward references will be filled in with empty bodies if no 1153193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1154193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD); 1155193326Sed 1156193326Sed /// EmitProtocolExtension - Generate the protocol extension 1157193326Sed /// structure used to store optional instance and class methods, and 1158193326Sed /// protocol properties. The return value has type 1159193326Sed /// ProtocolExtensionPtrTy. 1160193326Sed llvm::Constant * 1161193326Sed EmitProtocolExtension(const ObjCProtocolDecl *PD, 1162234353Sdim ArrayRef<llvm::Constant*> OptInstanceMethods, 1163234353Sdim ArrayRef<llvm::Constant*> OptClassMethods, 1164234353Sdim ArrayRef<llvm::Constant*> MethodTypesExt); 1165193326Sed 1166193326Sed /// EmitProtocolList - Generate the list of referenced 1167193326Sed /// protocols. The return value has type ProtocolListPtrTy. 1168226633Sdim llvm::Constant *EmitProtocolList(Twine Name, 1169193326Sed ObjCProtocolDecl::protocol_iterator begin, 1170193326Sed ObjCProtocolDecl::protocol_iterator end); 1171193326Sed 1172193326Sed /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, 1173193326Sed /// for the given selector. 1174249423Sdim llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel, 1175210299Sed bool lval=false); 1176198092Srdivacky 1177198092Srdivackypublic: 1178193326Sed CGObjCMac(CodeGen::CodeGenModule &cgm); 1179193326Sed 1180193326Sed virtual llvm::Function *ModuleInitFunction(); 1181198092Srdivacky 1182193326Sed virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1183208600Srdivacky ReturnValueSlot Return, 1184193326Sed QualType ResultType, 1185193326Sed Selector Sel, 1186193326Sed llvm::Value *Receiver, 1187193326Sed const CallArgList &CallArgs, 1188207619Srdivacky const ObjCInterfaceDecl *Class, 1189193326Sed const ObjCMethodDecl *Method); 1190193326Sed 1191198092Srdivacky virtual CodeGen::RValue 1192193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1193208600Srdivacky ReturnValueSlot Return, 1194193326Sed QualType ResultType, 1195193326Sed Selector Sel, 1196193326Sed const ObjCInterfaceDecl *Class, 1197193326Sed bool isCategoryImpl, 1198193326Sed llvm::Value *Receiver, 1199193326Sed bool IsClassMessage, 1200198092Srdivacky const CallArgList &CallArgs, 1201198092Srdivacky const ObjCMethodDecl *Method); 1202198092Srdivacky 1203249423Sdim virtual llvm::Value *GetClass(CodeGenFunction &CGF, 1204193326Sed const ObjCInterfaceDecl *ID); 1205193326Sed 1206249423Sdim virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel, 1207210299Sed bool lval = false); 1208193326Sed 1209193326Sed /// The NeXT/Apple runtimes do not support typed selectors; just emit an 1210193326Sed /// untyped one. 1211249423Sdim virtual llvm::Value *GetSelector(CodeGenFunction &CGF, 1212193326Sed const ObjCMethodDecl *Method); 1213193326Sed 1214212904Sdim virtual llvm::Constant *GetEHType(QualType T); 1215212904Sdim 1216193326Sed virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); 1217193326Sed 1218193326Sed virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); 1219193326Sed 1220234353Sdim virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {} 1221234353Sdim 1222249423Sdim virtual llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, 1223193326Sed const ObjCProtocolDecl *PD); 1224198092Srdivacky 1225193326Sed virtual llvm::Constant *GetPropertyGetFunction(); 1226193326Sed virtual llvm::Constant *GetPropertySetFunction(); 1227234353Sdim virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, 1228234353Sdim bool copy); 1229218893Sdim virtual llvm::Constant *GetGetStructFunction(); 1230218893Sdim virtual llvm::Constant *GetSetStructFunction(); 1231249423Sdim virtual llvm::Constant *GetCppAtomicObjectGetFunction(); 1232249423Sdim virtual llvm::Constant *GetCppAtomicObjectSetFunction(); 1233193326Sed virtual llvm::Constant *EnumerationMutationFunction(); 1234198092Srdivacky 1235210299Sed virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF, 1236210299Sed const ObjCAtTryStmt &S); 1237210299Sed virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1238210299Sed const ObjCAtSynchronizedStmt &S); 1239210299Sed void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S); 1240193326Sed virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 1241249423Sdim const ObjCAtThrowStmt &S, 1242249423Sdim bool ClearInsertionPoint=true); 1243193326Sed virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1244198092Srdivacky llvm::Value *AddrWeakObj); 1245193326Sed virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1246198092Srdivacky llvm::Value *src, llvm::Value *dst); 1247193326Sed virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1248212904Sdim llvm::Value *src, llvm::Value *dest, 1249212904Sdim bool threadlocal = false); 1250193326Sed virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 1251198092Srdivacky llvm::Value *src, llvm::Value *dest, 1252198092Srdivacky llvm::Value *ivarOffset); 1253193326Sed virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 1254193326Sed llvm::Value *src, llvm::Value *dest); 1255198092Srdivacky virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 1256198092Srdivacky llvm::Value *dest, llvm::Value *src, 1257210299Sed llvm::Value *size); 1258198092Srdivacky 1259193326Sed virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 1260193326Sed QualType ObjectTy, 1261193326Sed llvm::Value *BaseValue, 1262193326Sed const ObjCIvarDecl *Ivar, 1263193326Sed unsigned CVRQualifiers); 1264193326Sed virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 1265193326Sed const ObjCInterfaceDecl *Interface, 1266193326Sed const ObjCIvarDecl *Ivar); 1267223017Sdim 1268223017Sdim /// GetClassGlobal - Return the global variable for the Objective-C 1269223017Sdim /// class of the given name. 1270223017Sdim virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) { 1271226633Sdim llvm_unreachable("CGObjCMac::GetClassGlobal"); 1272223017Sdim } 1273193326Sed}; 1274198092Srdivacky 1275193326Sedclass CGObjCNonFragileABIMac : public CGObjCCommonMac { 1276193326Sedprivate: 1277193326Sed ObjCNonFragileABITypesHelper ObjCTypes; 1278193326Sed llvm::GlobalVariable* ObjCEmptyCacheVar; 1279193326Sed llvm::GlobalVariable* ObjCEmptyVtableVar; 1280198092Srdivacky 1281193326Sed /// SuperClassReferences - uniqued super class references. 1282193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences; 1283198092Srdivacky 1284193326Sed /// MetaClassReferences - uniqued meta class references. 1285193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences; 1286193326Sed 1287193326Sed /// EHTypeReferences - uniqued class ehtype references. 1288193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences; 1289198092Srdivacky 1290223017Sdim /// VTableDispatchMethods - List of methods for which we generate 1291223017Sdim /// vtable-based message dispatch. 1292223017Sdim llvm::DenseSet<Selector> VTableDispatchMethods; 1293198092Srdivacky 1294199482Srdivacky /// DefinedMetaClasses - List of defined meta-classes. 1295199482Srdivacky std::vector<llvm::GlobalValue*> DefinedMetaClasses; 1296199482Srdivacky 1297223017Sdim /// isVTableDispatchedSelector - Returns true if SEL is a 1298223017Sdim /// vtable-based selector. 1299223017Sdim bool isVTableDispatchedSelector(Selector Sel); 1300198092Srdivacky 1301193326Sed /// FinishNonFragileABIModule - Write out global data structures at the end of 1302193326Sed /// processing a translation unit. 1303193326Sed void FinishNonFragileABIModule(); 1304193326Sed 1305193326Sed /// AddModuleClassList - Add the given list of class pointers to the 1306193326Sed /// module with the provided symbol and section names. 1307234353Sdim void AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container, 1308193326Sed const char *SymbolName, 1309193326Sed const char *SectionName); 1310193326Sed 1311198092Srdivacky llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags, 1312198092Srdivacky unsigned InstanceStart, 1313198092Srdivacky unsigned InstanceSize, 1314198092Srdivacky const ObjCImplementationDecl *ID); 1315193326Sed llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName, 1316198092Srdivacky llvm::Constant *IsAGV, 1317193326Sed llvm::Constant *SuperClassGV, 1318193326Sed llvm::Constant *ClassRoGV, 1319193326Sed bool HiddenVisibility); 1320198092Srdivacky 1321193326Sed llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); 1322198092Srdivacky 1323193326Sed llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD); 1324198092Srdivacky 1325193326Sed /// EmitMethodList - Emit the method list for the given 1326193326Sed /// implementation. The return value has type MethodListnfABITy. 1327226633Sdim llvm::Constant *EmitMethodList(Twine Name, 1328193326Sed const char *Section, 1329234353Sdim ArrayRef<llvm::Constant*> Methods); 1330193326Sed /// EmitIvarList - Emit the ivar list for the given 1331193326Sed /// implementation. If ForClass is true the list of class ivars 1332193326Sed /// (i.e. metaclass ivars) is emitted, otherwise the list of 1333193326Sed /// interface ivars will be emitted. The return value has type 1334193326Sed /// IvarListnfABIPtrTy. 1335193326Sed llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID); 1336198092Srdivacky 1337193326Sed llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, 1338193326Sed const ObjCIvarDecl *Ivar, 1339193326Sed unsigned long int offset); 1340198092Srdivacky 1341193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1342193326Sed /// declaration, emitting it if necessary. The return value has type 1343193326Sed /// ProtocolPtrTy. 1344193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD); 1345198092Srdivacky 1346193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1347193326Sed /// object for the given declaration, emitting it if needed. These 1348193326Sed /// forward references will be filled in with empty bodies if no 1349193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1350193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD); 1351198092Srdivacky 1352193326Sed /// EmitProtocolList - Generate the list of referenced 1353193326Sed /// protocols. The return value has type ProtocolListPtrTy. 1354226633Sdim llvm::Constant *EmitProtocolList(Twine Name, 1355193326Sed ObjCProtocolDecl::protocol_iterator begin, 1356193326Sed ObjCProtocolDecl::protocol_iterator end); 1357198092Srdivacky 1358223017Sdim CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF, 1359223017Sdim ReturnValueSlot Return, 1360223017Sdim QualType ResultType, 1361223017Sdim Selector Sel, 1362223017Sdim llvm::Value *Receiver, 1363223017Sdim QualType Arg0Ty, 1364223017Sdim bool IsSuper, 1365223017Sdim const CallArgList &CallArgs, 1366223017Sdim const ObjCMethodDecl *Method); 1367223017Sdim 1368193326Sed /// GetClassGlobal - Return the global variable for the Objective-C 1369193326Sed /// class of the given name. 1370193326Sed llvm::GlobalVariable *GetClassGlobal(const std::string &Name); 1371223017Sdim 1372193326Sed /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1373193326Sed /// for the given class reference. 1374249423Sdim llvm::Value *EmitClassRef(CodeGenFunction &CGF, 1375193326Sed const ObjCInterfaceDecl *ID); 1376224145Sdim 1377249423Sdim llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, 1378224145Sdim IdentifierInfo *II); 1379224145Sdim 1380249423Sdim llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF); 1381198092Srdivacky 1382193326Sed /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1383193326Sed /// for the given super class reference. 1384249423Sdim llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF, 1385198092Srdivacky const ObjCInterfaceDecl *ID); 1386198092Srdivacky 1387193326Sed /// EmitMetaClassRef - Return a Value * of the address of _class_t 1388193326Sed /// meta-data 1389249423Sdim llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF, 1390193326Sed const ObjCInterfaceDecl *ID); 1391193326Sed 1392193326Sed /// ObjCIvarOffsetVariable - Returns the ivar offset variable for 1393193326Sed /// the given ivar. 1394193326Sed /// 1395193326Sed llvm::GlobalVariable * ObjCIvarOffsetVariable( 1396198092Srdivacky const ObjCInterfaceDecl *ID, 1397198092Srdivacky const ObjCIvarDecl *Ivar); 1398198092Srdivacky 1399193326Sed /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, 1400193326Sed /// for the given selector. 1401249423Sdim llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel, 1402210299Sed bool lval=false); 1403193326Sed 1404193326Sed /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C 1405193326Sed /// interface. The return value has type EHTypePtrTy. 1406212904Sdim llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID, 1407193326Sed bool ForDefinition); 1408193326Sed 1409198092Srdivacky const char *getMetaclassSymbolPrefix() const { 1410193326Sed return "OBJC_METACLASS_$_"; 1411193326Sed } 1412198092Srdivacky 1413193326Sed const char *getClassSymbolPrefix() const { 1414193326Sed return "OBJC_CLASS_$_"; 1415193326Sed } 1416193326Sed 1417193326Sed void GetClassSizeInfo(const ObjCImplementationDecl *OID, 1418193326Sed uint32_t &InstanceStart, 1419193326Sed uint32_t &InstanceSize); 1420198092Srdivacky 1421193326Sed // Shamelessly stolen from Analysis/CFRefCount.cpp 1422193326Sed Selector GetNullarySelector(const char* name) const { 1423193326Sed IdentifierInfo* II = &CGM.getContext().Idents.get(name); 1424193326Sed return CGM.getContext().Selectors.getSelector(0, &II); 1425193326Sed } 1426198092Srdivacky 1427193326Sed Selector GetUnarySelector(const char* name) const { 1428193326Sed IdentifierInfo* II = &CGM.getContext().Idents.get(name); 1429193326Sed return CGM.getContext().Selectors.getSelector(1, &II); 1430193326Sed } 1431193326Sed 1432193326Sed /// ImplementationIsNonLazy - Check whether the given category or 1433193326Sed /// class implementation is "non-lazy". 1434193326Sed bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const; 1435193326Sed 1436249423Sdim bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF, 1437249423Sdim const ObjCInterfaceDecl *ID, 1438249423Sdim const ObjCIvarDecl *IV) { 1439249423Sdim // Annotate the load as an invariant load iff the object type is the type, 1440249423Sdim // or a derived type, of the class containing the ivar within an ObjC 1441249423Sdim // method. This check is needed because the ivar offset is a lazily 1442249423Sdim // initialised value that may depend on objc_msgSend to perform a fixup on 1443249423Sdim // the first message dispatch. 1444249423Sdim // 1445249423Sdim // An additional opportunity to mark the load as invariant arises when the 1446249423Sdim // base of the ivar access is a parameter to an Objective C method. 1447249423Sdim // However, because the parameters are not available in the current 1448249423Sdim // interface, we cannot perform this check. 1449249423Sdim if (CGF.CurFuncDecl && isa<ObjCMethodDecl>(CGF.CurFuncDecl)) 1450249423Sdim if (IV->getContainingInterface()->isSuperClassOf(ID)) 1451249423Sdim return true; 1452249423Sdim return false; 1453249423Sdim } 1454249423Sdim 1455193326Sedpublic: 1456193326Sed CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); 1457193326Sed // FIXME. All stubs for now! 1458193326Sed virtual llvm::Function *ModuleInitFunction(); 1459198092Srdivacky 1460193326Sed virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1461208600Srdivacky ReturnValueSlot Return, 1462193326Sed QualType ResultType, 1463193326Sed Selector Sel, 1464193326Sed llvm::Value *Receiver, 1465193326Sed const CallArgList &CallArgs, 1466207619Srdivacky const ObjCInterfaceDecl *Class, 1467193326Sed const ObjCMethodDecl *Method); 1468198092Srdivacky 1469198092Srdivacky virtual CodeGen::RValue 1470193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1471208600Srdivacky ReturnValueSlot Return, 1472193326Sed QualType ResultType, 1473193326Sed Selector Sel, 1474193326Sed const ObjCInterfaceDecl *Class, 1475193326Sed bool isCategoryImpl, 1476193326Sed llvm::Value *Receiver, 1477193326Sed bool IsClassMessage, 1478198092Srdivacky const CallArgList &CallArgs, 1479198092Srdivacky const ObjCMethodDecl *Method); 1480198092Srdivacky 1481249423Sdim virtual llvm::Value *GetClass(CodeGenFunction &CGF, 1482193326Sed const ObjCInterfaceDecl *ID); 1483198092Srdivacky 1484249423Sdim virtual llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel, 1485210299Sed bool lvalue = false) 1486249423Sdim { return EmitSelector(CGF, Sel, lvalue); } 1487193326Sed 1488193326Sed /// The NeXT/Apple runtimes do not support typed selectors; just emit an 1489193326Sed /// untyped one. 1490249423Sdim virtual llvm::Value *GetSelector(CodeGenFunction &CGF, 1491193326Sed const ObjCMethodDecl *Method) 1492249423Sdim { return EmitSelector(CGF, Method->getSelector()); } 1493198092Srdivacky 1494193326Sed virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); 1495198092Srdivacky 1496193326Sed virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); 1497234353Sdim 1498234353Sdim virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {} 1499234353Sdim 1500249423Sdim virtual llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF, 1501193326Sed const ObjCProtocolDecl *PD); 1502198092Srdivacky 1503212904Sdim virtual llvm::Constant *GetEHType(QualType T); 1504212904Sdim 1505198092Srdivacky virtual llvm::Constant *GetPropertyGetFunction() { 1506193326Sed return ObjCTypes.getGetPropertyFn(); 1507193326Sed } 1508198092Srdivacky virtual llvm::Constant *GetPropertySetFunction() { 1509198092Srdivacky return ObjCTypes.getSetPropertyFn(); 1510193326Sed } 1511207619Srdivacky 1512234353Sdim virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic, 1513234353Sdim bool copy) { 1514234353Sdim return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy); 1515234353Sdim } 1516234353Sdim 1517218893Sdim virtual llvm::Constant *GetSetStructFunction() { 1518207619Srdivacky return ObjCTypes.getCopyStructFn(); 1519207619Srdivacky } 1520218893Sdim virtual llvm::Constant *GetGetStructFunction() { 1521218893Sdim return ObjCTypes.getCopyStructFn(); 1522218893Sdim } 1523249423Sdim virtual llvm::Constant *GetCppAtomicObjectSetFunction() { 1524234353Sdim return ObjCTypes.getCppAtomicObjectFunction(); 1525234353Sdim } 1526249423Sdim virtual llvm::Constant *GetCppAtomicObjectGetFunction() { 1527249423Sdim return ObjCTypes.getCppAtomicObjectFunction(); 1528249423Sdim } 1529207619Srdivacky 1530193326Sed virtual llvm::Constant *EnumerationMutationFunction() { 1531193326Sed return ObjCTypes.getEnumerationMutationFn(); 1532193326Sed } 1533198092Srdivacky 1534210299Sed virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF, 1535210299Sed const ObjCAtTryStmt &S); 1536210299Sed virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1537210299Sed const ObjCAtSynchronizedStmt &S); 1538193326Sed virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 1539249423Sdim const ObjCAtThrowStmt &S, 1540249423Sdim bool ClearInsertionPoint=true); 1541193326Sed virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1542193326Sed llvm::Value *AddrWeakObj); 1543193326Sed virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1544193326Sed llvm::Value *src, llvm::Value *dst); 1545193326Sed virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1546212904Sdim llvm::Value *src, llvm::Value *dest, 1547212904Sdim bool threadlocal = false); 1548193326Sed virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 1549198092Srdivacky llvm::Value *src, llvm::Value *dest, 1550198092Srdivacky llvm::Value *ivarOffset); 1551193326Sed virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 1552193326Sed llvm::Value *src, llvm::Value *dest); 1553198092Srdivacky virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 1554198092Srdivacky llvm::Value *dest, llvm::Value *src, 1555210299Sed llvm::Value *size); 1556193326Sed virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 1557193326Sed QualType ObjectTy, 1558193326Sed llvm::Value *BaseValue, 1559193326Sed const ObjCIvarDecl *Ivar, 1560193326Sed unsigned CVRQualifiers); 1561193326Sed virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 1562193326Sed const ObjCInterfaceDecl *Interface, 1563193326Sed const ObjCIvarDecl *Ivar); 1564193326Sed}; 1565198092Srdivacky 1566223017Sdim/// A helper class for performing the null-initialization of a return 1567223017Sdim/// value. 1568223017Sdimstruct NullReturnState { 1569223017Sdim llvm::BasicBlock *NullBB; 1570249423Sdim NullReturnState() : NullBB(0) {} 1571223017Sdim 1572249423Sdim /// Perform a null-check of the given receiver. 1573223017Sdim void init(CodeGenFunction &CGF, llvm::Value *receiver) { 1574249423Sdim // Make blocks for the null-receiver and call edges. 1575249423Sdim NullBB = CGF.createBasicBlock("msgSend.null-receiver"); 1576249423Sdim llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call"); 1577223017Sdim 1578223017Sdim // Check for a null receiver and, if there is one, jump to the 1579249423Sdim // null-receiver block. There's no point in trying to avoid it: 1580249423Sdim // we're always going to put *something* there, because otherwise 1581249423Sdim // we shouldn't have done this null-check in the first place. 1582223017Sdim llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver); 1583223017Sdim CGF.Builder.CreateCondBr(isNull, NullBB, callBB); 1584223017Sdim 1585223017Sdim // Otherwise, start performing the call. 1586223017Sdim CGF.EmitBlock(callBB); 1587223017Sdim } 1588223017Sdim 1589249423Sdim /// Complete the null-return operation. It is valid to call this 1590249423Sdim /// regardless of whether 'init' has been called. 1591234353Sdim RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType, 1592234353Sdim const CallArgList &CallArgs, 1593234353Sdim const ObjCMethodDecl *Method) { 1594249423Sdim // If we never had to do a null-check, just use the raw result. 1595223017Sdim if (!NullBB) return result; 1596249423Sdim 1597249423Sdim // The continuation block. This will be left null if we don't have an 1598249423Sdim // IP, which can happen if the method we're calling is marked noreturn. 1599249423Sdim llvm::BasicBlock *contBB = 0; 1600234353Sdim 1601249423Sdim // Finish the call path. 1602249423Sdim llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock(); 1603249423Sdim if (callBB) { 1604249423Sdim contBB = CGF.createBasicBlock("msgSend.cont"); 1605249423Sdim CGF.Builder.CreateBr(contBB); 1606234353Sdim } 1607223017Sdim 1608249423Sdim // Okay, start emitting the null-receiver block. 1609223017Sdim CGF.EmitBlock(NullBB); 1610234353Sdim 1611249423Sdim // Release any consumed arguments we've got. 1612234353Sdim if (Method) { 1613234353Sdim CallArgList::const_iterator I = CallArgs.begin(); 1614234353Sdim for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(), 1615234353Sdim e = Method->param_end(); i != e; ++i, ++I) { 1616234353Sdim const ParmVarDecl *ParamDecl = (*i); 1617234353Sdim if (ParamDecl->hasAttr<NSConsumedAttr>()) { 1618234353Sdim RValue RV = I->RV; 1619234353Sdim assert(RV.isScalar() && 1620234353Sdim "NullReturnState::complete - arg not on object"); 1621249423Sdim CGF.EmitARCRelease(RV.getScalarVal(), ARCImpreciseLifetime); 1622234353Sdim } 1623234353Sdim } 1624234353Sdim } 1625249423Sdim 1626249423Sdim // The phi code below assumes that we haven't needed any control flow yet. 1627249423Sdim assert(CGF.Builder.GetInsertBlock() == NullBB); 1628249423Sdim 1629249423Sdim // If we've got a void return, just jump to the continuation block. 1630249423Sdim if (result.isScalar() && resultType->isVoidType()) { 1631249423Sdim // No jumps required if the message-send was noreturn. 1632249423Sdim if (contBB) CGF.EmitBlock(contBB); 1633249423Sdim return result; 1634249423Sdim } 1635249423Sdim 1636249423Sdim // If we've got a scalar return, build a phi. 1637234353Sdim if (result.isScalar()) { 1638249423Sdim // Derive the null-initialization value. 1639249423Sdim llvm::Constant *null = CGF.CGM.EmitNullConstant(resultType); 1640249423Sdim 1641249423Sdim // If no join is necessary, just flow out. 1642249423Sdim if (!contBB) return RValue::get(null); 1643249423Sdim 1644249423Sdim // Otherwise, build a phi. 1645234353Sdim CGF.EmitBlock(contBB); 1646249423Sdim llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2); 1647249423Sdim phi->addIncoming(result.getScalarVal(), callBB); 1648249423Sdim phi->addIncoming(null, NullBB); 1649249423Sdim return RValue::get(phi); 1650234353Sdim } 1651249423Sdim 1652249423Sdim // If we've got an aggregate return, null the buffer out. 1653249423Sdim // FIXME: maybe we should be doing things differently for all the 1654249423Sdim // cases where the ABI has us returning (1) non-agg values in 1655249423Sdim // memory or (2) agg values in registers. 1656249423Sdim if (result.isAggregate()) { 1657234353Sdim assert(result.isAggregate() && "null init of non-aggregate result?"); 1658234353Sdim CGF.EmitNullInitialization(result.getAggregateAddr(), resultType); 1659249423Sdim if (contBB) CGF.EmitBlock(contBB); 1660234353Sdim return result; 1661234353Sdim } 1662223017Sdim 1663249423Sdim // Complex types. 1664223017Sdim CGF.EmitBlock(contBB); 1665249423Sdim CodeGenFunction::ComplexPairTy callResult = result.getComplexVal(); 1666249423Sdim 1667249423Sdim // Find the scalar type and its zero value. 1668249423Sdim llvm::Type *scalarTy = callResult.first->getType(); 1669249423Sdim llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy); 1670249423Sdim 1671249423Sdim // Build phis for both coordinates. 1672249423Sdim llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2); 1673249423Sdim real->addIncoming(callResult.first, callBB); 1674249423Sdim real->addIncoming(scalarZero, NullBB); 1675249423Sdim llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2); 1676249423Sdim imag->addIncoming(callResult.second, callBB); 1677249423Sdim imag->addIncoming(scalarZero, NullBB); 1678249423Sdim return RValue::getComplex(real, imag); 1679223017Sdim } 1680223017Sdim}; 1681223017Sdim 1682193326Sed} // end anonymous namespace 1683193326Sed 1684193326Sed/* *** Helper Functions *** */ 1685193326Sed 1686193326Sed/// getConstantGEP() - Help routine to construct simple GEPs. 1687198092Srdivackystatic llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext, 1688198092Srdivacky llvm::Constant *C, 1689193326Sed unsigned idx0, 1690193326Sed unsigned idx1) { 1691193326Sed llvm::Value *Idxs[] = { 1692198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0), 1693198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1) 1694193326Sed }; 1695226633Sdim return llvm::ConstantExpr::getGetElementPtr(C, Idxs); 1696193326Sed} 1697193326Sed 1698193326Sed/// hasObjCExceptionAttribute - Return true if this class or any super 1699193326Sed/// class has the __objc_exception__ attribute. 1700198092Srdivackystatic bool hasObjCExceptionAttribute(ASTContext &Context, 1701194613Sed const ObjCInterfaceDecl *OID) { 1702195341Sed if (OID->hasAttr<ObjCExceptionAttr>()) 1703193326Sed return true; 1704193326Sed if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 1705194613Sed return hasObjCExceptionAttribute(Context, Super); 1706193326Sed return false; 1707193326Sed} 1708193326Sed 1709193326Sed/* *** CGObjCMac Public Interface *** */ 1710198092Srdivacky 1711193326SedCGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), 1712198092Srdivacky ObjCTypes(cgm) { 1713193326Sed ObjCABI = 1; 1714198092Srdivacky EmitImageInfo(); 1715193326Sed} 1716193326Sed 1717193326Sed/// GetClass - Return a reference to the class for the given interface 1718193326Sed/// decl. 1719249423Sdimllvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF, 1720193326Sed const ObjCInterfaceDecl *ID) { 1721249423Sdim return EmitClassRef(CGF, ID); 1722193326Sed} 1723193326Sed 1724193326Sed/// GetSelector - Return the pointer to the unique'd string for this selector. 1725249423Sdimllvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel, 1726210299Sed bool lval) { 1727249423Sdim return EmitSelector(CGF, Sel, lval); 1728193326Sed} 1729249423Sdimllvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl 1730198092Srdivacky *Method) { 1731249423Sdim return EmitSelector(CGF, Method->getSelector()); 1732193326Sed} 1733193326Sed 1734212904Sdimllvm::Constant *CGObjCMac::GetEHType(QualType T) { 1735224145Sdim if (T->isObjCIdType() || 1736224145Sdim T->isObjCQualifiedIdType()) { 1737224145Sdim return CGM.GetAddrOfRTTIDescriptor( 1738226633Sdim CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true); 1739224145Sdim } 1740224145Sdim if (T->isObjCClassType() || 1741224145Sdim T->isObjCQualifiedClassType()) { 1742224145Sdim return CGM.GetAddrOfRTTIDescriptor( 1743226633Sdim CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true); 1744224145Sdim } 1745224145Sdim if (T->isObjCObjectPointerType()) 1746224145Sdim return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true); 1747224145Sdim 1748212904Sdim llvm_unreachable("asking for catch type for ObjC type in fragile runtime"); 1749212904Sdim} 1750212904Sdim 1751193326Sed/// Generate a constant CFString object. 1752198092Srdivacky/* 1753198092Srdivacky struct __builtin_CFString { 1754198092Srdivacky const int *isa; // point to __CFConstantStringClassReference 1755198092Srdivacky int flags; 1756198092Srdivacky const char *str; 1757198092Srdivacky long length; 1758198092Srdivacky }; 1759193326Sed*/ 1760193326Sed 1761207619Srdivacky/// or Generate a constant NSString object. 1762207619Srdivacky/* 1763207619Srdivacky struct __builtin_NSString { 1764207619Srdivacky const int *isa; // point to __NSConstantStringClassReference 1765207619Srdivacky const char *str; 1766207619Srdivacky unsigned int length; 1767207619Srdivacky }; 1768207619Srdivacky*/ 1769207619Srdivacky 1770193326Sedllvm::Constant *CGObjCCommonMac::GenerateConstantString( 1771202879Srdivacky const StringLiteral *SL) { 1772234353Sdim return (CGM.getLangOpts().NoConstantCFStrings == 0 ? 1773207619Srdivacky CGM.GetAddrOfConstantCFString(SL) : 1774218893Sdim CGM.GetAddrOfConstantString(SL)); 1775193326Sed} 1776193326Sed 1777234353Sdimenum { 1778234353Sdim kCFTaggedObjectID_Integer = (1 << 1) + 1 1779234353Sdim}; 1780234353Sdim 1781193326Sed/// Generates a message send where the super is the receiver. This is 1782193326Sed/// a message send to self with special delivery semantics indicating 1783193326Sed/// which class's method should be called. 1784193326SedCodeGen::RValue 1785193326SedCGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1786208600Srdivacky ReturnValueSlot Return, 1787193326Sed QualType ResultType, 1788193326Sed Selector Sel, 1789193326Sed const ObjCInterfaceDecl *Class, 1790193326Sed bool isCategoryImpl, 1791193326Sed llvm::Value *Receiver, 1792193326Sed bool IsClassMessage, 1793198092Srdivacky const CodeGen::CallArgList &CallArgs, 1794198092Srdivacky const ObjCMethodDecl *Method) { 1795193326Sed // Create and init a super structure; this is a (receiver, class) 1796193326Sed // pair we will pass to objc_msgSendSuper. 1797198092Srdivacky llvm::Value *ObjCSuper = 1798221345Sdim CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super"); 1799198092Srdivacky llvm::Value *ReceiverAsObject = 1800193326Sed CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); 1801198092Srdivacky CGF.Builder.CreateStore(ReceiverAsObject, 1802193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 1803193326Sed 1804193326Sed // If this is a class message the metaclass is passed as the target. 1805193326Sed llvm::Value *Target; 1806193326Sed if (IsClassMessage) { 1807193326Sed if (isCategoryImpl) { 1808193326Sed // Message sent to 'super' in a class method defined in a category 1809193326Sed // implementation requires an odd treatment. 1810193326Sed // If we are in a class method, we must retrieve the 1811193326Sed // _metaclass_ for the current class, pointed at by 1812193326Sed // the class's "isa" pointer. The following assumes that 1813193326Sed // isa" is the first ivar in a class (which it must be). 1814249423Sdim Target = EmitClassRef(CGF, Class->getSuperClass()); 1815193326Sed Target = CGF.Builder.CreateStructGEP(Target, 0); 1816193326Sed Target = CGF.Builder.CreateLoad(Target); 1817198092Srdivacky } else { 1818193326Sed llvm::Value *MetaClassPtr = EmitMetaClassRef(Class); 1819193326Sed llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1); 1820193326Sed llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr); 1821193326Sed Target = Super; 1822198092Srdivacky } 1823199482Srdivacky } 1824199482Srdivacky else if (isCategoryImpl) 1825249423Sdim Target = EmitClassRef(CGF, Class->getSuperClass()); 1826199482Srdivacky else { 1827199482Srdivacky llvm::Value *ClassPtr = EmitSuperClassRef(Class); 1828199482Srdivacky ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1); 1829199482Srdivacky Target = CGF.Builder.CreateLoad(ClassPtr); 1830193326Sed } 1831193326Sed // FIXME: We shouldn't need to do this cast, rectify the ASTContext and 1832193326Sed // ObjCTypes types. 1833226633Sdim llvm::Type *ClassTy = 1834193326Sed CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); 1835193326Sed Target = CGF.Builder.CreateBitCast(Target, ClassTy); 1836198092Srdivacky CGF.Builder.CreateStore(Target, 1837193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 1838223017Sdim return EmitMessageSend(CGF, Return, ResultType, 1839249423Sdim EmitSelector(CGF, Sel), 1840223017Sdim ObjCSuper, ObjCTypes.SuperPtrCTy, 1841223017Sdim true, CallArgs, Method, ObjCTypes); 1842193326Sed} 1843198092Srdivacky 1844198092Srdivacky/// Generate code for a message send expression. 1845193326SedCodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1846208600Srdivacky ReturnValueSlot Return, 1847193326Sed QualType ResultType, 1848193326Sed Selector Sel, 1849193326Sed llvm::Value *Receiver, 1850193326Sed const CallArgList &CallArgs, 1851207619Srdivacky const ObjCInterfaceDecl *Class, 1852193326Sed const ObjCMethodDecl *Method) { 1853223017Sdim return EmitMessageSend(CGF, Return, ResultType, 1854249423Sdim EmitSelector(CGF, Sel), 1855223017Sdim Receiver, CGF.getContext().getObjCIdType(), 1856223017Sdim false, CallArgs, Method, ObjCTypes); 1857193326Sed} 1858193326Sed 1859198092SrdivackyCodeGen::RValue 1860223017SdimCGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, 1861223017Sdim ReturnValueSlot Return, 1862223017Sdim QualType ResultType, 1863223017Sdim llvm::Value *Sel, 1864223017Sdim llvm::Value *Arg0, 1865223017Sdim QualType Arg0Ty, 1866223017Sdim bool IsSuper, 1867223017Sdim const CallArgList &CallArgs, 1868223017Sdim const ObjCMethodDecl *Method, 1869223017Sdim const ObjCCommonTypesHelper &ObjCTypes) { 1870193326Sed CallArgList ActualArgs; 1871193326Sed if (!IsSuper) 1872226633Sdim Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy); 1873221345Sdim ActualArgs.add(RValue::get(Arg0), Arg0Ty); 1874221345Sdim ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType()); 1875224145Sdim ActualArgs.addFrom(CallArgs); 1876198092Srdivacky 1877234353Sdim // If we're calling a method, use the formal signature. 1878234353Sdim MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs); 1879198092Srdivacky 1880210299Sed if (Method) 1881210299Sed assert(CGM.getContext().getCanonicalType(Method->getResultType()) == 1882210299Sed CGM.getContext().getCanonicalType(ResultType) && 1883210299Sed "Result type mismatch!"); 1884210299Sed 1885223017Sdim NullReturnState nullReturn; 1886223017Sdim 1887193326Sed llvm::Constant *Fn = NULL; 1888234353Sdim if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) { 1889223017Sdim if (!IsSuper) nullReturn.init(CGF, Arg0); 1890193326Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) 1891198092Srdivacky : ObjCTypes.getSendStretFn(IsSuper); 1892210299Sed } else if (CGM.ReturnTypeUsesFPRet(ResultType)) { 1893210299Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper) 1894210299Sed : ObjCTypes.getSendFpretFn(IsSuper); 1895234353Sdim } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) { 1896234353Sdim Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper) 1897234353Sdim : ObjCTypes.getSendFp2retFn(IsSuper); 1898193326Sed } else { 1899193326Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper) 1900198092Srdivacky : ObjCTypes.getSendFn(IsSuper); 1901193326Sed } 1902234353Sdim 1903234353Sdim bool requiresnullCheck = false; 1904234353Sdim if (CGM.getLangOpts().ObjCAutoRefCount && Method) 1905234353Sdim for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(), 1906234353Sdim e = Method->param_end(); i != e; ++i) { 1907234353Sdim const ParmVarDecl *ParamDecl = (*i); 1908234353Sdim if (ParamDecl->hasAttr<NSConsumedAttr>()) { 1909234353Sdim if (!nullReturn.NullBB) 1910234353Sdim nullReturn.init(CGF, Arg0); 1911234353Sdim requiresnullCheck = true; 1912234353Sdim break; 1913234353Sdim } 1914234353Sdim } 1915234353Sdim 1916234353Sdim Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType); 1917234353Sdim RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs); 1918234353Sdim return nullReturn.complete(CGF, rvalue, ResultType, CallArgs, 1919234353Sdim requiresnullCheck ? Method : 0); 1920193326Sed} 1921193326Sed 1922212904Sdimstatic Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) { 1923212904Sdim if (FQT.isObjCGCStrong()) 1924212904Sdim return Qualifiers::Strong; 1925212904Sdim 1926224145Sdim if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak) 1927212904Sdim return Qualifiers::Weak; 1928212904Sdim 1929234353Sdim // check for __unsafe_unretained 1930234353Sdim if (FQT.getObjCLifetime() == Qualifiers::OCL_ExplicitNone) 1931234353Sdim return Qualifiers::GCNone; 1932234353Sdim 1933212904Sdim if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) 1934212904Sdim return Qualifiers::Strong; 1935212904Sdim 1936212904Sdim if (const PointerType *PT = FQT->getAs<PointerType>()) 1937212904Sdim return GetGCAttrTypeForType(Ctx, PT->getPointeeType()); 1938212904Sdim 1939212904Sdim return Qualifiers::GCNone; 1940212904Sdim} 1941212904Sdim 1942218893Sdimllvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, 1943218893Sdim const CGBlockInfo &blockInfo) { 1944243830Sdim 1945234353Sdim llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); 1946234353Sdim if (CGM.getLangOpts().getGC() == LangOptions::NonGC && 1947234353Sdim !CGM.getLangOpts().ObjCAutoRefCount) 1948218893Sdim return nullPtr; 1949218893Sdim 1950212904Sdim bool hasUnion = false; 1951212904Sdim SkipIvars.clear(); 1952212904Sdim IvarsInfo.clear(); 1953251662Sdim unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); 1954251662Sdim unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); 1955212904Sdim 1956218893Sdim // __isa is the first field in block descriptor and must assume by runtime's 1957218893Sdim // convention that it is GC'able. 1958218893Sdim IvarsInfo.push_back(GC_IVAR(0, 1)); 1959218893Sdim 1960218893Sdim const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1961218893Sdim 1962218893Sdim // Calculate the basic layout of the block structure. 1963218893Sdim const llvm::StructLayout *layout = 1964243830Sdim CGM.getDataLayout().getStructLayout(blockInfo.StructureType); 1965218893Sdim 1966218893Sdim // Ignore the optional 'this' capture: C++ objects are not assumed 1967218893Sdim // to be GC'ed. 1968218893Sdim 1969218893Sdim // Walk the captured variables. 1970218893Sdim for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1971218893Sdim ce = blockDecl->capture_end(); ci != ce; ++ci) { 1972218893Sdim const VarDecl *variable = ci->getVariable(); 1973218893Sdim QualType type = variable->getType(); 1974218893Sdim 1975218893Sdim const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1976218893Sdim 1977218893Sdim // Ignore constant captures. 1978218893Sdim if (capture.isConstant()) continue; 1979218893Sdim 1980218893Sdim uint64_t fieldOffset = layout->getElementOffset(capture.getIndex()); 1981218893Sdim 1982218893Sdim // __block variables are passed by their descriptor address. 1983218893Sdim if (ci->isByRef()) { 1984218893Sdim IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1)); 1985212904Sdim continue; 1986212904Sdim } 1987218893Sdim 1988218893Sdim assert(!type->isArrayType() && "array variable should not be caught"); 1989218893Sdim if (const RecordType *record = type->getAs<RecordType>()) { 1990218893Sdim BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion); 1991218893Sdim continue; 1992218893Sdim } 1993212904Sdim 1994218893Sdim Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type); 1995218893Sdim unsigned fieldSize = CGM.getContext().getTypeSize(type); 1996218893Sdim 1997218893Sdim if (GCAttr == Qualifiers::Strong) 1998218893Sdim IvarsInfo.push_back(GC_IVAR(fieldOffset, 1999218893Sdim fieldSize / WordSizeInBits)); 2000212904Sdim else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak) 2001218893Sdim SkipIvars.push_back(GC_IVAR(fieldOffset, 2002218893Sdim fieldSize / ByteSizeInBits)); 2003212904Sdim } 2004212904Sdim 2005212904Sdim if (IvarsInfo.empty()) 2006218893Sdim return nullPtr; 2007218893Sdim 2008218893Sdim // Sort on byte position; captures might not be allocated in order, 2009218893Sdim // and unions can do funny things. 2010218893Sdim llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end()); 2011218893Sdim llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end()); 2012212904Sdim 2013212904Sdim std::string BitMap; 2014212904Sdim llvm::Constant *C = BuildIvarLayoutBitmap(BitMap); 2015234353Sdim if (CGM.getLangOpts().ObjCGCBitmapPrint) { 2016212904Sdim printf("\n block variable layout for block: "); 2017243830Sdim const unsigned char *s = (const unsigned char*)BitMap.c_str(); 2018234353Sdim for (unsigned i = 0, e = BitMap.size(); i < e; i++) 2019212904Sdim if (!(s[i] & 0xf0)) 2020212904Sdim printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); 2021212904Sdim else 2022212904Sdim printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); 2023212904Sdim printf("\n"); 2024212904Sdim } 2025212904Sdim 2026212904Sdim return C; 2027212904Sdim} 2028212904Sdim 2029243830Sdim/// getBlockCaptureLifetime - This routine returns life time of the captured 2030243830Sdim/// block variable for the purpose of block layout meta-data generation. FQT is 2031243830Sdim/// the type of the variable captured in the block. 2032249423SdimQualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT, 2033249423Sdim bool ByrefLayout) { 2034243830Sdim if (CGM.getLangOpts().ObjCAutoRefCount) 2035243830Sdim return FQT.getObjCLifetime(); 2036243830Sdim 2037243830Sdim // MRR. 2038243830Sdim if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) 2039249423Sdim return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong; 2040243830Sdim 2041243830Sdim return Qualifiers::OCL_None; 2042243830Sdim} 2043243830Sdim 2044243830Sdimvoid CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref, 2045243830Sdim Qualifiers::ObjCLifetime LifeTime, 2046243830Sdim CharUnits FieldOffset, 2047243830Sdim CharUnits FieldSize) { 2048243830Sdim // __block variables are passed by their descriptor address. 2049243830Sdim if (IsByref) 2050243830Sdim RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, 2051243830Sdim FieldSize)); 2052243830Sdim else if (LifeTime == Qualifiers::OCL_Strong) 2053243830Sdim RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, 2054243830Sdim FieldSize)); 2055243830Sdim else if (LifeTime == Qualifiers::OCL_Weak) 2056243830Sdim RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, 2057243830Sdim FieldSize)); 2058243830Sdim else if (LifeTime == Qualifiers::OCL_ExplicitNone) 2059243830Sdim RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, 2060243830Sdim FieldSize)); 2061243830Sdim else 2062243830Sdim RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, 2063243830Sdim FieldOffset, 2064243830Sdim FieldSize)); 2065243830Sdim} 2066243830Sdim 2067243830Sdimvoid CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, 2068243830Sdim const RecordDecl *RD, 2069243830Sdim ArrayRef<const FieldDecl*> RecFields, 2070249423Sdim CharUnits BytePos, bool &HasUnion, 2071249423Sdim bool ByrefLayout) { 2072243830Sdim bool IsUnion = (RD && RD->isUnion()); 2073243830Sdim CharUnits MaxUnionSize = CharUnits::Zero(); 2074243830Sdim const FieldDecl *MaxField = 0; 2075243830Sdim const FieldDecl *LastFieldBitfieldOrUnnamed = 0; 2076243830Sdim CharUnits MaxFieldOffset = CharUnits::Zero(); 2077243830Sdim CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero(); 2078243830Sdim 2079243830Sdim if (RecFields.empty()) 2080243830Sdim return; 2081251662Sdim unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); 2082243830Sdim 2083243830Sdim for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { 2084243830Sdim const FieldDecl *Field = RecFields[i]; 2085243830Sdim // Note that 'i' here is actually the field index inside RD of Field, 2086243830Sdim // although this dependency is hidden. 2087243830Sdim const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); 2088243830Sdim CharUnits FieldOffset = 2089243830Sdim CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i)); 2090243830Sdim 2091243830Sdim // Skip over unnamed or bitfields 2092243830Sdim if (!Field->getIdentifier() || Field->isBitField()) { 2093243830Sdim LastFieldBitfieldOrUnnamed = Field; 2094243830Sdim LastBitfieldOrUnnamedOffset = FieldOffset; 2095243830Sdim continue; 2096243830Sdim } 2097243830Sdim 2098243830Sdim LastFieldBitfieldOrUnnamed = 0; 2099243830Sdim QualType FQT = Field->getType(); 2100243830Sdim if (FQT->isRecordType() || FQT->isUnionType()) { 2101243830Sdim if (FQT->isUnionType()) 2102243830Sdim HasUnion = true; 2103243830Sdim 2104243830Sdim BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(), 2105243830Sdim BytePos + FieldOffset, HasUnion); 2106243830Sdim continue; 2107243830Sdim } 2108243830Sdim 2109243830Sdim if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 2110243830Sdim const ConstantArrayType *CArray = 2111243830Sdim dyn_cast_or_null<ConstantArrayType>(Array); 2112243830Sdim uint64_t ElCount = CArray->getSize().getZExtValue(); 2113243830Sdim assert(CArray && "only array with known element size is supported"); 2114243830Sdim FQT = CArray->getElementType(); 2115243830Sdim while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 2116243830Sdim const ConstantArrayType *CArray = 2117243830Sdim dyn_cast_or_null<ConstantArrayType>(Array); 2118243830Sdim ElCount *= CArray->getSize().getZExtValue(); 2119243830Sdim FQT = CArray->getElementType(); 2120243830Sdim } 2121243830Sdim 2122243830Sdim assert(!FQT->isUnionType() && 2123243830Sdim "layout for array of unions not supported"); 2124243830Sdim if (FQT->isRecordType() && ElCount) { 2125243830Sdim int OldIndex = RunSkipBlockVars.size() - 1; 2126243830Sdim const RecordType *RT = FQT->getAs<RecordType>(); 2127243830Sdim BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, 2128243830Sdim HasUnion); 2129243830Sdim 2130243830Sdim // Replicate layout information for each array element. Note that 2131243830Sdim // one element is already done. 2132243830Sdim uint64_t ElIx = 1; 2133243830Sdim for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) { 2134243830Sdim CharUnits Size = CGM.getContext().getTypeSizeInChars(RT); 2135243830Sdim for (int i = OldIndex+1; i <= FirstIndex; ++i) 2136243830Sdim RunSkipBlockVars.push_back( 2137243830Sdim RUN_SKIP(RunSkipBlockVars[i].opcode, 2138243830Sdim RunSkipBlockVars[i].block_var_bytepos + Size*ElIx, 2139243830Sdim RunSkipBlockVars[i].block_var_size)); 2140243830Sdim } 2141243830Sdim continue; 2142243830Sdim } 2143243830Sdim } 2144243830Sdim CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType()); 2145243830Sdim if (IsUnion) { 2146243830Sdim CharUnits UnionIvarSize = FieldSize; 2147243830Sdim if (UnionIvarSize > MaxUnionSize) { 2148243830Sdim MaxUnionSize = UnionIvarSize; 2149243830Sdim MaxField = Field; 2150243830Sdim MaxFieldOffset = FieldOffset; 2151243830Sdim } 2152243830Sdim } else { 2153243830Sdim UpdateRunSkipBlockVars(false, 2154249423Sdim getBlockCaptureLifetime(FQT, ByrefLayout), 2155243830Sdim BytePos + FieldOffset, 2156243830Sdim FieldSize); 2157243830Sdim } 2158243830Sdim } 2159243830Sdim 2160243830Sdim if (LastFieldBitfieldOrUnnamed) { 2161243830Sdim if (LastFieldBitfieldOrUnnamed->isBitField()) { 2162243830Sdim // Last field was a bitfield. Must update the info. 2163243830Sdim uint64_t BitFieldSize 2164243830Sdim = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext()); 2165243830Sdim unsigned UnsSize = (BitFieldSize / ByteSizeInBits) + 2166243830Sdim ((BitFieldSize % ByteSizeInBits) != 0); 2167243830Sdim CharUnits Size = CharUnits::fromQuantity(UnsSize); 2168243830Sdim Size += LastBitfieldOrUnnamedOffset; 2169243830Sdim UpdateRunSkipBlockVars(false, 2170249423Sdim getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(), 2171249423Sdim ByrefLayout), 2172243830Sdim BytePos + LastBitfieldOrUnnamedOffset, 2173243830Sdim Size); 2174243830Sdim } else { 2175243830Sdim assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed"); 2176243830Sdim // Last field was unnamed. Must update skip info. 2177243830Sdim CharUnits FieldSize 2178243830Sdim = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType()); 2179243830Sdim UpdateRunSkipBlockVars(false, 2180249423Sdim getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(), 2181249423Sdim ByrefLayout), 2182243830Sdim BytePos + LastBitfieldOrUnnamedOffset, 2183243830Sdim FieldSize); 2184243830Sdim } 2185243830Sdim } 2186243830Sdim 2187243830Sdim if (MaxField) 2188243830Sdim UpdateRunSkipBlockVars(false, 2189249423Sdim getBlockCaptureLifetime(MaxField->getType(), ByrefLayout), 2190243830Sdim BytePos + MaxFieldOffset, 2191243830Sdim MaxUnionSize); 2192243830Sdim} 2193243830Sdim 2194243830Sdimvoid CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT, 2195243830Sdim CharUnits BytePos, 2196249423Sdim bool &HasUnion, 2197249423Sdim bool ByrefLayout) { 2198243830Sdim const RecordDecl *RD = RT->getDecl(); 2199243830Sdim SmallVector<const FieldDecl*, 16> Fields; 2200243830Sdim for (RecordDecl::field_iterator i = RD->field_begin(), 2201243830Sdim e = RD->field_end(); i != e; ++i) 2202243830Sdim Fields.push_back(*i); 2203243830Sdim llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); 2204243830Sdim const llvm::StructLayout *RecLayout = 2205243830Sdim CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty)); 2206243830Sdim 2207249423Sdim BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout); 2208243830Sdim} 2209243830Sdim 2210243830Sdim/// InlineLayoutInstruction - This routine produce an inline instruction for the 2211243830Sdim/// block variable layout if it can. If not, it returns 0. Rules are as follow: 2212243830Sdim/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world, 2213243830Sdim/// an inline layout of value 0x0000000000000xyz is interpreted as follows: 2214243830Sdim/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by 2215243830Sdim/// y captured object of BLOCK_LAYOUT_BYREF. Followed by 2216243830Sdim/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero 2217243830Sdim/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no 2218243830Sdim/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured. 2219243830Sdimuint64_t CGObjCCommonMac::InlineLayoutInstruction( 2220243830Sdim SmallVectorImpl<unsigned char> &Layout) { 2221243830Sdim uint64_t Result = 0; 2222243830Sdim if (Layout.size() <= 3) { 2223243830Sdim unsigned size = Layout.size(); 2224243830Sdim unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0; 2225243830Sdim unsigned char inst; 2226243830Sdim enum BLOCK_LAYOUT_OPCODE opcode ; 2227243830Sdim switch (size) { 2228243830Sdim case 3: 2229243830Sdim inst = Layout[0]; 2230243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2231243830Sdim if (opcode == BLOCK_LAYOUT_STRONG) 2232243830Sdim strong_word_count = (inst & 0xF)+1; 2233243830Sdim else 2234243830Sdim return 0; 2235243830Sdim inst = Layout[1]; 2236243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2237243830Sdim if (opcode == BLOCK_LAYOUT_BYREF) 2238243830Sdim byref_word_count = (inst & 0xF)+1; 2239243830Sdim else 2240243830Sdim return 0; 2241243830Sdim inst = Layout[2]; 2242243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2243243830Sdim if (opcode == BLOCK_LAYOUT_WEAK) 2244243830Sdim weak_word_count = (inst & 0xF)+1; 2245243830Sdim else 2246243830Sdim return 0; 2247243830Sdim break; 2248243830Sdim 2249243830Sdim case 2: 2250243830Sdim inst = Layout[0]; 2251243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2252243830Sdim if (opcode == BLOCK_LAYOUT_STRONG) { 2253243830Sdim strong_word_count = (inst & 0xF)+1; 2254243830Sdim inst = Layout[1]; 2255243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2256243830Sdim if (opcode == BLOCK_LAYOUT_BYREF) 2257243830Sdim byref_word_count = (inst & 0xF)+1; 2258243830Sdim else if (opcode == BLOCK_LAYOUT_WEAK) 2259243830Sdim weak_word_count = (inst & 0xF)+1; 2260243830Sdim else 2261243830Sdim return 0; 2262243830Sdim } 2263243830Sdim else if (opcode == BLOCK_LAYOUT_BYREF) { 2264243830Sdim byref_word_count = (inst & 0xF)+1; 2265243830Sdim inst = Layout[1]; 2266243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2267243830Sdim if (opcode == BLOCK_LAYOUT_WEAK) 2268243830Sdim weak_word_count = (inst & 0xF)+1; 2269243830Sdim else 2270243830Sdim return 0; 2271243830Sdim } 2272243830Sdim else 2273243830Sdim return 0; 2274243830Sdim break; 2275243830Sdim 2276243830Sdim case 1: 2277243830Sdim inst = Layout[0]; 2278243830Sdim opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2279243830Sdim if (opcode == BLOCK_LAYOUT_STRONG) 2280243830Sdim strong_word_count = (inst & 0xF)+1; 2281243830Sdim else if (opcode == BLOCK_LAYOUT_BYREF) 2282243830Sdim byref_word_count = (inst & 0xF)+1; 2283243830Sdim else if (opcode == BLOCK_LAYOUT_WEAK) 2284243830Sdim weak_word_count = (inst & 0xF)+1; 2285243830Sdim else 2286243830Sdim return 0; 2287243830Sdim break; 2288243830Sdim 2289243830Sdim default: 2290243830Sdim return 0; 2291243830Sdim } 2292243830Sdim 2293243830Sdim // Cannot inline when any of the word counts is 15. Because this is one less 2294243830Sdim // than the actual work count (so 15 means 16 actual word counts), 2295243830Sdim // and we can only display 0 thru 15 word counts. 2296243830Sdim if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16) 2297243830Sdim return 0; 2298243830Sdim 2299243830Sdim unsigned count = 2300243830Sdim (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0); 2301243830Sdim 2302243830Sdim if (size == count) { 2303243830Sdim if (strong_word_count) 2304243830Sdim Result = strong_word_count; 2305243830Sdim Result <<= 4; 2306243830Sdim if (byref_word_count) 2307243830Sdim Result += byref_word_count; 2308243830Sdim Result <<= 4; 2309243830Sdim if (weak_word_count) 2310243830Sdim Result += weak_word_count; 2311243830Sdim } 2312243830Sdim } 2313243830Sdim return Result; 2314243830Sdim} 2315243830Sdim 2316249423Sdimllvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) { 2317243830Sdim llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); 2318249423Sdim if (RunSkipBlockVars.empty()) 2319249423Sdim return nullPtr; 2320251662Sdim unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); 2321251662Sdim unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); 2322243830Sdim unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; 2323243830Sdim 2324243830Sdim // Sort on byte position; captures might not be allocated in order, 2325243830Sdim // and unions can do funny things. 2326243830Sdim llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end()); 2327243830Sdim SmallVector<unsigned char, 16> Layout; 2328249423Sdim 2329243830Sdim unsigned size = RunSkipBlockVars.size(); 2330243830Sdim for (unsigned i = 0; i < size; i++) { 2331243830Sdim enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode; 2332243830Sdim CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos; 2333243830Sdim CharUnits end_byte_pos = start_byte_pos; 2334243830Sdim unsigned j = i+1; 2335243830Sdim while (j < size) { 2336243830Sdim if (opcode == RunSkipBlockVars[j].opcode) { 2337243830Sdim end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos; 2338243830Sdim i++; 2339243830Sdim } 2340243830Sdim else 2341243830Sdim break; 2342243830Sdim } 2343243830Sdim CharUnits size_in_bytes = 2344249423Sdim end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size; 2345243830Sdim if (j < size) { 2346243830Sdim CharUnits gap = 2347249423Sdim RunSkipBlockVars[j].block_var_bytepos - 2348249423Sdim RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size; 2349243830Sdim size_in_bytes += gap; 2350243830Sdim } 2351243830Sdim CharUnits residue_in_bytes = CharUnits::Zero(); 2352243830Sdim if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) { 2353243830Sdim residue_in_bytes = size_in_bytes % WordSizeInBytes; 2354243830Sdim size_in_bytes -= residue_in_bytes; 2355243830Sdim opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS; 2356243830Sdim } 2357249423Sdim 2358243830Sdim unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes; 2359243830Sdim while (size_in_words >= 16) { 2360243830Sdim // Note that value in imm. is one less that the actual 2361243830Sdim // value. So, 0xf means 16 words follow! 2362243830Sdim unsigned char inst = (opcode << 4) | 0xf; 2363243830Sdim Layout.push_back(inst); 2364243830Sdim size_in_words -= 16; 2365243830Sdim } 2366243830Sdim if (size_in_words > 0) { 2367243830Sdim // Note that value in imm. is one less that the actual 2368243830Sdim // value. So, we subtract 1 away! 2369243830Sdim unsigned char inst = (opcode << 4) | (size_in_words-1); 2370243830Sdim Layout.push_back(inst); 2371243830Sdim } 2372243830Sdim if (residue_in_bytes > CharUnits::Zero()) { 2373243830Sdim unsigned char inst = 2374249423Sdim (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1); 2375243830Sdim Layout.push_back(inst); 2376243830Sdim } 2377243830Sdim } 2378243830Sdim 2379243830Sdim int e = Layout.size()-1; 2380243830Sdim while (e >= 0) { 2381243830Sdim unsigned char inst = Layout[e--]; 2382243830Sdim enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2383243830Sdim if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS) 2384243830Sdim Layout.pop_back(); 2385243830Sdim else 2386243830Sdim break; 2387243830Sdim } 2388243830Sdim 2389243830Sdim uint64_t Result = InlineLayoutInstruction(Layout); 2390243830Sdim if (Result != 0) { 2391243830Sdim // Block variable layout instruction has been inlined. 2392243830Sdim if (CGM.getLangOpts().ObjCGCBitmapPrint) { 2393249423Sdim if (ComputeByrefLayout) 2394249423Sdim printf("\n Inline instruction for BYREF variable layout: "); 2395249423Sdim else 2396249423Sdim printf("\n Inline instruction for block variable layout: "); 2397251662Sdim printf("0x0%" PRIx64 "\n", Result); 2398243830Sdim } 2399243830Sdim if (WordSizeInBytes == 8) { 2400243830Sdim const llvm::APInt Instruction(64, Result); 2401243830Sdim return llvm::Constant::getIntegerValue(CGM.Int64Ty, Instruction); 2402243830Sdim } 2403243830Sdim else { 2404243830Sdim const llvm::APInt Instruction(32, Result); 2405243830Sdim return llvm::Constant::getIntegerValue(CGM.Int32Ty, Instruction); 2406243830Sdim } 2407243830Sdim } 2408243830Sdim 2409243830Sdim unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0; 2410243830Sdim Layout.push_back(inst); 2411243830Sdim std::string BitMap; 2412243830Sdim for (unsigned i = 0, e = Layout.size(); i != e; i++) 2413243830Sdim BitMap += Layout[i]; 2414243830Sdim 2415243830Sdim if (CGM.getLangOpts().ObjCGCBitmapPrint) { 2416249423Sdim if (ComputeByrefLayout) 2417249423Sdim printf("\n BYREF variable layout: "); 2418249423Sdim else 2419249423Sdim printf("\n block variable layout: "); 2420243830Sdim for (unsigned i = 0, e = BitMap.size(); i != e; i++) { 2421243830Sdim unsigned char inst = BitMap[i]; 2422243830Sdim enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); 2423243830Sdim unsigned delta = 1; 2424243830Sdim switch (opcode) { 2425243830Sdim case BLOCK_LAYOUT_OPERATOR: 2426243830Sdim printf("BL_OPERATOR:"); 2427243830Sdim delta = 0; 2428243830Sdim break; 2429243830Sdim case BLOCK_LAYOUT_NON_OBJECT_BYTES: 2430243830Sdim printf("BL_NON_OBJECT_BYTES:"); 2431243830Sdim break; 2432243830Sdim case BLOCK_LAYOUT_NON_OBJECT_WORDS: 2433243830Sdim printf("BL_NON_OBJECT_WORD:"); 2434243830Sdim break; 2435243830Sdim case BLOCK_LAYOUT_STRONG: 2436243830Sdim printf("BL_STRONG:"); 2437243830Sdim break; 2438243830Sdim case BLOCK_LAYOUT_BYREF: 2439243830Sdim printf("BL_BYREF:"); 2440243830Sdim break; 2441243830Sdim case BLOCK_LAYOUT_WEAK: 2442243830Sdim printf("BL_WEAK:"); 2443243830Sdim break; 2444243830Sdim case BLOCK_LAYOUT_UNRETAINED: 2445243830Sdim printf("BL_UNRETAINED:"); 2446243830Sdim break; 2447249423Sdim } 2448243830Sdim // Actual value of word count is one more that what is in the imm. 2449243830Sdim // field of the instruction 2450249423Sdim printf("%d", (inst & 0xf) + delta); 2451243830Sdim if (i < e-1) 2452243830Sdim printf(", "); 2453243830Sdim else 2454243830Sdim printf("\n"); 2455243830Sdim } 2456243830Sdim } 2457243830Sdim 2458243830Sdim llvm::GlobalVariable * Entry = 2459249423Sdim CreateMetadataVar("\01L_OBJC_CLASS_NAME_", 2460243830Sdim llvm::ConstantDataArray::getString(VMContext, BitMap,false), 2461243830Sdim "__TEXT,__objc_classname,cstring_literals", 1, true); 2462243830Sdim return getConstantGEP(VMContext, Entry, 0, 0); 2463243830Sdim} 2464243830Sdim 2465249423Sdimllvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM, 2466249423Sdim const CGBlockInfo &blockInfo) { 2467249423Sdim assert(CGM.getLangOpts().getGC() == LangOptions::NonGC); 2468249423Sdim 2469249423Sdim RunSkipBlockVars.clear(); 2470249423Sdim bool hasUnion = false; 2471249423Sdim 2472251662Sdim unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); 2473251662Sdim unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); 2474249423Sdim unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; 2475249423Sdim 2476249423Sdim const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 2477249423Sdim 2478249423Sdim // Calculate the basic layout of the block structure. 2479249423Sdim const llvm::StructLayout *layout = 2480249423Sdim CGM.getDataLayout().getStructLayout(blockInfo.StructureType); 2481249423Sdim 2482249423Sdim // Ignore the optional 'this' capture: C++ objects are not assumed 2483249423Sdim // to be GC'ed. 2484249423Sdim if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero()) 2485249423Sdim UpdateRunSkipBlockVars(false, Qualifiers::OCL_None, 2486249423Sdim blockInfo.BlockHeaderForcedGapOffset, 2487249423Sdim blockInfo.BlockHeaderForcedGapSize); 2488249423Sdim // Walk the captured variables. 2489249423Sdim for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 2490249423Sdim ce = blockDecl->capture_end(); ci != ce; ++ci) { 2491249423Sdim const VarDecl *variable = ci->getVariable(); 2492249423Sdim QualType type = variable->getType(); 2493249423Sdim 2494249423Sdim const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 2495249423Sdim 2496249423Sdim // Ignore constant captures. 2497249423Sdim if (capture.isConstant()) continue; 2498249423Sdim 2499249423Sdim CharUnits fieldOffset = 2500249423Sdim CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex())); 2501249423Sdim 2502249423Sdim assert(!type->isArrayType() && "array variable should not be caught"); 2503249423Sdim if (!ci->isByRef()) 2504249423Sdim if (const RecordType *record = type->getAs<RecordType>()) { 2505249423Sdim BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion); 2506249423Sdim continue; 2507249423Sdim } 2508249423Sdim CharUnits fieldSize; 2509249423Sdim if (ci->isByRef()) 2510249423Sdim fieldSize = CharUnits::fromQuantity(WordSizeInBytes); 2511249423Sdim else 2512249423Sdim fieldSize = CGM.getContext().getTypeSizeInChars(type); 2513249423Sdim UpdateRunSkipBlockVars(ci->isByRef(), getBlockCaptureLifetime(type, false), 2514249423Sdim fieldOffset, fieldSize); 2515249423Sdim } 2516249423Sdim return getBitmapBlockLayout(false); 2517249423Sdim} 2518249423Sdim 2519249423Sdim 2520249423Sdimllvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM, 2521249423Sdim QualType T) { 2522249423Sdim assert(CGM.getLangOpts().getGC() == LangOptions::NonGC); 2523249423Sdim assert(!T->isArrayType() && "__block array variable should not be caught"); 2524249423Sdim CharUnits fieldOffset; 2525249423Sdim RunSkipBlockVars.clear(); 2526249423Sdim bool hasUnion = false; 2527249423Sdim if (const RecordType *record = T->getAs<RecordType>()) { 2528249423Sdim BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */); 2529249423Sdim llvm::Constant *Result = getBitmapBlockLayout(true); 2530249423Sdim return Result; 2531249423Sdim } 2532249423Sdim llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); 2533249423Sdim return nullPtr; 2534249423Sdim} 2535249423Sdim 2536249423Sdimllvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF, 2537193326Sed const ObjCProtocolDecl *PD) { 2538193326Sed // FIXME: I don't understand why gcc generates this, or where it is 2539193326Sed // resolved. Investigate. Its also wasteful to look this up over and over. 2540193326Sed LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); 2541193326Sed 2542193326Sed return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD), 2543234353Sdim ObjCTypes.getExternalProtocolPtrTy()); 2544193326Sed} 2545193326Sed 2546193326Sedvoid CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) { 2547193326Sed // FIXME: We shouldn't need this, the protocol decl should contain enough 2548193326Sed // information to tell us whether this was a declaration or a definition. 2549193326Sed DefinedProtocols.insert(PD->getIdentifier()); 2550193326Sed 2551193326Sed // If we have generated a forward reference to this protocol, emit 2552193326Sed // it now. Otherwise do nothing, the protocol objects are lazily 2553193326Sed // emitted. 2554198092Srdivacky if (Protocols.count(PD->getIdentifier())) 2555193326Sed GetOrEmitProtocol(PD); 2556193326Sed} 2557193326Sed 2558193326Sedllvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) { 2559193326Sed if (DefinedProtocols.count(PD->getIdentifier())) 2560193326Sed return GetOrEmitProtocol(PD); 2561223017Sdim 2562193326Sed return GetOrEmitProtocolRef(PD); 2563193326Sed} 2564193326Sed 2565193326Sed/* 2566198092Srdivacky// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions 2567198092Srdivackystruct _objc_protocol { 2568198092Srdivackystruct _objc_protocol_extension *isa; 2569198092Srdivackychar *protocol_name; 2570198092Srdivackystruct _objc_protocol_list *protocol_list; 2571198092Srdivackystruct _objc__method_prototype_list *instance_methods; 2572198092Srdivackystruct _objc__method_prototype_list *class_methods 2573198092Srdivacky}; 2574193326Sed 2575198092SrdivackySee EmitProtocolExtension(). 2576193326Sed*/ 2577193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { 2578234353Sdim llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()]; 2579193326Sed 2580193326Sed // Early exit if a defining object has already been generated. 2581193326Sed if (Entry && Entry->hasInitializer()) 2582193326Sed return Entry; 2583193326Sed 2584234353Sdim // Use the protocol definition, if there is one. 2585234353Sdim if (const ObjCProtocolDecl *Def = PD->getDefinition()) 2586234353Sdim PD = Def; 2587234353Sdim 2588193326Sed // FIXME: I don't understand why gcc generates this, or where it is 2589193326Sed // resolved. Investigate. Its also wasteful to look this up over and over. 2590193326Sed LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); 2591193326Sed 2592193326Sed // Construct method lists. 2593193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 2594193326Sed std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; 2595234353Sdim std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt; 2596198092Srdivacky for (ObjCProtocolDecl::instmeth_iterator 2597195341Sed i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { 2598193326Sed ObjCMethodDecl *MD = *i; 2599193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 2600223017Sdim if (!C) 2601223017Sdim return GetOrEmitProtocolRef(PD); 2602223017Sdim 2603193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 2604193326Sed OptInstanceMethods.push_back(C); 2605234353Sdim OptMethodTypesExt.push_back(GetMethodVarType(MD, true)); 2606193326Sed } else { 2607193326Sed InstanceMethods.push_back(C); 2608234353Sdim MethodTypesExt.push_back(GetMethodVarType(MD, true)); 2609198092Srdivacky } 2610193326Sed } 2611193326Sed 2612198092Srdivacky for (ObjCProtocolDecl::classmeth_iterator 2613195341Sed i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { 2614193326Sed ObjCMethodDecl *MD = *i; 2615193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 2616223017Sdim if (!C) 2617223017Sdim return GetOrEmitProtocolRef(PD); 2618223017Sdim 2619193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 2620193326Sed OptClassMethods.push_back(C); 2621234353Sdim OptMethodTypesExt.push_back(GetMethodVarType(MD, true)); 2622193326Sed } else { 2623193326Sed ClassMethods.push_back(C); 2624234353Sdim MethodTypesExt.push_back(GetMethodVarType(MD, true)); 2625198092Srdivacky } 2626193326Sed } 2627193326Sed 2628234353Sdim MethodTypesExt.insert(MethodTypesExt.end(), 2629234353Sdim OptMethodTypesExt.begin(), OptMethodTypesExt.end()); 2630234353Sdim 2631234353Sdim llvm::Constant *Values[] = { 2632234353Sdim EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods, 2633234353Sdim MethodTypesExt), 2634234353Sdim GetClassName(PD->getIdentifier()), 2635198398Srdivacky EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(), 2636193326Sed PD->protocol_begin(), 2637234353Sdim PD->protocol_end()), 2638198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(), 2639193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 2640234353Sdim InstanceMethods), 2641198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(), 2642193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 2643234353Sdim ClassMethods) 2644234353Sdim }; 2645193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, 2646193326Sed Values); 2647198092Srdivacky 2648193326Sed if (Entry) { 2649193326Sed // Already created, fix the linkage and update the initializer. 2650193326Sed Entry->setLinkage(llvm::GlobalValue::InternalLinkage); 2651193326Sed Entry->setInitializer(Init); 2652193326Sed } else { 2653198092Srdivacky Entry = 2654198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, 2655193326Sed llvm::GlobalValue::InternalLinkage, 2656198092Srdivacky Init, 2657198398Srdivacky "\01L_OBJC_PROTOCOL_" + PD->getName()); 2658193326Sed Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); 2659193326Sed // FIXME: Is this necessary? Why only for protocol? 2660193326Sed Entry->setAlignment(4); 2661234353Sdim 2662234353Sdim Protocols[PD->getIdentifier()] = Entry; 2663193326Sed } 2664198092Srdivacky CGM.AddUsedGlobal(Entry); 2665193326Sed 2666193326Sed return Entry; 2667193326Sed} 2668193326Sed 2669193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { 2670193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 2671193326Sed 2672193326Sed if (!Entry) { 2673193326Sed // We use the initializer as a marker of whether this is a forward 2674193326Sed // reference or not. At module finalization we add the empty 2675193326Sed // contents for protocols which were referenced but never defined. 2676198092Srdivacky Entry = 2677198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, 2678193326Sed llvm::GlobalValue::ExternalLinkage, 2679193326Sed 0, 2680198398Srdivacky "\01L_OBJC_PROTOCOL_" + PD->getName()); 2681193326Sed Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); 2682193326Sed // FIXME: Is this necessary? Why only for protocol? 2683193326Sed Entry->setAlignment(4); 2684193326Sed } 2685198092Srdivacky 2686193326Sed return Entry; 2687193326Sed} 2688193326Sed 2689193326Sed/* 2690193326Sed struct _objc_protocol_extension { 2691198092Srdivacky uint32_t size; 2692198092Srdivacky struct objc_method_description_list *optional_instance_methods; 2693198092Srdivacky struct objc_method_description_list *optional_class_methods; 2694198092Srdivacky struct objc_property_list *instance_properties; 2695234353Sdim const char ** extendedMethodTypes; 2696193326Sed }; 2697193326Sed*/ 2698193326Sedllvm::Constant * 2699193326SedCGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, 2700234353Sdim ArrayRef<llvm::Constant*> OptInstanceMethods, 2701234353Sdim ArrayRef<llvm::Constant*> OptClassMethods, 2702234353Sdim ArrayRef<llvm::Constant*> MethodTypesExt) { 2703198092Srdivacky uint64_t Size = 2704243830Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); 2705234353Sdim llvm::Constant *Values[] = { 2706234353Sdim llvm::ConstantInt::get(ObjCTypes.IntTy, Size), 2707198092Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_" 2708198398Srdivacky + PD->getName(), 2709193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 2710234353Sdim OptInstanceMethods), 2711198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(), 2712193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 2713234353Sdim OptClassMethods), 2714234353Sdim EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD, 2715234353Sdim ObjCTypes), 2716234353Sdim EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(), 2717234353Sdim MethodTypesExt, ObjCTypes) 2718234353Sdim }; 2719193326Sed 2720193326Sed // Return null if no extension bits are used. 2721198092Srdivacky if (Values[1]->isNullValue() && Values[2]->isNullValue() && 2722234353Sdim Values[3]->isNullValue() && Values[4]->isNullValue()) 2723193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); 2724193326Sed 2725198092Srdivacky llvm::Constant *Init = 2726193326Sed llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values); 2727193326Sed 2728193326Sed // No special section, but goes in llvm.used 2729198398Srdivacky return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(), 2730198092Srdivacky Init, 2731193326Sed 0, 0, true); 2732193326Sed} 2733193326Sed 2734193326Sed/* 2735193326Sed struct objc_protocol_list { 2736234353Sdim struct objc_protocol_list *next; 2737234353Sdim long count; 2738234353Sdim Protocol *list[]; 2739193326Sed }; 2740193326Sed*/ 2741193326Sedllvm::Constant * 2742226633SdimCGObjCMac::EmitProtocolList(Twine Name, 2743193326Sed ObjCProtocolDecl::protocol_iterator begin, 2744193326Sed ObjCProtocolDecl::protocol_iterator end) { 2745249423Sdim SmallVector<llvm::Constant *, 16> ProtocolRefs; 2746193326Sed 2747193326Sed for (; begin != end; ++begin) 2748193326Sed ProtocolRefs.push_back(GetProtocolRef(*begin)); 2749193326Sed 2750193326Sed // Just return null for empty protocol lists 2751198092Srdivacky if (ProtocolRefs.empty()) 2752193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 2753193326Sed 2754193326Sed // This list is null terminated. 2755193326Sed ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy)); 2756193326Sed 2757224145Sdim llvm::Constant *Values[3]; 2758193326Sed // This field is only used by the runtime. 2759193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 2760198092Srdivacky Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, 2761198092Srdivacky ProtocolRefs.size() - 1); 2762198092Srdivacky Values[2] = 2763198092Srdivacky llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy, 2764198092Srdivacky ProtocolRefs.size()), 2765193326Sed ProtocolRefs); 2766198092Srdivacky 2767224145Sdim llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values); 2768198092Srdivacky llvm::GlobalVariable *GV = 2769193326Sed CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip", 2770193326Sed 4, false); 2771193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy); 2772193326Sed} 2773193326Sed 2774234353Sdimvoid CGObjCCommonMac:: 2775234353SdimPushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet, 2776249423Sdim SmallVectorImpl<llvm::Constant *> &Properties, 2777234353Sdim const Decl *Container, 2778234353Sdim const ObjCProtocolDecl *PROTO, 2779234353Sdim const ObjCCommonTypesHelper &ObjCTypes) { 2780200583Srdivacky for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(), 2781200583Srdivacky E = PROTO->protocol_end(); P != E; ++P) 2782200583Srdivacky PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes); 2783200583Srdivacky for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(), 2784200583Srdivacky E = PROTO->prop_end(); I != E; ++I) { 2785200583Srdivacky const ObjCPropertyDecl *PD = *I; 2786200583Srdivacky if (!PropertySet.insert(PD->getIdentifier())) 2787200583Srdivacky continue; 2788234353Sdim llvm::Constant *Prop[] = { 2789234353Sdim GetPropertyName(PD->getIdentifier()), 2790234353Sdim GetPropertyTypeString(PD, Container) 2791234353Sdim }; 2792200583Srdivacky Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop)); 2793200583Srdivacky } 2794200583Srdivacky} 2795200583Srdivacky 2796193326Sed/* 2797193326Sed struct _objc_property { 2798234353Sdim const char * const name; 2799234353Sdim const char * const attributes; 2800193326Sed }; 2801193326Sed 2802193326Sed struct _objc_property_list { 2803234353Sdim uint32_t entsize; // sizeof (struct _objc_property) 2804234353Sdim uint32_t prop_count; 2805234353Sdim struct _objc_property[prop_count]; 2806193326Sed }; 2807193326Sed*/ 2808226633Sdimllvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name, 2809198092Srdivacky const Decl *Container, 2810198092Srdivacky const ObjCContainerDecl *OCD, 2811198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 2812249423Sdim SmallVector<llvm::Constant *, 16> Properties; 2813200583Srdivacky llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet; 2814198092Srdivacky for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(), 2815198092Srdivacky E = OCD->prop_end(); I != E; ++I) { 2816193326Sed const ObjCPropertyDecl *PD = *I; 2817200583Srdivacky PropertySet.insert(PD->getIdentifier()); 2818234353Sdim llvm::Constant *Prop[] = { 2819234353Sdim GetPropertyName(PD->getIdentifier()), 2820234353Sdim GetPropertyTypeString(PD, Container) 2821234353Sdim }; 2822193326Sed Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, 2823193326Sed Prop)); 2824193326Sed } 2825210299Sed if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) { 2826212904Sdim for (ObjCInterfaceDecl::all_protocol_iterator 2827212904Sdim P = OID->all_referenced_protocol_begin(), 2828212904Sdim E = OID->all_referenced_protocol_end(); P != E; ++P) 2829210299Sed PushProtocolProperties(PropertySet, Properties, Container, (*P), 2830210299Sed ObjCTypes); 2831210299Sed } 2832210299Sed else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) { 2833210299Sed for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(), 2834210299Sed E = CD->protocol_end(); P != E; ++P) 2835210299Sed PushProtocolProperties(PropertySet, Properties, Container, (*P), 2836210299Sed ObjCTypes); 2837210299Sed } 2838193326Sed 2839193326Sed // Return null for empty list. 2840193326Sed if (Properties.empty()) 2841193326Sed return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 2842193326Sed 2843198092Srdivacky unsigned PropertySize = 2844243830Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy); 2845224145Sdim llvm::Constant *Values[3]; 2846193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize); 2847193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size()); 2848198092Srdivacky llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy, 2849193326Sed Properties.size()); 2850193326Sed Values[2] = llvm::ConstantArray::get(AT, Properties); 2851224145Sdim llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values); 2852193326Sed 2853198092Srdivacky llvm::GlobalVariable *GV = 2854198092Srdivacky CreateMetadataVar(Name, Init, 2855198092Srdivacky (ObjCABI == 2) ? "__DATA, __objc_const" : 2856193326Sed "__OBJC,__property,regular,no_dead_strip", 2857198092Srdivacky (ObjCABI == 2) ? 8 : 4, 2858193326Sed true); 2859193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy); 2860193326Sed} 2861193326Sed 2862234353Sdimllvm::Constant * 2863234353SdimCGObjCCommonMac::EmitProtocolMethodTypes(Twine Name, 2864234353Sdim ArrayRef<llvm::Constant*> MethodTypes, 2865234353Sdim const ObjCCommonTypesHelper &ObjCTypes) { 2866234353Sdim // Return null for empty list. 2867234353Sdim if (MethodTypes.empty()) 2868234353Sdim return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy); 2869234353Sdim 2870234353Sdim llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 2871234353Sdim MethodTypes.size()); 2872234353Sdim llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes); 2873234353Sdim 2874234353Sdim llvm::GlobalVariable *GV = 2875234353Sdim CreateMetadataVar(Name, Init, 2876234353Sdim (ObjCABI == 2) ? "__DATA, __objc_const" : 0, 2877234353Sdim (ObjCABI == 2) ? 8 : 4, 2878234353Sdim true); 2879234353Sdim return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy); 2880234353Sdim} 2881234353Sdim 2882193326Sed/* 2883193326Sed struct objc_method_description_list { 2884198092Srdivacky int count; 2885198092Srdivacky struct objc_method_description list[]; 2886193326Sed }; 2887193326Sed*/ 2888193326Sedllvm::Constant * 2889193326SedCGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { 2890234353Sdim llvm::Constant *Desc[] = { 2891198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 2892234353Sdim ObjCTypes.SelectorPtrTy), 2893234353Sdim GetMethodVarType(MD) 2894234353Sdim }; 2895223017Sdim if (!Desc[1]) 2896223017Sdim return 0; 2897223017Sdim 2898193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy, 2899193326Sed Desc); 2900193326Sed} 2901193326Sed 2902234353Sdimllvm::Constant * 2903234353SdimCGObjCMac::EmitMethodDescList(Twine Name, const char *Section, 2904234353Sdim ArrayRef<llvm::Constant*> Methods) { 2905193326Sed // Return null for empty list. 2906193326Sed if (Methods.empty()) 2907193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); 2908193326Sed 2909224145Sdim llvm::Constant *Values[2]; 2910193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 2911198092Srdivacky llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy, 2912193326Sed Methods.size()); 2913193326Sed Values[1] = llvm::ConstantArray::get(AT, Methods); 2914224145Sdim llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values); 2915193326Sed 2916193326Sed llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true); 2917198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, 2918193326Sed ObjCTypes.MethodDescriptionListPtrTy); 2919193326Sed} 2920193326Sed 2921193326Sed/* 2922193326Sed struct _objc_category { 2923198092Srdivacky char *category_name; 2924198092Srdivacky char *class_name; 2925198092Srdivacky struct _objc_method_list *instance_methods; 2926198092Srdivacky struct _objc_method_list *class_methods; 2927198092Srdivacky struct _objc_protocol_list *protocols; 2928198092Srdivacky uint32_t size; // <rdar://4585769> 2929198092Srdivacky struct _objc_property_list *instance_properties; 2930193326Sed }; 2931198092Srdivacky*/ 2932193326Sedvoid CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 2933243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy); 2934193326Sed 2935193326Sed // FIXME: This is poor design, the OCD should have a pointer to the category 2936193326Sed // decl. Additionally, note that Category can be null for the @implementation 2937193326Sed // w/o an @interface case. Sema should just create one for us as it does for 2938193326Sed // @implementation so everyone else can live life under a clear blue sky. 2939193326Sed const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); 2940198092Srdivacky const ObjCCategoryDecl *Category = 2941193326Sed Interface->FindCategoryDeclaration(OCD->getIdentifier()); 2942193326Sed 2943234353Sdim SmallString<256> ExtName; 2944198398Srdivacky llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_' 2945198398Srdivacky << OCD->getName(); 2946198398Srdivacky 2947249423Sdim SmallVector<llvm::Constant *, 16> InstanceMethods, ClassMethods; 2948198092Srdivacky for (ObjCCategoryImplDecl::instmeth_iterator 2949195341Sed i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { 2950193326Sed // Instance methods should always be defined. 2951193326Sed InstanceMethods.push_back(GetMethodConstant(*i)); 2952193326Sed } 2953198092Srdivacky for (ObjCCategoryImplDecl::classmeth_iterator 2954195341Sed i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { 2955193326Sed // Class methods should always be defined. 2956193326Sed ClassMethods.push_back(GetMethodConstant(*i)); 2957193326Sed } 2958193326Sed 2959224145Sdim llvm::Constant *Values[7]; 2960193326Sed Values[0] = GetClassName(OCD->getIdentifier()); 2961193326Sed Values[1] = GetClassName(Interface->getIdentifier()); 2962193326Sed LazySymbols.insert(Interface->getIdentifier()); 2963198092Srdivacky Values[2] = 2964198398Srdivacky EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(), 2965193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 2966193326Sed InstanceMethods); 2967198092Srdivacky Values[3] = 2968198398Srdivacky EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(), 2969193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 2970193326Sed ClassMethods); 2971193326Sed if (Category) { 2972198092Srdivacky Values[4] = 2973198398Srdivacky EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(), 2974193326Sed Category->protocol_begin(), 2975193326Sed Category->protocol_end()); 2976193326Sed } else { 2977193326Sed Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 2978193326Sed } 2979193326Sed Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 2980193326Sed 2981193326Sed // If there is no category @interface then there can be no properties. 2982193326Sed if (Category) { 2983198398Srdivacky Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), 2984193326Sed OCD, Category, ObjCTypes); 2985193326Sed } else { 2986193326Sed Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 2987193326Sed } 2988198092Srdivacky 2989193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy, 2990193326Sed Values); 2991193326Sed 2992198092Srdivacky llvm::GlobalVariable *GV = 2993198398Srdivacky CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init, 2994193326Sed "__OBJC,__category,regular,no_dead_strip", 2995193326Sed 4, true); 2996193326Sed DefinedCategories.push_back(GV); 2997210299Sed DefinedCategoryNames.insert(ExtName.str()); 2998221345Sdim // method definition entries must be clear for next implementation. 2999221345Sdim MethodDefinitions.clear(); 3000193326Sed} 3001193326Sed 3002243830Sdimenum FragileClassFlags { 3003243830Sdim FragileABI_Class_Factory = 0x00001, 3004243830Sdim FragileABI_Class_Meta = 0x00002, 3005243830Sdim FragileABI_Class_HasCXXStructors = 0x02000, 3006243830Sdim FragileABI_Class_Hidden = 0x20000 3007193326Sed}; 3008193326Sed 3009243830Sdimenum NonFragileClassFlags { 3010243830Sdim /// Is a meta-class. 3011243830Sdim NonFragileABI_Class_Meta = 0x00001, 3012243830Sdim 3013243830Sdim /// Is a root class. 3014243830Sdim NonFragileABI_Class_Root = 0x00002, 3015243830Sdim 3016243830Sdim /// Has a C++ constructor and destructor. 3017243830Sdim NonFragileABI_Class_HasCXXStructors = 0x00004, 3018243830Sdim 3019243830Sdim /// Has hidden visibility. 3020243830Sdim NonFragileABI_Class_Hidden = 0x00010, 3021243830Sdim 3022243830Sdim /// Has the exception attribute. 3023243830Sdim NonFragileABI_Class_Exception = 0x00020, 3024243830Sdim 3025243830Sdim /// (Obsolete) ARC-specific: this class has a .release_ivars method 3026243830Sdim NonFragileABI_Class_HasIvarReleaser = 0x00040, 3027243830Sdim 3028243830Sdim /// Class implementation was compiled under ARC. 3029243830Sdim NonFragileABI_Class_CompiledByARC = 0x00080, 3030243830Sdim 3031243830Sdim /// Class has non-trivial destructors, but zero-initialization is okay. 3032243830Sdim NonFragileABI_Class_HasCXXDestructorOnly = 0x00100 3033243830Sdim}; 3034243830Sdim 3035193326Sed/* 3036193326Sed struct _objc_class { 3037198092Srdivacky Class isa; 3038198092Srdivacky Class super_class; 3039198092Srdivacky const char *name; 3040198092Srdivacky long version; 3041198092Srdivacky long info; 3042198092Srdivacky long instance_size; 3043198092Srdivacky struct _objc_ivar_list *ivars; 3044198092Srdivacky struct _objc_method_list *methods; 3045198092Srdivacky struct _objc_cache *cache; 3046198092Srdivacky struct _objc_protocol_list *protocols; 3047198092Srdivacky // Objective-C 1.0 extensions (<rdr://4585769>) 3048198092Srdivacky const char *ivar_layout; 3049198092Srdivacky struct _objc_class_ext *ext; 3050193326Sed }; 3051193326Sed 3052193326Sed See EmitClassExtension(); 3053198092Srdivacky*/ 3054193326Sedvoid CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { 3055193326Sed DefinedSymbols.insert(ID->getIdentifier()); 3056193326Sed 3057193326Sed std::string ClassName = ID->getNameAsString(); 3058193326Sed // FIXME: Gross 3059198092Srdivacky ObjCInterfaceDecl *Interface = 3060193326Sed const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); 3061198092Srdivacky llvm::Constant *Protocols = 3062198398Srdivacky EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(), 3063212904Sdim Interface->all_referenced_protocol_begin(), 3064212904Sdim Interface->all_referenced_protocol_end()); 3065243830Sdim unsigned Flags = FragileABI_Class_Factory; 3066243830Sdim if (ID->hasNonZeroConstructors() || ID->hasDestructors()) 3067243830Sdim Flags |= FragileABI_Class_HasCXXStructors; 3068198092Srdivacky unsigned Size = 3069218893Sdim CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity(); 3070193326Sed 3071193326Sed // FIXME: Set CXX-structors flag. 3072218893Sdim if (ID->getClassInterface()->getVisibility() == HiddenVisibility) 3073243830Sdim Flags |= FragileABI_Class_Hidden; 3074193326Sed 3075249423Sdim SmallVector<llvm::Constant *, 16> InstanceMethods, ClassMethods; 3076198092Srdivacky for (ObjCImplementationDecl::instmeth_iterator 3077195341Sed i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { 3078193326Sed // Instance methods should always be defined. 3079193326Sed InstanceMethods.push_back(GetMethodConstant(*i)); 3080193326Sed } 3081198092Srdivacky for (ObjCImplementationDecl::classmeth_iterator 3082195341Sed i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { 3083193326Sed // Class methods should always be defined. 3084193326Sed ClassMethods.push_back(GetMethodConstant(*i)); 3085193326Sed } 3086193326Sed 3087198092Srdivacky for (ObjCImplementationDecl::propimpl_iterator 3088195341Sed i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { 3089193326Sed ObjCPropertyImplDecl *PID = *i; 3090193326Sed 3091193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { 3092193326Sed ObjCPropertyDecl *PD = PID->getPropertyDecl(); 3093193326Sed 3094193326Sed if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) 3095193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 3096193326Sed InstanceMethods.push_back(C); 3097193326Sed if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) 3098193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 3099193326Sed InstanceMethods.push_back(C); 3100193326Sed } 3101193326Sed } 3102193326Sed 3103224145Sdim llvm::Constant *Values[12]; 3104193326Sed Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods); 3105193326Sed if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) { 3106193326Sed // Record a reference to the super class. 3107193326Sed LazySymbols.insert(Super->getIdentifier()); 3108193326Sed 3109198092Srdivacky Values[ 1] = 3110193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), 3111193326Sed ObjCTypes.ClassPtrTy); 3112193326Sed } else { 3113193326Sed Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy); 3114193326Sed } 3115193326Sed Values[ 2] = GetClassName(ID->getIdentifier()); 3116193326Sed // Version is always 0. 3117193326Sed Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 3118193326Sed Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); 3119193326Sed Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 3120193326Sed Values[ 6] = EmitIvarList(ID, false); 3121198092Srdivacky Values[ 7] = 3122198398Srdivacky EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(), 3123193326Sed "__OBJC,__inst_meth,regular,no_dead_strip", 3124193326Sed InstanceMethods); 3125193326Sed // cache is always NULL. 3126193326Sed Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy); 3127193326Sed Values[ 9] = Protocols; 3128198092Srdivacky Values[10] = BuildIvarLayout(ID, true); 3129193326Sed Values[11] = EmitClassExtension(ID); 3130193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy, 3131193326Sed Values); 3132199482Srdivacky std::string Name("\01L_OBJC_CLASS_"); 3133199482Srdivacky Name += ClassName; 3134199482Srdivacky const char *Section = "__OBJC,__class,regular,no_dead_strip"; 3135199482Srdivacky // Check for a forward reference. 3136199482Srdivacky llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 3137199482Srdivacky if (GV) { 3138199482Srdivacky assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 3139199482Srdivacky "Forward metaclass reference has incorrect type."); 3140199482Srdivacky GV->setLinkage(llvm::GlobalValue::InternalLinkage); 3141199482Srdivacky GV->setInitializer(Init); 3142199482Srdivacky GV->setSection(Section); 3143199482Srdivacky GV->setAlignment(4); 3144199482Srdivacky CGM.AddUsedGlobal(GV); 3145199482Srdivacky } 3146199482Srdivacky else 3147199482Srdivacky GV = CreateMetadataVar(Name, Init, Section, 4, true); 3148193326Sed DefinedClasses.push_back(GV); 3149221345Sdim // method definition entries must be clear for next implementation. 3150221345Sdim MethodDefinitions.clear(); 3151193326Sed} 3152193326Sed 3153193326Sedllvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, 3154193326Sed llvm::Constant *Protocols, 3155234353Sdim ArrayRef<llvm::Constant*> Methods) { 3156243830Sdim unsigned Flags = FragileABI_Class_Meta; 3157243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy); 3158193326Sed 3159218893Sdim if (ID->getClassInterface()->getVisibility() == HiddenVisibility) 3160243830Sdim Flags |= FragileABI_Class_Hidden; 3161198092Srdivacky 3162224145Sdim llvm::Constant *Values[12]; 3163193326Sed // The isa for the metaclass is the root of the hierarchy. 3164193326Sed const ObjCInterfaceDecl *Root = ID->getClassInterface(); 3165193326Sed while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) 3166193326Sed Root = Super; 3167198092Srdivacky Values[ 0] = 3168193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()), 3169193326Sed ObjCTypes.ClassPtrTy); 3170193326Sed // The super class for the metaclass is emitted as the name of the 3171193326Sed // super class. The runtime fixes this up to point to the 3172193326Sed // *metaclass* for the super class. 3173193326Sed if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) { 3174198092Srdivacky Values[ 1] = 3175193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), 3176193326Sed ObjCTypes.ClassPtrTy); 3177193326Sed } else { 3178193326Sed Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy); 3179193326Sed } 3180193326Sed Values[ 2] = GetClassName(ID->getIdentifier()); 3181193326Sed // Version is always 0. 3182193326Sed Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 3183193326Sed Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); 3184193326Sed Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 3185193326Sed Values[ 6] = EmitIvarList(ID, true); 3186198092Srdivacky Values[ 7] = 3187193326Sed EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(), 3188193326Sed "__OBJC,__cls_meth,regular,no_dead_strip", 3189193326Sed Methods); 3190193326Sed // cache is always NULL. 3191193326Sed Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy); 3192193326Sed Values[ 9] = Protocols; 3193193326Sed // ivar_layout for metaclass is always NULL. 3194193326Sed Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 3195193326Sed // The class extension is always unused for metaclasses. 3196193326Sed Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); 3197193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy, 3198193326Sed Values); 3199193326Sed 3200193326Sed std::string Name("\01L_OBJC_METACLASS_"); 3201239462Sdim Name += ID->getName(); 3202193326Sed 3203193326Sed // Check for a forward reference. 3204193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 3205193326Sed if (GV) { 3206193326Sed assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 3207193326Sed "Forward metaclass reference has incorrect type."); 3208193326Sed GV->setLinkage(llvm::GlobalValue::InternalLinkage); 3209193326Sed GV->setInitializer(Init); 3210193326Sed } else { 3211198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 3212193326Sed llvm::GlobalValue::InternalLinkage, 3213198092Srdivacky Init, Name); 3214193326Sed } 3215193326Sed GV->setSection("__OBJC,__meta_class,regular,no_dead_strip"); 3216193326Sed GV->setAlignment(4); 3217198092Srdivacky CGM.AddUsedGlobal(GV); 3218193326Sed 3219193326Sed return GV; 3220193326Sed} 3221193326Sed 3222198092Srdivackyllvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) { 3223193326Sed std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString(); 3224193326Sed 3225193326Sed // FIXME: Should we look these up somewhere other than the module. Its a bit 3226193326Sed // silly since we only generate these while processing an implementation, so 3227193326Sed // exactly one pointer would work if know when we entered/exitted an 3228193326Sed // implementation block. 3229193326Sed 3230193326Sed // Check for an existing forward reference. 3231193326Sed // Previously, metaclass with internal linkage may have been defined. 3232193326Sed // pass 'true' as 2nd argument so it is returned. 3233198092Srdivacky if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, 3234198092Srdivacky true)) { 3235193326Sed assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 3236193326Sed "Forward metaclass reference has incorrect type."); 3237193326Sed return GV; 3238193326Sed } else { 3239193326Sed // Generate as an external reference to keep a consistent 3240193326Sed // module. This will be patched up when we emit the metaclass. 3241198092Srdivacky return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 3242193326Sed llvm::GlobalValue::ExternalLinkage, 3243193326Sed 0, 3244198092Srdivacky Name); 3245193326Sed } 3246193326Sed} 3247193326Sed 3248199482Srdivackyllvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) { 3249199482Srdivacky std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString(); 3250199482Srdivacky 3251199482Srdivacky if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, 3252199482Srdivacky true)) { 3253199482Srdivacky assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 3254199482Srdivacky "Forward class metadata reference has incorrect type."); 3255199482Srdivacky return GV; 3256199482Srdivacky } else { 3257199482Srdivacky return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 3258199482Srdivacky llvm::GlobalValue::ExternalLinkage, 3259199482Srdivacky 0, 3260199482Srdivacky Name); 3261199482Srdivacky } 3262199482Srdivacky} 3263199482Srdivacky 3264193326Sed/* 3265193326Sed struct objc_class_ext { 3266198092Srdivacky uint32_t size; 3267198092Srdivacky const char *weak_ivar_layout; 3268198092Srdivacky struct _objc_property_list *properties; 3269193326Sed }; 3270193326Sed*/ 3271193326Sedllvm::Constant * 3272193326SedCGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) { 3273198092Srdivacky uint64_t Size = 3274243830Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy); 3275193326Sed 3276224145Sdim llvm::Constant *Values[3]; 3277193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 3278193326Sed Values[1] = BuildIvarLayout(ID, false); 3279198398Srdivacky Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), 3280193326Sed ID, ID->getClassInterface(), ObjCTypes); 3281193326Sed 3282193326Sed // Return null if no extension bits are used. 3283193326Sed if (Values[1]->isNullValue() && Values[2]->isNullValue()) 3284193326Sed return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); 3285193326Sed 3286198092Srdivacky llvm::Constant *Init = 3287193326Sed llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values); 3288198398Srdivacky return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(), 3289198092Srdivacky Init, "__OBJC,__class_ext,regular,no_dead_strip", 3290193326Sed 4, true); 3291193326Sed} 3292193326Sed 3293193326Sed/* 3294193326Sed struct objc_ivar { 3295234353Sdim char *ivar_name; 3296234353Sdim char *ivar_type; 3297234353Sdim int ivar_offset; 3298193326Sed }; 3299193326Sed 3300193326Sed struct objc_ivar_list { 3301234353Sdim int ivar_count; 3302234353Sdim struct objc_ivar list[count]; 3303193326Sed }; 3304198092Srdivacky*/ 3305193326Sedllvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, 3306193326Sed bool ForClass) { 3307234353Sdim std::vector<llvm::Constant*> Ivars; 3308193326Sed 3309193326Sed // When emitting the root class GCC emits ivar entries for the 3310193326Sed // actual class structure. It is not clear if we need to follow this 3311193326Sed // behavior; for now lets try and get away with not doing it. If so, 3312193326Sed // the cleanest solution would be to make up an ObjCInterfaceDecl 3313193326Sed // for the class. 3314193326Sed if (ForClass) 3315193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); 3316198092Srdivacky 3317226633Sdim const ObjCInterfaceDecl *OID = ID->getClassInterface(); 3318198092Srdivacky 3319226633Sdim for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); 3320224145Sdim IVD; IVD = IVD->getNextIvar()) { 3321193576Sed // Ignore unnamed bit-fields. 3322193576Sed if (!IVD->getDeclName()) 3323198092Srdivacky continue; 3324234353Sdim llvm::Constant *Ivar[] = { 3325234353Sdim GetMethodVarName(IVD->getIdentifier()), 3326234353Sdim GetMethodVarType(IVD), 3327234353Sdim llvm::ConstantInt::get(ObjCTypes.IntTy, 3328234353Sdim ComputeIvarBaseOffset(CGM, OID, IVD)) 3329234353Sdim }; 3330193326Sed Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar)); 3331193326Sed } 3332193326Sed 3333193326Sed // Return null for empty list. 3334193326Sed if (Ivars.empty()) 3335193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); 3336193326Sed 3337224145Sdim llvm::Constant *Values[2]; 3338193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size()); 3339193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy, 3340193326Sed Ivars.size()); 3341193326Sed Values[1] = llvm::ConstantArray::get(AT, Ivars); 3342224145Sdim llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values); 3343193326Sed 3344193326Sed llvm::GlobalVariable *GV; 3345193326Sed if (ForClass) 3346198398Srdivacky GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(), 3347198092Srdivacky Init, "__OBJC,__class_vars,regular,no_dead_strip", 3348193326Sed 4, true); 3349193326Sed else 3350198398Srdivacky GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(), 3351193326Sed Init, "__OBJC,__instance_vars,regular,no_dead_strip", 3352193326Sed 4, true); 3353193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy); 3354193326Sed} 3355193326Sed 3356193326Sed/* 3357193326Sed struct objc_method { 3358198092Srdivacky SEL method_name; 3359198092Srdivacky char *method_types; 3360198092Srdivacky void *method; 3361193326Sed }; 3362198092Srdivacky 3363193326Sed struct objc_method_list { 3364198092Srdivacky struct objc_method_list *obsolete; 3365198092Srdivacky int count; 3366198092Srdivacky struct objc_method methods_list[count]; 3367193326Sed }; 3368193326Sed*/ 3369193326Sed 3370193326Sed/// GetMethodConstant - Return a struct objc_method constant for the 3371193326Sed/// given method if it has been defined. The result is null if the 3372193326Sed/// method has not been defined. The return value has type MethodPtrTy. 3373193326Sedllvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) { 3374212904Sdim llvm::Function *Fn = GetMethodDefinition(MD); 3375193326Sed if (!Fn) 3376193326Sed return 0; 3377198092Srdivacky 3378234353Sdim llvm::Constant *Method[] = { 3379193326Sed llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 3380234353Sdim ObjCTypes.SelectorPtrTy), 3381234353Sdim GetMethodVarType(MD), 3382234353Sdim llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy) 3383234353Sdim }; 3384193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method); 3385193326Sed} 3386193326Sed 3387226633Sdimllvm::Constant *CGObjCMac::EmitMethodList(Twine Name, 3388193326Sed const char *Section, 3389234353Sdim ArrayRef<llvm::Constant*> Methods) { 3390193326Sed // Return null for empty list. 3391193326Sed if (Methods.empty()) 3392193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy); 3393193326Sed 3394224145Sdim llvm::Constant *Values[3]; 3395193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 3396193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 3397193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy, 3398193326Sed Methods.size()); 3399193326Sed Values[2] = llvm::ConstantArray::get(AT, Methods); 3400224145Sdim llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values); 3401193326Sed 3402193326Sed llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true); 3403224145Sdim return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy); 3404193326Sed} 3405193326Sed 3406193326Sedllvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD, 3407198092Srdivacky const ObjCContainerDecl *CD) { 3408234353Sdim SmallString<256> Name; 3409193326Sed GetNameForMethod(OMD, CD, Name); 3410193326Sed 3411193326Sed CodeGenTypes &Types = CGM.getTypes(); 3412226633Sdim llvm::FunctionType *MethodTy = 3413234353Sdim Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD)); 3414198092Srdivacky llvm::Function *Method = 3415193326Sed llvm::Function::Create(MethodTy, 3416193326Sed llvm::GlobalValue::InternalLinkage, 3417198398Srdivacky Name.str(), 3418193326Sed &CGM.getModule()); 3419193326Sed MethodDefinitions.insert(std::make_pair(OMD, Method)); 3420193326Sed 3421193326Sed return Method; 3422193326Sed} 3423193326Sed 3424193326Sedllvm::GlobalVariable * 3425226633SdimCGObjCCommonMac::CreateMetadataVar(Twine Name, 3426193326Sed llvm::Constant *Init, 3427193326Sed const char *Section, 3428193326Sed unsigned Align, 3429193326Sed bool AddToUsed) { 3430226633Sdim llvm::Type *Ty = Init->getType(); 3431198092Srdivacky llvm::GlobalVariable *GV = 3432198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Ty, false, 3433198092Srdivacky llvm::GlobalValue::InternalLinkage, Init, Name); 3434193326Sed if (Section) 3435193326Sed GV->setSection(Section); 3436193326Sed if (Align) 3437193326Sed GV->setAlignment(Align); 3438193326Sed if (AddToUsed) 3439198092Srdivacky CGM.AddUsedGlobal(GV); 3440193326Sed return GV; 3441193326Sed} 3442193326Sed 3443198092Srdivackyllvm::Function *CGObjCMac::ModuleInitFunction() { 3444193326Sed // Abuse this interface function as a place to finalize. 3445193326Sed FinishModule(); 3446193326Sed return NULL; 3447193326Sed} 3448193326Sed 3449193326Sedllvm::Constant *CGObjCMac::GetPropertyGetFunction() { 3450193326Sed return ObjCTypes.getGetPropertyFn(); 3451193326Sed} 3452193326Sed 3453193326Sedllvm::Constant *CGObjCMac::GetPropertySetFunction() { 3454193326Sed return ObjCTypes.getSetPropertyFn(); 3455193326Sed} 3456193326Sed 3457234353Sdimllvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic, 3458234353Sdim bool copy) { 3459234353Sdim return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy); 3460234353Sdim} 3461234353Sdim 3462218893Sdimllvm::Constant *CGObjCMac::GetGetStructFunction() { 3463207619Srdivacky return ObjCTypes.getCopyStructFn(); 3464207619Srdivacky} 3465218893Sdimllvm::Constant *CGObjCMac::GetSetStructFunction() { 3466218893Sdim return ObjCTypes.getCopyStructFn(); 3467218893Sdim} 3468207619Srdivacky 3469249423Sdimllvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() { 3470234353Sdim return ObjCTypes.getCppAtomicObjectFunction(); 3471234353Sdim} 3472249423Sdimllvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() { 3473249423Sdim return ObjCTypes.getCppAtomicObjectFunction(); 3474249423Sdim} 3475234353Sdim 3476193326Sedllvm::Constant *CGObjCMac::EnumerationMutationFunction() { 3477193326Sed return ObjCTypes.getEnumerationMutationFn(); 3478193326Sed} 3479193326Sed 3480210299Sedvoid CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) { 3481210299Sed return EmitTryOrSynchronizedStmt(CGF, S); 3482210299Sed} 3483210299Sed 3484210299Sedvoid CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF, 3485210299Sed const ObjCAtSynchronizedStmt &S) { 3486210299Sed return EmitTryOrSynchronizedStmt(CGF, S); 3487210299Sed} 3488210299Sed 3489212904Sdimnamespace { 3490212904Sdim struct PerformFragileFinally : EHScopeStack::Cleanup { 3491212904Sdim const Stmt &S; 3492212904Sdim llvm::Value *SyncArgSlot; 3493212904Sdim llvm::Value *CallTryExitVar; 3494212904Sdim llvm::Value *ExceptionData; 3495212904Sdim ObjCTypesHelper &ObjCTypes; 3496212904Sdim PerformFragileFinally(const Stmt *S, 3497212904Sdim llvm::Value *SyncArgSlot, 3498212904Sdim llvm::Value *CallTryExitVar, 3499212904Sdim llvm::Value *ExceptionData, 3500212904Sdim ObjCTypesHelper *ObjCTypes) 3501212904Sdim : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar), 3502212904Sdim ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {} 3503212904Sdim 3504224145Sdim void Emit(CodeGenFunction &CGF, Flags flags) { 3505212904Sdim // Check whether we need to call objc_exception_try_exit. 3506212904Sdim // In optimized code, this branch will always be folded. 3507212904Sdim llvm::BasicBlock *FinallyCallExit = 3508212904Sdim CGF.createBasicBlock("finally.call_exit"); 3509212904Sdim llvm::BasicBlock *FinallyNoCallExit = 3510212904Sdim CGF.createBasicBlock("finally.no_call_exit"); 3511212904Sdim CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar), 3512212904Sdim FinallyCallExit, FinallyNoCallExit); 3513212904Sdim 3514212904Sdim CGF.EmitBlock(FinallyCallExit); 3515249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(), 3516249423Sdim ExceptionData); 3517212904Sdim 3518212904Sdim CGF.EmitBlock(FinallyNoCallExit); 3519212904Sdim 3520212904Sdim if (isa<ObjCAtTryStmt>(S)) { 3521212904Sdim if (const ObjCAtFinallyStmt* FinallyStmt = 3522212904Sdim cast<ObjCAtTryStmt>(S).getFinallyStmt()) { 3523249423Sdim // Don't try to do the @finally if this is an EH cleanup. 3524249423Sdim if (flags.isForEHCleanup()) return; 3525249423Sdim 3526212904Sdim // Save the current cleanup destination in case there's 3527212904Sdim // control flow inside the finally statement. 3528212904Sdim llvm::Value *CurCleanupDest = 3529212904Sdim CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot()); 3530212904Sdim 3531212904Sdim CGF.EmitStmt(FinallyStmt->getFinallyBody()); 3532212904Sdim 3533212904Sdim if (CGF.HaveInsertPoint()) { 3534212904Sdim CGF.Builder.CreateStore(CurCleanupDest, 3535212904Sdim CGF.getNormalCleanupDestSlot()); 3536212904Sdim } else { 3537212904Sdim // Currently, the end of the cleanup must always exist. 3538212904Sdim CGF.EnsureInsertPoint(); 3539212904Sdim } 3540212904Sdim } 3541212904Sdim } else { 3542212904Sdim // Emit objc_sync_exit(expr); as finally's sole statement for 3543212904Sdim // @synchronized. 3544212904Sdim llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot); 3545249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg); 3546212904Sdim } 3547212904Sdim } 3548212904Sdim }; 3549212904Sdim 3550212904Sdim class FragileHazards { 3551212904Sdim CodeGenFunction &CGF; 3552226633Sdim SmallVector<llvm::Value*, 20> Locals; 3553212904Sdim llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry; 3554212904Sdim 3555212904Sdim llvm::InlineAsm *ReadHazard; 3556212904Sdim llvm::InlineAsm *WriteHazard; 3557212904Sdim 3558212904Sdim llvm::FunctionType *GetAsmFnType(); 3559212904Sdim 3560212904Sdim void collectLocals(); 3561212904Sdim void emitReadHazard(CGBuilderTy &Builder); 3562212904Sdim 3563212904Sdim public: 3564212904Sdim FragileHazards(CodeGenFunction &CGF); 3565212904Sdim 3566212904Sdim void emitWriteHazard(); 3567212904Sdim void emitHazardsInNewBlocks(); 3568212904Sdim }; 3569212904Sdim} 3570212904Sdim 3571212904Sdim/// Create the fragile-ABI read and write hazards based on the current 3572212904Sdim/// state of the function, which is presumed to be immediately prior 3573212904Sdim/// to a @try block. These hazards are used to maintain correct 3574212904Sdim/// semantics in the face of optimization and the fragile ABI's 3575212904Sdim/// cavalier use of setjmp/longjmp. 3576212904SdimFragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) { 3577212904Sdim collectLocals(); 3578212904Sdim 3579212904Sdim if (Locals.empty()) return; 3580212904Sdim 3581212904Sdim // Collect all the blocks in the function. 3582212904Sdim for (llvm::Function::iterator 3583212904Sdim I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I) 3584212904Sdim BlocksBeforeTry.insert(&*I); 3585212904Sdim 3586212904Sdim llvm::FunctionType *AsmFnTy = GetAsmFnType(); 3587212904Sdim 3588212904Sdim // Create a read hazard for the allocas. This inhibits dead-store 3589212904Sdim // optimizations and forces the values to memory. This hazard is 3590212904Sdim // inserted before any 'throwing' calls in the protected scope to 3591212904Sdim // reflect the possibility that the variables might be read from the 3592212904Sdim // catch block if the call throws. 3593212904Sdim { 3594212904Sdim std::string Constraint; 3595212904Sdim for (unsigned I = 0, E = Locals.size(); I != E; ++I) { 3596212904Sdim if (I) Constraint += ','; 3597212904Sdim Constraint += "*m"; 3598212904Sdim } 3599212904Sdim 3600212904Sdim ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false); 3601212904Sdim } 3602212904Sdim 3603212904Sdim // Create a write hazard for the allocas. This inhibits folding 3604212904Sdim // loads across the hazard. This hazard is inserted at the 3605212904Sdim // beginning of the catch path to reflect the possibility that the 3606212904Sdim // variables might have been written within the protected scope. 3607212904Sdim { 3608212904Sdim std::string Constraint; 3609212904Sdim for (unsigned I = 0, E = Locals.size(); I != E; ++I) { 3610212904Sdim if (I) Constraint += ','; 3611212904Sdim Constraint += "=*m"; 3612212904Sdim } 3613212904Sdim 3614212904Sdim WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false); 3615212904Sdim } 3616212904Sdim} 3617212904Sdim 3618212904Sdim/// Emit a write hazard at the current location. 3619212904Sdimvoid FragileHazards::emitWriteHazard() { 3620212904Sdim if (Locals.empty()) return; 3621212904Sdim 3622249423Sdim CGF.EmitNounwindRuntimeCall(WriteHazard, Locals); 3623212904Sdim} 3624212904Sdim 3625212904Sdimvoid FragileHazards::emitReadHazard(CGBuilderTy &Builder) { 3626212904Sdim assert(!Locals.empty()); 3627249423Sdim llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals); 3628249423Sdim call->setDoesNotThrow(); 3629249423Sdim call->setCallingConv(CGF.getRuntimeCC()); 3630212904Sdim} 3631212904Sdim 3632212904Sdim/// Emit read hazards in all the protected blocks, i.e. all the blocks 3633212904Sdim/// which have been inserted since the beginning of the try. 3634212904Sdimvoid FragileHazards::emitHazardsInNewBlocks() { 3635212904Sdim if (Locals.empty()) return; 3636212904Sdim 3637212904Sdim CGBuilderTy Builder(CGF.getLLVMContext()); 3638212904Sdim 3639212904Sdim // Iterate through all blocks, skipping those prior to the try. 3640212904Sdim for (llvm::Function::iterator 3641212904Sdim FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) { 3642212904Sdim llvm::BasicBlock &BB = *FI; 3643212904Sdim if (BlocksBeforeTry.count(&BB)) continue; 3644212904Sdim 3645212904Sdim // Walk through all the calls in the block. 3646212904Sdim for (llvm::BasicBlock::iterator 3647212904Sdim BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) { 3648212904Sdim llvm::Instruction &I = *BI; 3649212904Sdim 3650212904Sdim // Ignore instructions that aren't non-intrinsic calls. 3651212904Sdim // These are the only calls that can possibly call longjmp. 3652212904Sdim if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue; 3653212904Sdim if (isa<llvm::IntrinsicInst>(I)) 3654212904Sdim continue; 3655212904Sdim 3656212904Sdim // Ignore call sites marked nounwind. This may be questionable, 3657212904Sdim // since 'nounwind' doesn't necessarily mean 'does not call longjmp'. 3658212904Sdim llvm::CallSite CS(&I); 3659212904Sdim if (CS.doesNotThrow()) continue; 3660212904Sdim 3661212904Sdim // Insert a read hazard before the call. This will ensure that 3662212904Sdim // any writes to the locals are performed before making the 3663212904Sdim // call. If the call throws, then this is sufficient to 3664212904Sdim // guarantee correctness as long as it doesn't also write to any 3665212904Sdim // locals. 3666212904Sdim Builder.SetInsertPoint(&BB, BI); 3667212904Sdim emitReadHazard(Builder); 3668212904Sdim } 3669212904Sdim } 3670212904Sdim} 3671212904Sdim 3672212904Sdimstatic void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) { 3673212904Sdim if (V) S.insert(V); 3674212904Sdim} 3675212904Sdim 3676212904Sdimvoid FragileHazards::collectLocals() { 3677212904Sdim // Compute a set of allocas to ignore. 3678212904Sdim llvm::DenseSet<llvm::Value*> AllocasToIgnore; 3679212904Sdim addIfPresent(AllocasToIgnore, CGF.ReturnValue); 3680212904Sdim addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest); 3681212904Sdim 3682212904Sdim // Collect all the allocas currently in the function. This is 3683212904Sdim // probably way too aggressive. 3684212904Sdim llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock(); 3685212904Sdim for (llvm::BasicBlock::iterator 3686212904Sdim I = Entry.begin(), E = Entry.end(); I != E; ++I) 3687212904Sdim if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I)) 3688212904Sdim Locals.push_back(&*I); 3689212904Sdim} 3690212904Sdim 3691212904Sdimllvm::FunctionType *FragileHazards::GetAsmFnType() { 3692226633Sdim SmallVector<llvm::Type *, 16> tys(Locals.size()); 3693223017Sdim for (unsigned i = 0, e = Locals.size(); i != e; ++i) 3694223017Sdim tys[i] = Locals[i]->getType(); 3695223017Sdim return llvm::FunctionType::get(CGF.VoidTy, tys, false); 3696212904Sdim} 3697212904Sdim 3698198092Srdivacky/* 3699193326Sed 3700198092Srdivacky Objective-C setjmp-longjmp (sjlj) Exception Handling 3701198092Srdivacky -- 3702193326Sed 3703210299Sed A catch buffer is a setjmp buffer plus: 3704210299Sed - a pointer to the exception that was caught 3705210299Sed - a pointer to the previous exception data buffer 3706210299Sed - two pointers of reserved storage 3707210299Sed Therefore catch buffers form a stack, with a pointer to the top 3708210299Sed of the stack kept in thread-local storage. 3709210299Sed 3710210299Sed objc_exception_try_enter pushes a catch buffer onto the EH stack. 3711210299Sed objc_exception_try_exit pops the given catch buffer, which is 3712210299Sed required to be the top of the EH stack. 3713210299Sed objc_exception_throw pops the top of the EH stack, writes the 3714210299Sed thrown exception into the appropriate field, and longjmps 3715210299Sed to the setjmp buffer. It crashes the process (with a printf 3716210299Sed and an abort()) if there are no catch buffers on the stack. 3717210299Sed objc_exception_extract just reads the exception pointer out of the 3718210299Sed catch buffer. 3719210299Sed 3720210299Sed There's no reason an implementation couldn't use a light-weight 3721210299Sed setjmp here --- something like __builtin_setjmp, but API-compatible 3722210299Sed with the heavyweight setjmp. This will be more important if we ever 3723210299Sed want to implement correct ObjC/C++ exception interactions for the 3724210299Sed fragile ABI. 3725210299Sed 3726210299Sed Note that for this use of setjmp/longjmp to be correct, we may need 3727210299Sed to mark some local variables volatile: if a non-volatile local 3728210299Sed variable is modified between the setjmp and the longjmp, it has 3729210299Sed indeterminate value. For the purposes of LLVM IR, it may be 3730210299Sed sufficient to make loads and stores within the @try (to variables 3731210299Sed declared outside the @try) volatile. This is necessary for 3732210299Sed optimized correctness, but is not currently being done; this is 3733210299Sed being tracked as rdar://problem/8160285 3734210299Sed 3735198092Srdivacky The basic framework for a @try-catch-finally is as follows: 3736198092Srdivacky { 3737193326Sed objc_exception_data d; 3738193326Sed id _rethrow = null; 3739193326Sed bool _call_try_exit = true; 3740198092Srdivacky 3741193326Sed objc_exception_try_enter(&d); 3742193326Sed if (!setjmp(d.jmp_buf)) { 3743198092Srdivacky ... try body ... 3744193326Sed } else { 3745198092Srdivacky // exception path 3746198092Srdivacky id _caught = objc_exception_extract(&d); 3747198092Srdivacky 3748198092Srdivacky // enter new try scope for handlers 3749198092Srdivacky if (!setjmp(d.jmp_buf)) { 3750198092Srdivacky ... match exception and execute catch blocks ... 3751198092Srdivacky 3752198092Srdivacky // fell off end, rethrow. 3753198092Srdivacky _rethrow = _caught; 3754198092Srdivacky ... jump-through-finally to finally_rethrow ... 3755198092Srdivacky } else { 3756198092Srdivacky // exception in catch block 3757198092Srdivacky _rethrow = objc_exception_extract(&d); 3758198092Srdivacky _call_try_exit = false; 3759198092Srdivacky ... jump-through-finally to finally_rethrow ... 3760193326Sed } 3761198092Srdivacky } 3762193326Sed ... jump-through-finally to finally_end ... 3763193326Sed 3764198092Srdivacky finally: 3765193326Sed if (_call_try_exit) 3766198092Srdivacky objc_exception_try_exit(&d); 3767193326Sed 3768193326Sed ... finally block .... 3769193326Sed ... dispatch to finally destination ... 3770193326Sed 3771198092Srdivacky finally_rethrow: 3772193326Sed objc_exception_throw(_rethrow); 3773193326Sed 3774198092Srdivacky finally_end: 3775198092Srdivacky } 3776193326Sed 3777198092Srdivacky This framework differs slightly from the one gcc uses, in that gcc 3778198092Srdivacky uses _rethrow to determine if objc_exception_try_exit should be called 3779198092Srdivacky and if the object should be rethrown. This breaks in the face of 3780198092Srdivacky throwing nil and introduces unnecessary branches. 3781193326Sed 3782198092Srdivacky We specialize this framework for a few particular circumstances: 3783193326Sed 3784198092Srdivacky - If there are no catch blocks, then we avoid emitting the second 3785198092Srdivacky exception handling context. 3786193326Sed 3787198092Srdivacky - If there is a catch-all catch block (i.e. @catch(...) or @catch(id 3788198092Srdivacky e)) we avoid emitting the code to rethrow an uncaught exception. 3789193326Sed 3790198092Srdivacky - FIXME: If there is no @finally block we can do a few more 3791198092Srdivacky simplifications. 3792193326Sed 3793198092Srdivacky Rethrows and Jumps-Through-Finally 3794198092Srdivacky -- 3795193326Sed 3796210299Sed '@throw;' is supported by pushing the currently-caught exception 3797210299Sed onto ObjCEHStack while the @catch blocks are emitted. 3798193326Sed 3799210299Sed Branches through the @finally block are handled with an ordinary 3800210299Sed normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC 3801210299Sed exceptions are not compatible with C++ exceptions, and this is 3802210299Sed hardly the only place where this will go wrong. 3803193326Sed 3804210299Sed @synchronized(expr) { stmt; } is emitted as if it were: 3805210299Sed id synch_value = expr; 3806210299Sed objc_sync_enter(synch_value); 3807210299Sed @try { stmt; } @finally { objc_sync_exit(synch_value); } 3808193326Sed*/ 3809193326Sed 3810193326Sedvoid CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 3811193326Sed const Stmt &S) { 3812193326Sed bool isTry = isa<ObjCAtTryStmt>(S); 3813198092Srdivacky 3814210299Sed // A destination for the fall-through edges of the catch handlers to 3815210299Sed // jump to. 3816210299Sed CodeGenFunction::JumpDest FinallyEnd = 3817210299Sed CGF.getJumpDestInCurrentScope("finally.end"); 3818210299Sed 3819210299Sed // A destination for the rethrow edge of the catch handlers to jump 3820210299Sed // to. 3821210299Sed CodeGenFunction::JumpDest FinallyRethrow = 3822210299Sed CGF.getJumpDestInCurrentScope("finally.rethrow"); 3823210299Sed 3824193326Sed // For @synchronized, call objc_sync_enter(sync.expr). The 3825193326Sed // evaluation of the expression must occur before we enter the 3826212904Sdim // @synchronized. We can't avoid a temp here because we need the 3827212904Sdim // value to be preserved. If the backend ever does liveness 3828212904Sdim // correctly after setjmp, this will be unnecessary. 3829212904Sdim llvm::Value *SyncArgSlot = 0; 3830193326Sed if (!isTry) { 3831212904Sdim llvm::Value *SyncArg = 3832193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 3833193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); 3834249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg); 3835212904Sdim 3836212904Sdim SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg"); 3837212904Sdim CGF.Builder.CreateStore(SyncArg, SyncArgSlot); 3838193326Sed } 3839193326Sed 3840212904Sdim // Allocate memory for the setjmp buffer. This needs to be kept 3841212904Sdim // live throughout the try and catch blocks. 3842193326Sed llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy, 3843193326Sed "exceptiondata.ptr"); 3844210299Sed 3845212904Sdim // Create the fragile hazards. Note that this will not capture any 3846212904Sdim // of the allocas required for exception processing, but will 3847212904Sdim // capture the current basic block (which extends all the way to the 3848212904Sdim // setjmp call) as "before the @try". 3849212904Sdim FragileHazards Hazards(CGF); 3850212904Sdim 3851210299Sed // Create a flag indicating whether the cleanup needs to call 3852210299Sed // objc_exception_try_exit. This is true except when 3853210299Sed // - no catches match and we're branching through the cleanup 3854210299Sed // just to rethrow the exception, or 3855210299Sed // - a catch matched and we're falling out of the catch handler. 3856212904Sdim // The setjmp-safety rule here is that we should always store to this 3857212904Sdim // variable in a place that dominates the branch through the cleanup 3858212904Sdim // without passing through any setjmps. 3859210299Sed llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), 3860193326Sed "_call_try_exit"); 3861198092Srdivacky 3862218893Sdim // A slot containing the exception to rethrow. Only needed when we 3863218893Sdim // have both a @catch and a @finally. 3864218893Sdim llvm::Value *PropagatingExnVar = 0; 3865218893Sdim 3866210299Sed // Push a normal cleanup to leave the try scope. 3867249423Sdim CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S, 3868212904Sdim SyncArgSlot, 3869212904Sdim CallTryExitVar, 3870212904Sdim ExceptionData, 3871212904Sdim &ObjCTypes); 3872193326Sed 3873210299Sed // Enter a try block: 3874210299Sed // - Call objc_exception_try_enter to push ExceptionData on top of 3875210299Sed // the EH stack. 3876249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData); 3877210299Sed 3878210299Sed // - Call setjmp on the exception data buffer. 3879210299Sed llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); 3880210299Sed llvm::Value *GEPIndexes[] = { Zero, Zero, Zero }; 3881210299Sed llvm::Value *SetJmpBuffer = 3882226633Sdim CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer"); 3883210299Sed llvm::CallInst *SetJmpResult = 3884249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result"); 3885234353Sdim SetJmpResult->setCanReturnTwice(); 3886210299Sed 3887210299Sed // If setjmp returned 0, enter the protected block; otherwise, 3888210299Sed // branch to the handler. 3889193326Sed llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); 3890193326Sed llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); 3891210299Sed llvm::Value *DidCatch = 3892212904Sdim CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); 3893212904Sdim CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock); 3894193326Sed 3895210299Sed // Emit the protected block. 3896193326Sed CGF.EmitBlock(TryBlock); 3897212904Sdim CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar); 3898198092Srdivacky CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() 3899210299Sed : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); 3900198092Srdivacky 3901212904Sdim CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP(); 3902212904Sdim 3903210299Sed // Emit the exception handler block. 3904193326Sed CGF.EmitBlock(TryHandler); 3905193326Sed 3906212904Sdim // Don't optimize loads of the in-scope locals across this point. 3907212904Sdim Hazards.emitWriteHazard(); 3908210299Sed 3909210299Sed // For a @synchronized (or a @try with no catches), just branch 3910210299Sed // through the cleanup to the rethrow block. 3911210299Sed if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) { 3912210299Sed // Tell the cleanup not to re-pop the exit. 3913212904Sdim CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar); 3914193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 3915210299Sed 3916210299Sed // Otherwise, we have to match against the caught exceptions. 3917210299Sed } else { 3918212904Sdim // Retrieve the exception object. We may emit multiple blocks but 3919212904Sdim // nothing can cross this so the value is already in SSA form. 3920212904Sdim llvm::CallInst *Caught = 3921249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), 3922249423Sdim ExceptionData, "caught"); 3923212904Sdim 3924210299Sed // Push the exception to rethrow onto the EH value stack for the 3925210299Sed // benefit of any @throws in the handlers. 3926210299Sed CGF.ObjCEHValueStack.push_back(Caught); 3927210299Sed 3928207619Srdivacky const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S); 3929198092Srdivacky 3930212904Sdim bool HasFinally = (AtTryStmt->getFinallyStmt() != 0); 3931193326Sed 3932212904Sdim llvm::BasicBlock *CatchBlock = 0; 3933212904Sdim llvm::BasicBlock *CatchHandler = 0; 3934212904Sdim if (HasFinally) { 3935218893Sdim // Save the currently-propagating exception before 3936218893Sdim // objc_exception_try_enter clears the exception slot. 3937218893Sdim PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(), 3938218893Sdim "propagating_exception"); 3939218893Sdim CGF.Builder.CreateStore(Caught, PropagatingExnVar); 3940218893Sdim 3941212904Sdim // Enter a new exception try block (in case a @catch block 3942212904Sdim // throws an exception). 3943249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), 3944249423Sdim ExceptionData); 3945210299Sed 3946212904Sdim llvm::CallInst *SetJmpResult = 3947249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), 3948249423Sdim SetJmpBuffer, "setjmp.result"); 3949234353Sdim SetJmpResult->setCanReturnTwice(); 3950198092Srdivacky 3951212904Sdim llvm::Value *Threw = 3952212904Sdim CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); 3953198092Srdivacky 3954212904Sdim CatchBlock = CGF.createBasicBlock("catch"); 3955212904Sdim CatchHandler = CGF.createBasicBlock("catch_for_catch"); 3956212904Sdim CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock); 3957212904Sdim 3958212904Sdim CGF.EmitBlock(CatchBlock); 3959212904Sdim } 3960212904Sdim 3961212904Sdim CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar); 3962212904Sdim 3963193326Sed // Handle catch list. As a special case we check if everything is 3964193326Sed // matched and avoid generating code for falling off the end if 3965193326Sed // so. 3966193326Sed bool AllMatched = false; 3967207619Srdivacky for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) { 3968207619Srdivacky const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I); 3969193326Sed 3970207619Srdivacky const VarDecl *CatchParam = CatchStmt->getCatchParamDecl(); 3971198092Srdivacky const ObjCObjectPointerType *OPT = 0; 3972193326Sed 3973193326Sed // catch(...) always matches. 3974193326Sed if (!CatchParam) { 3975193326Sed AllMatched = true; 3976193326Sed } else { 3977198092Srdivacky OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>(); 3978198092Srdivacky 3979210299Sed // catch(id e) always matches under this ABI, since only 3980210299Sed // ObjC exceptions end up here in the first place. 3981193326Sed // FIXME: For the time being we also match id<X>; this should 3982193326Sed // be rejected by Sema instead. 3983198092Srdivacky if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())) 3984193326Sed AllMatched = true; 3985193326Sed } 3986198092Srdivacky 3987210299Sed // If this is a catch-all, we don't need to test anything. 3988198092Srdivacky if (AllMatched) { 3989210299Sed CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF); 3990210299Sed 3991193326Sed if (CatchParam) { 3992218893Sdim CGF.EmitAutoVarDecl(*CatchParam); 3993193326Sed assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); 3994210299Sed 3995210299Sed // These types work out because ConvertType(id) == i8*. 3996193326Sed CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam)); 3997193326Sed } 3998198092Srdivacky 3999193326Sed CGF.EmitStmt(CatchStmt->getCatchBody()); 4000210299Sed 4001210299Sed // The scope of the catch variable ends right here. 4002210299Sed CatchVarCleanups.ForceCleanup(); 4003210299Sed 4004193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 4005193326Sed break; 4006193326Sed } 4007198092Srdivacky 4008198092Srdivacky assert(OPT && "Unexpected non-object pointer type in @catch"); 4009208600Srdivacky const ObjCObjectType *ObjTy = OPT->getObjectType(); 4010210299Sed 4011210299Sed // FIXME: @catch (Class c) ? 4012208600Srdivacky ObjCInterfaceDecl *IDecl = ObjTy->getInterface(); 4013208600Srdivacky assert(IDecl && "Catch parameter must have Objective-C type!"); 4014193326Sed 4015193326Sed // Check if the @catch block matches the exception object. 4016249423Sdim llvm::Value *Class = EmitClassRef(CGF, IDecl); 4017198092Srdivacky 4018249423Sdim llvm::Value *matchArgs[] = { Class, Caught }; 4019210299Sed llvm::CallInst *Match = 4020249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(), 4021249423Sdim matchArgs, "match"); 4022198092Srdivacky 4023210299Sed llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match"); 4024210299Sed llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next"); 4025198092Srdivacky 4026198092Srdivacky CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"), 4027193326Sed MatchedBlock, NextCatchBlock); 4028198092Srdivacky 4029193326Sed // Emit the @catch block. 4030193326Sed CGF.EmitBlock(MatchedBlock); 4031210299Sed 4032210299Sed // Collect any cleanups for the catch variable. The scope lasts until 4033210299Sed // the end of the catch body. 4034212904Sdim CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF); 4035210299Sed 4036218893Sdim CGF.EmitAutoVarDecl(*CatchParam); 4037193326Sed assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); 4038193326Sed 4039210299Sed // Initialize the catch variable. 4040198092Srdivacky llvm::Value *Tmp = 4041198092Srdivacky CGF.Builder.CreateBitCast(Caught, 4042226633Sdim CGF.ConvertType(CatchParam->getType())); 4043193326Sed CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam)); 4044198092Srdivacky 4045193326Sed CGF.EmitStmt(CatchStmt->getCatchBody()); 4046210299Sed 4047210299Sed // We're done with the catch variable. 4048210299Sed CatchVarCleanups.ForceCleanup(); 4049210299Sed 4050193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 4051198092Srdivacky 4052193326Sed CGF.EmitBlock(NextCatchBlock); 4053193326Sed } 4054193326Sed 4055210299Sed CGF.ObjCEHValueStack.pop_back(); 4056210299Sed 4057212904Sdim // If nothing wanted anything to do with the caught exception, 4058212904Sdim // kill the extract call. 4059212904Sdim if (Caught->use_empty()) 4060212904Sdim Caught->eraseFromParent(); 4061212904Sdim 4062212904Sdim if (!AllMatched) 4063193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 4064198092Srdivacky 4065212904Sdim if (HasFinally) { 4066212904Sdim // Emit the exception handler for the @catch blocks. 4067212904Sdim CGF.EmitBlock(CatchHandler); 4068210299Sed 4069212904Sdim // In theory we might now need a write hazard, but actually it's 4070212904Sdim // unnecessary because there's no local-accessing code between 4071212904Sdim // the try's write hazard and here. 4072212904Sdim //Hazards.emitWriteHazard(); 4073210299Sed 4074218893Sdim // Extract the new exception and save it to the 4075218893Sdim // propagating-exception slot. 4076218893Sdim assert(PropagatingExnVar); 4077218893Sdim llvm::CallInst *NewCaught = 4078249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), 4079249423Sdim ExceptionData, "caught"); 4080218893Sdim CGF.Builder.CreateStore(NewCaught, PropagatingExnVar); 4081218893Sdim 4082212904Sdim // Don't pop the catch handler; the throw already did. 4083212904Sdim CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar); 4084212904Sdim CGF.EmitBranchThroughCleanup(FinallyRethrow); 4085212904Sdim } 4086193326Sed } 4087198092Srdivacky 4088212904Sdim // Insert read hazards as required in the new blocks. 4089212904Sdim Hazards.emitHazardsInNewBlocks(); 4090212904Sdim 4091210299Sed // Pop the cleanup. 4092212904Sdim CGF.Builder.restoreIP(TryFallthroughIP); 4093212904Sdim if (CGF.HaveInsertPoint()) 4094212904Sdim CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar); 4095210299Sed CGF.PopCleanupBlock(); 4096212904Sdim CGF.EmitBlock(FinallyEnd.getBlock(), true); 4097193326Sed 4098210299Sed // Emit the rethrow block. 4099212904Sdim CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); 4100212904Sdim CGF.EmitBlock(FinallyRethrow.getBlock(), true); 4101210299Sed if (CGF.HaveInsertPoint()) { 4102218893Sdim // If we have a propagating-exception variable, check it. 4103218893Sdim llvm::Value *PropagatingExn; 4104218893Sdim if (PropagatingExnVar) { 4105218893Sdim PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar); 4106212904Sdim 4107218893Sdim // Otherwise, just look in the buffer for the exception to throw. 4108218893Sdim } else { 4109218893Sdim llvm::CallInst *Caught = 4110249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionExtractFn(), 4111249423Sdim ExceptionData); 4112218893Sdim PropagatingExn = Caught; 4113218893Sdim } 4114218893Sdim 4115249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(), 4116249423Sdim PropagatingExn); 4117210299Sed CGF.Builder.CreateUnreachable(); 4118193326Sed } 4119193326Sed 4120212904Sdim CGF.Builder.restoreIP(SavedIP); 4121193326Sed} 4122193326Sed 4123193326Sedvoid CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 4124249423Sdim const ObjCAtThrowStmt &S, 4125249423Sdim bool ClearInsertionPoint) { 4126193326Sed llvm::Value *ExceptionAsObject; 4127198092Srdivacky 4128193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 4129226633Sdim llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr); 4130198092Srdivacky ExceptionAsObject = 4131226633Sdim CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy); 4132193326Sed } else { 4133198092Srdivacky assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && 4134193326Sed "Unexpected rethrow outside @catch block."); 4135193326Sed ExceptionAsObject = CGF.ObjCEHValueStack.back(); 4136193326Sed } 4137198092Srdivacky 4138249423Sdim CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject) 4139210299Sed ->setDoesNotReturn(); 4140193326Sed CGF.Builder.CreateUnreachable(); 4141193326Sed 4142193326Sed // Clear the insertion point to indicate we are in unreachable code. 4143249423Sdim if (ClearInsertionPoint) 4144249423Sdim CGF.Builder.ClearInsertionPoint(); 4145193326Sed} 4146193326Sed 4147193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak 4148193326Sed/// object: objc_read_weak (id *src) 4149193326Sed/// 4150193326Sedllvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 4151198092Srdivacky llvm::Value *AddrWeakObj) { 4152226633Sdim llvm::Type* DestTy = 4153198092Srdivacky cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); 4154198092Srdivacky AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, 4155198092Srdivacky ObjCTypes.PtrObjectPtrTy); 4156249423Sdim llvm::Value *read_weak = 4157249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), 4158249423Sdim AddrWeakObj, "weakread"); 4159193326Sed read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); 4160193326Sed return read_weak; 4161193326Sed} 4162193326Sed 4163193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. 4164193326Sed/// objc_assign_weak (id src, id *dst) 4165193326Sed/// 4166193326Sedvoid CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 4167198092Srdivacky llvm::Value *src, llvm::Value *dst) { 4168226633Sdim llvm::Type * SrcTy = src->getType(); 4169193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 4170243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 4171193326Sed assert(Size <= 8 && "does not support size > 8"); 4172193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 4173198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 4174193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 4175193326Sed } 4176193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 4177193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 4178249423Sdim llvm::Value *args[] = { src, dst }; 4179249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), 4180249423Sdim args, "weakassign"); 4181193326Sed return; 4182193326Sed} 4183193326Sed 4184193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. 4185193326Sed/// objc_assign_global (id src, id *dst) 4186193326Sed/// 4187193326Sedvoid CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 4188212904Sdim llvm::Value *src, llvm::Value *dst, 4189212904Sdim bool threadlocal) { 4190226633Sdim llvm::Type * SrcTy = src->getType(); 4191193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 4192243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 4193193326Sed assert(Size <= 8 && "does not support size > 8"); 4194193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 4195198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 4196193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 4197193326Sed } 4198193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 4199193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 4200249423Sdim llvm::Value *args[] = { src, dst }; 4201212904Sdim if (!threadlocal) 4202249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), 4203249423Sdim args, "globalassign"); 4204212904Sdim else 4205249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), 4206249423Sdim args, "threadlocalassign"); 4207193326Sed return; 4208193326Sed} 4209193326Sed 4210193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. 4211198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset) 4212193326Sed/// 4213193326Sedvoid CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 4214198092Srdivacky llvm::Value *src, llvm::Value *dst, 4215198092Srdivacky llvm::Value *ivarOffset) { 4216198092Srdivacky assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL"); 4217226633Sdim llvm::Type * SrcTy = src->getType(); 4218193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 4219243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 4220193326Sed assert(Size <= 8 && "does not support size > 8"); 4221193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 4222198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 4223193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 4224193326Sed } 4225193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 4226193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 4227249423Sdim llvm::Value *args[] = { src, dst, ivarOffset }; 4228249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); 4229193326Sed return; 4230193326Sed} 4231193326Sed 4232193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. 4233193326Sed/// objc_assign_strongCast (id src, id *dst) 4234193326Sed/// 4235193326Sedvoid CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 4236198092Srdivacky llvm::Value *src, llvm::Value *dst) { 4237226633Sdim llvm::Type * SrcTy = src->getType(); 4238193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 4239243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 4240193326Sed assert(Size <= 8 && "does not support size > 8"); 4241193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 4242198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 4243193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 4244193326Sed } 4245193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 4246193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 4247249423Sdim llvm::Value *args[] = { src, dst }; 4248249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), 4249249423Sdim args, "weakassign"); 4250193326Sed return; 4251193326Sed} 4252193326Sed 4253198092Srdivackyvoid CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 4254198092Srdivacky llvm::Value *DestPtr, 4255198092Srdivacky llvm::Value *SrcPtr, 4256210299Sed llvm::Value *size) { 4257198092Srdivacky SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); 4258198092Srdivacky DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); 4259249423Sdim llvm::Value *args[] = { DestPtr, SrcPtr, size }; 4260249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); 4261198092Srdivacky} 4262198092Srdivacky 4263193326Sed/// EmitObjCValueForIvar - Code Gen for ivar reference. 4264193326Sed/// 4265193326SedLValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 4266193326Sed QualType ObjectTy, 4267193326Sed llvm::Value *BaseValue, 4268193326Sed const ObjCIvarDecl *Ivar, 4269193326Sed unsigned CVRQualifiers) { 4270208600Srdivacky const ObjCInterfaceDecl *ID = 4271208600Srdivacky ObjectTy->getAs<ObjCObjectType>()->getInterface(); 4272193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 4273193326Sed EmitIvarOffset(CGF, ID, Ivar)); 4274193326Sed} 4275193326Sed 4276193326Sedllvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 4277193326Sed const ObjCInterfaceDecl *Interface, 4278193326Sed const ObjCIvarDecl *Ivar) { 4279193326Sed uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar); 4280193326Sed return llvm::ConstantInt::get( 4281198092Srdivacky CGM.getTypes().ConvertType(CGM.getContext().LongTy), 4282198092Srdivacky Offset); 4283193326Sed} 4284193326Sed 4285193326Sed/* *** Private Interface *** */ 4286193326Sed 4287193326Sed/// EmitImageInfo - Emit the image info marker used to encode some module 4288193326Sed/// level information. 4289193326Sed/// 4290193326Sed/// See: <rdr://4810609&4810587&4810587> 4291193326Sed/// struct IMAGE_INFO { 4292193326Sed/// unsigned version; 4293193326Sed/// unsigned flags; 4294193326Sed/// }; 4295193326Sedenum ImageInfoFlags { 4296207619Srdivacky eImageInfo_FixAndContinue = (1 << 0), 4297198092Srdivacky eImageInfo_GarbageCollected = (1 << 1), 4298198092Srdivacky eImageInfo_GCOnly = (1 << 2), 4299193326Sed eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set. 4300193326Sed 4301207619Srdivacky // A flag indicating that the module has no instances of a @synthesize of a 4302207619Srdivacky // superclass variable. <rdar://problem/6803242> 4303239462Sdim eImageInfo_CorrectedSynthesize = (1 << 4), 4304239462Sdim eImageInfo_ImageIsSimulated = (1 << 5) 4305193326Sed}; 4306193326Sed 4307207619Srdivackyvoid CGObjCCommonMac::EmitImageInfo() { 4308193326Sed unsigned version = 0; // Version is unused? 4309234353Sdim const char *Section = (ObjCABI == 1) ? 4310234353Sdim "__OBJC, __image_info,regular" : 4311234353Sdim "__DATA, __objc_imageinfo, regular, no_dead_strip"; 4312193326Sed 4313234353Sdim // Generate module-level named metadata to convey this information to the 4314234353Sdim // linker and code-gen. 4315234353Sdim llvm::Module &Mod = CGM.getModule(); 4316198092Srdivacky 4317234353Sdim // Add the ObjC ABI version to the module flags. 4318234353Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI); 4319234353Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version", 4320234353Sdim version); 4321234353Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section", 4322234353Sdim llvm::MDString::get(VMContext,Section)); 4323193326Sed 4324234353Sdim if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { 4325234353Sdim // Non-GC overrides those files which specify GC. 4326234353Sdim Mod.addModuleFlag(llvm::Module::Override, 4327234353Sdim "Objective-C Garbage Collection", (uint32_t)0); 4328234353Sdim } else { 4329234353Sdim // Add the ObjC garbage collection value. 4330234353Sdim Mod.addModuleFlag(llvm::Module::Error, 4331234353Sdim "Objective-C Garbage Collection", 4332234353Sdim eImageInfo_GarbageCollected); 4333193326Sed 4334234353Sdim if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { 4335234353Sdim // Add the ObjC GC Only value. 4336234353Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only", 4337234353Sdim eImageInfo_GCOnly); 4338234353Sdim 4339234353Sdim // Require that GC be specified and set to eImageInfo_GarbageCollected. 4340234353Sdim llvm::Value *Ops[2] = { 4341234353Sdim llvm::MDString::get(VMContext, "Objective-C Garbage Collection"), 4342234353Sdim llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 4343234353Sdim eImageInfo_GarbageCollected) 4344234353Sdim }; 4345234353Sdim Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only", 4346234353Sdim llvm::MDNode::get(VMContext, Ops)); 4347234353Sdim } 4348234353Sdim } 4349239462Sdim 4350239462Sdim // Indicate whether we're compiling this to run on a simulator. 4351239462Sdim const llvm::Triple &Triple = CGM.getTarget().getTriple(); 4352263508Sdim if (Triple.isiOS() && 4353239462Sdim (Triple.getArch() == llvm::Triple::x86 || 4354239462Sdim Triple.getArch() == llvm::Triple::x86_64)) 4355239462Sdim Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated", 4356239462Sdim eImageInfo_ImageIsSimulated); 4357193326Sed} 4358193326Sed 4359193326Sed// struct objc_module { 4360193326Sed// unsigned long version; 4361193326Sed// unsigned long size; 4362193326Sed// const char *name; 4363193326Sed// Symtab symtab; 4364193326Sed// }; 4365193326Sed 4366193326Sed// FIXME: Get from somewhere 4367193326Sedstatic const int ModuleVersion = 7; 4368193326Sed 4369193326Sedvoid CGObjCMac::EmitModuleInfo() { 4370243830Sdim uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy); 4371198092Srdivacky 4372234353Sdim llvm::Constant *Values[] = { 4373234353Sdim llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion), 4374234353Sdim llvm::ConstantInt::get(ObjCTypes.LongTy, Size), 4375234353Sdim // This used to be the filename, now it is unused. <rdr://4327263> 4376234353Sdim GetClassName(&CGM.getContext().Idents.get("")), 4377234353Sdim EmitModuleSymbols() 4378234353Sdim }; 4379198092Srdivacky CreateMetadataVar("\01L_OBJC_MODULES", 4380193326Sed llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values), 4381193326Sed "__OBJC,__module_info,regular,no_dead_strip", 4382193326Sed 4, true); 4383193326Sed} 4384193326Sed 4385193326Sedllvm::Constant *CGObjCMac::EmitModuleSymbols() { 4386193326Sed unsigned NumClasses = DefinedClasses.size(); 4387193326Sed unsigned NumCategories = DefinedCategories.size(); 4388193326Sed 4389193326Sed // Return null if no symbols were defined. 4390193326Sed if (!NumClasses && !NumCategories) 4391193326Sed return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy); 4392193326Sed 4393224145Sdim llvm::Constant *Values[5]; 4394193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 4395193326Sed Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy); 4396193326Sed Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses); 4397193326Sed Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories); 4398193326Sed 4399193326Sed // The runtime expects exactly the list of defined classes followed 4400193326Sed // by the list of defined categories, in a single array. 4401234353Sdim SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories); 4402193326Sed for (unsigned i=0; i<NumClasses; i++) 4403193326Sed Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i], 4404193326Sed ObjCTypes.Int8PtrTy); 4405193326Sed for (unsigned i=0; i<NumCategories; i++) 4406198092Srdivacky Symbols[NumClasses + i] = 4407193326Sed llvm::ConstantExpr::getBitCast(DefinedCategories[i], 4408193326Sed ObjCTypes.Int8PtrTy); 4409193326Sed 4410198092Srdivacky Values[4] = 4411193326Sed llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 4412234353Sdim Symbols.size()), 4413193326Sed Symbols); 4414193326Sed 4415224145Sdim llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values); 4416193326Sed 4417193326Sed llvm::GlobalVariable *GV = 4418193326Sed CreateMetadataVar("\01L_OBJC_SYMBOLS", Init, 4419193326Sed "__OBJC,__symbols,regular,no_dead_strip", 4420193326Sed 4, true); 4421193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy); 4422193326Sed} 4423193326Sed 4424249423Sdimllvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF, 4425249423Sdim IdentifierInfo *II) { 4426224145Sdim LazySymbols.insert(II); 4427224145Sdim 4428224145Sdim llvm::GlobalVariable *&Entry = ClassReferences[II]; 4429224145Sdim 4430193326Sed if (!Entry) { 4431198092Srdivacky llvm::Constant *Casted = 4432224145Sdim llvm::ConstantExpr::getBitCast(GetClassName(II), 4433224145Sdim ObjCTypes.ClassPtrTy); 4434198092Srdivacky Entry = 4435224145Sdim CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted, 4436224145Sdim "__OBJC,__cls_refs,literal_pointers,no_dead_strip", 4437224145Sdim 4, true); 4438193326Sed } 4439224145Sdim 4440249423Sdim return CGF.Builder.CreateLoad(Entry); 4441193326Sed} 4442193326Sed 4443249423Sdimllvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF, 4444224145Sdim const ObjCInterfaceDecl *ID) { 4445249423Sdim return EmitClassRefFromId(CGF, ID->getIdentifier()); 4446224145Sdim} 4447224145Sdim 4448249423Sdimllvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { 4449224145Sdim IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool"); 4450249423Sdim return EmitClassRefFromId(CGF, II); 4451224145Sdim} 4452224145Sdim 4453249423Sdimllvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel, 4454210299Sed bool lvalue) { 4455193326Sed llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; 4456198092Srdivacky 4457193326Sed if (!Entry) { 4458198092Srdivacky llvm::Constant *Casted = 4459193326Sed llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), 4460193326Sed ObjCTypes.SelectorPtrTy); 4461198092Srdivacky Entry = 4462193326Sed CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted, 4463193326Sed "__OBJC,__message_refs,literal_pointers,no_dead_strip", 4464193326Sed 4, true); 4465249423Sdim Entry->setExternallyInitialized(true); 4466193326Sed } 4467193326Sed 4468210299Sed if (lvalue) 4469210299Sed return Entry; 4470249423Sdim return CGF.Builder.CreateLoad(Entry); 4471193326Sed} 4472193326Sed 4473193326Sedllvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) { 4474193326Sed llvm::GlobalVariable *&Entry = ClassNames[Ident]; 4475193326Sed 4476193326Sed if (!Entry) 4477198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", 4478234353Sdim llvm::ConstantDataArray::getString(VMContext, 4479234353Sdim Ident->getNameStart()), 4480221345Sdim ((ObjCABI == 2) ? 4481221345Sdim "__TEXT,__objc_classname,cstring_literals" : 4482221345Sdim "__TEXT,__cstring,cstring_literals"), 4483193326Sed 1, true); 4484193326Sed 4485198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 4486193326Sed} 4487193326Sed 4488212904Sdimllvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) { 4489212904Sdim llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator 4490212904Sdim I = MethodDefinitions.find(MD); 4491212904Sdim if (I != MethodDefinitions.end()) 4492212904Sdim return I->second; 4493212904Sdim 4494212904Sdim return NULL; 4495212904Sdim} 4496212904Sdim 4497193326Sed/// GetIvarLayoutName - Returns a unique constant for the given 4498193326Sed/// ivar layout bitmap. 4499193326Sedllvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, 4500198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 4501193326Sed return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 4502193326Sed} 4503193326Sed 4504193326Sedvoid CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT, 4505198092Srdivacky unsigned int BytePos, 4506193326Sed bool ForStrongLayout, 4507193326Sed bool &HasUnion) { 4508193326Sed const RecordDecl *RD = RT->getDecl(); 4509193326Sed // FIXME - Use iterator. 4510239462Sdim SmallVector<const FieldDecl*, 16> Fields; 4511239462Sdim for (RecordDecl::field_iterator i = RD->field_begin(), 4512239462Sdim e = RD->field_end(); i != e; ++i) 4513239462Sdim Fields.push_back(*i); 4514226633Sdim llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); 4515198092Srdivacky const llvm::StructLayout *RecLayout = 4516243830Sdim CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty)); 4517198092Srdivacky 4518193326Sed BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos, 4519193326Sed ForStrongLayout, HasUnion); 4520193326Sed} 4521193326Sed 4522193326Sedvoid CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, 4523198092Srdivacky const llvm::StructLayout *Layout, 4524198092Srdivacky const RecordDecl *RD, 4525234353Sdim ArrayRef<const FieldDecl*> RecFields, 4526198092Srdivacky unsigned int BytePos, bool ForStrongLayout, 4527198092Srdivacky bool &HasUnion) { 4528193326Sed bool IsUnion = (RD && RD->isUnion()); 4529193326Sed uint64_t MaxUnionIvarSize = 0; 4530193326Sed uint64_t MaxSkippedUnionIvarSize = 0; 4531226633Sdim const FieldDecl *MaxField = 0; 4532226633Sdim const FieldDecl *MaxSkippedField = 0; 4533226633Sdim const FieldDecl *LastFieldBitfieldOrUnnamed = 0; 4534193326Sed uint64_t MaxFieldOffset = 0; 4535193326Sed uint64_t MaxSkippedFieldOffset = 0; 4536218893Sdim uint64_t LastBitfieldOrUnnamedOffset = 0; 4537224145Sdim uint64_t FirstFieldDelta = 0; 4538198092Srdivacky 4539193326Sed if (RecFields.empty()) 4540193326Sed return; 4541251662Sdim unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); 4542251662Sdim unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); 4543234353Sdim if (!RD && CGM.getLangOpts().ObjCAutoRefCount) { 4544226633Sdim const FieldDecl *FirstField = RecFields[0]; 4545224145Sdim FirstFieldDelta = 4546224145Sdim ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField)); 4547224145Sdim } 4548224145Sdim 4549193326Sed for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { 4550226633Sdim const FieldDecl *Field = RecFields[i]; 4551193326Sed uint64_t FieldOffset; 4552198092Srdivacky if (RD) { 4553207619Srdivacky // Note that 'i' here is actually the field index inside RD of Field, 4554207619Srdivacky // although this dependency is hidden. 4555207619Srdivacky const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); 4556224145Sdim FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta; 4557198092Srdivacky } else 4558224145Sdim FieldOffset = 4559224145Sdim ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta; 4560193326Sed 4561193326Sed // Skip over unnamed or bitfields 4562193326Sed if (!Field->getIdentifier() || Field->isBitField()) { 4563218893Sdim LastFieldBitfieldOrUnnamed = Field; 4564218893Sdim LastBitfieldOrUnnamedOffset = FieldOffset; 4565193326Sed continue; 4566193326Sed } 4567193326Sed 4568218893Sdim LastFieldBitfieldOrUnnamed = 0; 4569193326Sed QualType FQT = Field->getType(); 4570193326Sed if (FQT->isRecordType() || FQT->isUnionType()) { 4571193326Sed if (FQT->isUnionType()) 4572193326Sed HasUnion = true; 4573193326Sed 4574198092Srdivacky BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(), 4575193326Sed BytePos + FieldOffset, 4576193326Sed ForStrongLayout, HasUnion); 4577193326Sed continue; 4578193326Sed } 4579198092Srdivacky 4580193326Sed if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 4581198092Srdivacky const ConstantArrayType *CArray = 4582193326Sed dyn_cast_or_null<ConstantArrayType>(Array); 4583193326Sed uint64_t ElCount = CArray->getSize().getZExtValue(); 4584193326Sed assert(CArray && "only array with known element size is supported"); 4585193326Sed FQT = CArray->getElementType(); 4586193326Sed while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 4587193326Sed const ConstantArrayType *CArray = 4588193326Sed dyn_cast_or_null<ConstantArrayType>(Array); 4589193326Sed ElCount *= CArray->getSize().getZExtValue(); 4590193326Sed FQT = CArray->getElementType(); 4591193326Sed } 4592198092Srdivacky 4593198092Srdivacky assert(!FQT->isUnionType() && 4594193326Sed "layout for array of unions not supported"); 4595218893Sdim if (FQT->isRecordType() && ElCount) { 4596193326Sed int OldIndex = IvarsInfo.size() - 1; 4597193326Sed int OldSkIndex = SkipIvars.size() -1; 4598198092Srdivacky 4599198092Srdivacky const RecordType *RT = FQT->getAs<RecordType>(); 4600193326Sed BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset, 4601193326Sed ForStrongLayout, HasUnion); 4602198092Srdivacky 4603193326Sed // Replicate layout information for each array element. Note that 4604193326Sed // one element is already done. 4605193326Sed uint64_t ElIx = 1; 4606198092Srdivacky for (int FirstIndex = IvarsInfo.size() - 1, 4607198092Srdivacky FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) { 4608193326Sed uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits; 4609193326Sed for (int i = OldIndex+1; i <= FirstIndex; ++i) 4610193326Sed IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx, 4611193326Sed IvarsInfo[i].ivar_size)); 4612193326Sed for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i) 4613193326Sed SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx, 4614193326Sed SkipIvars[i].ivar_size)); 4615193326Sed } 4616193326Sed continue; 4617193326Sed } 4618193326Sed } 4619193326Sed // At this point, we are done with Record/Union and array there of. 4620193326Sed // For other arrays we are down to its element type. 4621198092Srdivacky Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT); 4622193326Sed 4623193326Sed unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType()); 4624198092Srdivacky if ((ForStrongLayout && GCAttr == Qualifiers::Strong) 4625198092Srdivacky || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) { 4626193326Sed if (IsUnion) { 4627193326Sed uint64_t UnionIvarSize = FieldSize / WordSizeInBits; 4628193326Sed if (UnionIvarSize > MaxUnionIvarSize) { 4629193326Sed MaxUnionIvarSize = UnionIvarSize; 4630193326Sed MaxField = Field; 4631193326Sed MaxFieldOffset = FieldOffset; 4632193326Sed } 4633193326Sed } else { 4634193326Sed IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset, 4635193326Sed FieldSize / WordSizeInBits)); 4636193326Sed } 4637198092Srdivacky } else if ((ForStrongLayout && 4638198092Srdivacky (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)) 4639198092Srdivacky || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) { 4640193326Sed if (IsUnion) { 4641193326Sed // FIXME: Why the asymmetry? We divide by word size in bits on other 4642193326Sed // side. 4643243830Sdim uint64_t UnionIvarSize = FieldSize / ByteSizeInBits; 4644193326Sed if (UnionIvarSize > MaxSkippedUnionIvarSize) { 4645193326Sed MaxSkippedUnionIvarSize = UnionIvarSize; 4646193326Sed MaxSkippedField = Field; 4647193326Sed MaxSkippedFieldOffset = FieldOffset; 4648193326Sed } 4649193326Sed } else { 4650193326Sed // FIXME: Why the asymmetry, we divide by byte size in bits here? 4651193326Sed SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset, 4652193326Sed FieldSize / ByteSizeInBits)); 4653193326Sed } 4654193326Sed } 4655193326Sed } 4656193326Sed 4657218893Sdim if (LastFieldBitfieldOrUnnamed) { 4658218893Sdim if (LastFieldBitfieldOrUnnamed->isBitField()) { 4659218893Sdim // Last field was a bitfield. Must update skip info. 4660226633Sdim uint64_t BitFieldSize 4661226633Sdim = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext()); 4662218893Sdim GC_IVAR skivar; 4663218893Sdim skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset; 4664218893Sdim skivar.ivar_size = (BitFieldSize / ByteSizeInBits) 4665218893Sdim + ((BitFieldSize % ByteSizeInBits) != 0); 4666218893Sdim SkipIvars.push_back(skivar); 4667218893Sdim } else { 4668218893Sdim assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed"); 4669218893Sdim // Last field was unnamed. Must update skip info. 4670218893Sdim unsigned FieldSize 4671218893Sdim = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType()); 4672218893Sdim SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset, 4673218893Sdim FieldSize / ByteSizeInBits)); 4674218893Sdim } 4675193326Sed } 4676198092Srdivacky 4677193326Sed if (MaxField) 4678198092Srdivacky IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset, 4679193326Sed MaxUnionIvarSize)); 4680193326Sed if (MaxSkippedField) 4681193326Sed SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset, 4682193326Sed MaxSkippedUnionIvarSize)); 4683193326Sed} 4684193326Sed 4685212904Sdim/// BuildIvarLayoutBitmap - This routine is the horsework for doing all 4686212904Sdim/// the computations and returning the layout bitmap (for ivar or blocks) in 4687212904Sdim/// the given argument BitMap string container. Routine reads 4688212904Sdim/// two containers, IvarsInfo and SkipIvars which are assumed to be 4689212904Sdim/// filled already by the caller. 4690234353Sdimllvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) { 4691193326Sed unsigned int WordsToScan, WordsToSkip; 4692234353Sdim llvm::Type *PtrTy = CGM.Int8PtrTy; 4693212904Sdim 4694193326Sed // Build the string of skip/scan nibbles 4695226633Sdim SmallVector<SKIP_SCAN, 32> SkipScanIvars; 4696198092Srdivacky unsigned int WordSize = 4697243830Sdim CGM.getTypes().getDataLayout().getTypeAllocSize(PtrTy); 4698193326Sed if (IvarsInfo[0].ivar_bytepos == 0) { 4699193326Sed WordsToSkip = 0; 4700193326Sed WordsToScan = IvarsInfo[0].ivar_size; 4701193326Sed } else { 4702193326Sed WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize; 4703193326Sed WordsToScan = IvarsInfo[0].ivar_size; 4704193326Sed } 4705193326Sed for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) { 4706198092Srdivacky unsigned int TailPrevGCObjC = 4707212904Sdim IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize; 4708193326Sed if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) { 4709193326Sed // consecutive 'scanned' object pointers. 4710193326Sed WordsToScan += IvarsInfo[i].ivar_size; 4711193326Sed } else { 4712193326Sed // Skip over 'gc'able object pointer which lay over each other. 4713193326Sed if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos) 4714193326Sed continue; 4715193326Sed // Must skip over 1 or more words. We save current skip/scan values 4716193326Sed // and start a new pair. 4717193326Sed SKIP_SCAN SkScan; 4718193326Sed SkScan.skip = WordsToSkip; 4719193326Sed SkScan.scan = WordsToScan; 4720193326Sed SkipScanIvars.push_back(SkScan); 4721212904Sdim 4722193326Sed // Skip the hole. 4723193326Sed SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize; 4724193326Sed SkScan.scan = 0; 4725193326Sed SkipScanIvars.push_back(SkScan); 4726193326Sed WordsToSkip = 0; 4727193326Sed WordsToScan = IvarsInfo[i].ivar_size; 4728193326Sed } 4729193326Sed } 4730193326Sed if (WordsToScan > 0) { 4731193326Sed SKIP_SCAN SkScan; 4732193326Sed SkScan.skip = WordsToSkip; 4733193326Sed SkScan.scan = WordsToScan; 4734193326Sed SkipScanIvars.push_back(SkScan); 4735193326Sed } 4736212904Sdim 4737193326Sed if (!SkipIvars.empty()) { 4738193326Sed unsigned int LastIndex = SkipIvars.size()-1; 4739198092Srdivacky int LastByteSkipped = 4740212904Sdim SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size; 4741193326Sed LastIndex = IvarsInfo.size()-1; 4742198092Srdivacky int LastByteScanned = 4743212904Sdim IvarsInfo[LastIndex].ivar_bytepos + 4744212904Sdim IvarsInfo[LastIndex].ivar_size * WordSize; 4745193326Sed // Compute number of bytes to skip at the tail end of the last ivar scanned. 4746201361Srdivacky if (LastByteSkipped > LastByteScanned) { 4747193326Sed unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize; 4748193326Sed SKIP_SCAN SkScan; 4749193326Sed SkScan.skip = TotalWords - (LastByteScanned/WordSize); 4750193326Sed SkScan.scan = 0; 4751193326Sed SkipScanIvars.push_back(SkScan); 4752193326Sed } 4753193326Sed } 4754193326Sed // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced 4755193326Sed // as 0xMN. 4756193326Sed int SkipScan = SkipScanIvars.size()-1; 4757193326Sed for (int i = 0; i <= SkipScan; i++) { 4758193326Sed if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0 4759193326Sed && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) { 4760193326Sed // 0xM0 followed by 0x0N detected. 4761193326Sed SkipScanIvars[i].scan = SkipScanIvars[i+1].scan; 4762193326Sed for (int j = i+1; j < SkipScan; j++) 4763193326Sed SkipScanIvars[j] = SkipScanIvars[j+1]; 4764193326Sed --SkipScan; 4765193326Sed } 4766193326Sed } 4767212904Sdim 4768193326Sed // Generate the string. 4769193326Sed for (int i = 0; i <= SkipScan; i++) { 4770193326Sed unsigned char byte; 4771193326Sed unsigned int skip_small = SkipScanIvars[i].skip % 0xf; 4772193326Sed unsigned int scan_small = SkipScanIvars[i].scan % 0xf; 4773193326Sed unsigned int skip_big = SkipScanIvars[i].skip / 0xf; 4774193326Sed unsigned int scan_big = SkipScanIvars[i].scan / 0xf; 4775212904Sdim 4776193326Sed // first skip big. 4777193326Sed for (unsigned int ix = 0; ix < skip_big; ix++) 4778193326Sed BitMap += (unsigned char)(0xf0); 4779212904Sdim 4780193326Sed // next (skip small, scan) 4781193326Sed if (skip_small) { 4782193326Sed byte = skip_small << 4; 4783193326Sed if (scan_big > 0) { 4784193326Sed byte |= 0xf; 4785193326Sed --scan_big; 4786193326Sed } else if (scan_small) { 4787193326Sed byte |= scan_small; 4788193326Sed scan_small = 0; 4789193326Sed } 4790193326Sed BitMap += byte; 4791193326Sed } 4792193326Sed // next scan big 4793193326Sed for (unsigned int ix = 0; ix < scan_big; ix++) 4794193326Sed BitMap += (unsigned char)(0x0f); 4795193326Sed // last scan small 4796193326Sed if (scan_small) { 4797193326Sed byte = scan_small; 4798193326Sed BitMap += byte; 4799193326Sed } 4800193326Sed } 4801193326Sed // null terminate string. 4802193326Sed unsigned char zero = 0; 4803193326Sed BitMap += zero; 4804212904Sdim 4805212904Sdim llvm::GlobalVariable * Entry = 4806212904Sdim CreateMetadataVar("\01L_OBJC_CLASS_NAME_", 4807234353Sdim llvm::ConstantDataArray::getString(VMContext, BitMap,false), 4808221345Sdim ((ObjCABI == 2) ? 4809221345Sdim "__TEXT,__objc_classname,cstring_literals" : 4810221345Sdim "__TEXT,__cstring,cstring_literals"), 4811212904Sdim 1, true); 4812212904Sdim return getConstantGEP(VMContext, Entry, 0, 0); 4813212904Sdim} 4814198092Srdivacky 4815212904Sdim/// BuildIvarLayout - Builds ivar layout bitmap for the class 4816212904Sdim/// implementation for the __strong or __weak case. 4817212904Sdim/// The layout map displays which words in ivar list must be skipped 4818212904Sdim/// and which must be scanned by GC (see below). String is built of bytes. 4819212904Sdim/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count 4820212904Sdim/// of words to skip and right nibble is count of words to scan. So, each 4821212904Sdim/// nibble represents up to 15 workds to skip or scan. Skipping the rest is 4822212904Sdim/// represented by a 0x00 byte which also ends the string. 4823212904Sdim/// 1. when ForStrongLayout is true, following ivars are scanned: 4824212904Sdim/// - id, Class 4825212904Sdim/// - object * 4826212904Sdim/// - __strong anything 4827212904Sdim/// 4828212904Sdim/// 2. When ForStrongLayout is false, following ivars are scanned: 4829212904Sdim/// - __weak anything 4830212904Sdim/// 4831212904Sdimllvm::Constant *CGObjCCommonMac::BuildIvarLayout( 4832212904Sdim const ObjCImplementationDecl *OMD, 4833212904Sdim bool ForStrongLayout) { 4834212904Sdim bool hasUnion = false; 4835212904Sdim 4836234353Sdim llvm::Type *PtrTy = CGM.Int8PtrTy; 4837234353Sdim if (CGM.getLangOpts().getGC() == LangOptions::NonGC && 4838234353Sdim !CGM.getLangOpts().ObjCAutoRefCount) 4839212904Sdim return llvm::Constant::getNullValue(PtrTy); 4840212904Sdim 4841226633Sdim const ObjCInterfaceDecl *OI = OMD->getClassInterface(); 4842226633Sdim SmallVector<const FieldDecl*, 32> RecFields; 4843234353Sdim if (CGM.getLangOpts().ObjCAutoRefCount) { 4844226633Sdim for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); 4845224145Sdim IVD; IVD = IVD->getNextIvar()) 4846224145Sdim RecFields.push_back(cast<FieldDecl>(IVD)); 4847224145Sdim } 4848224145Sdim else { 4849226633Sdim SmallVector<const ObjCIvarDecl*, 32> Ivars; 4850224145Sdim CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars); 4851212904Sdim 4852226633Sdim // FIXME: This is not ideal; we shouldn't have to do this copy. 4853226633Sdim RecFields.append(Ivars.begin(), Ivars.end()); 4854224145Sdim } 4855224145Sdim 4856212904Sdim if (RecFields.empty()) 4857212904Sdim return llvm::Constant::getNullValue(PtrTy); 4858212904Sdim 4859212904Sdim SkipIvars.clear(); 4860212904Sdim IvarsInfo.clear(); 4861212904Sdim 4862212904Sdim BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion); 4863212904Sdim if (IvarsInfo.empty()) 4864212904Sdim return llvm::Constant::getNullValue(PtrTy); 4865212904Sdim // Sort on byte position in case we encounterred a union nested in 4866212904Sdim // the ivar list. 4867212904Sdim if (hasUnion && !IvarsInfo.empty()) 4868212904Sdim std::sort(IvarsInfo.begin(), IvarsInfo.end()); 4869212904Sdim if (hasUnion && !SkipIvars.empty()) 4870212904Sdim std::sort(SkipIvars.begin(), SkipIvars.end()); 4871212904Sdim 4872212904Sdim std::string BitMap; 4873212904Sdim llvm::Constant *C = BuildIvarLayoutBitmap(BitMap); 4874212904Sdim 4875234353Sdim if (CGM.getLangOpts().ObjCGCBitmapPrint) { 4876198092Srdivacky printf("\n%s ivar layout for class '%s': ", 4877193326Sed ForStrongLayout ? "strong" : "weak", 4878212904Sdim OMD->getClassInterface()->getName().data()); 4879243830Sdim const unsigned char *s = (const unsigned char*)BitMap.c_str(); 4880234353Sdim for (unsigned i = 0, e = BitMap.size(); i < e; i++) 4881193326Sed if (!(s[i] & 0xf0)) 4882193326Sed printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); 4883193326Sed else 4884193326Sed printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); 4885193326Sed printf("\n"); 4886193326Sed } 4887212904Sdim return C; 4888193326Sed} 4889193326Sed 4890193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) { 4891193326Sed llvm::GlobalVariable *&Entry = MethodVarNames[Sel]; 4892193326Sed 4893234353Sdim // FIXME: Avoid std::string in "Sel.getAsString()" 4894193326Sed if (!Entry) 4895198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_", 4896234353Sdim llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()), 4897221345Sdim ((ObjCABI == 2) ? 4898221345Sdim "__TEXT,__objc_methname,cstring_literals" : 4899221345Sdim "__TEXT,__cstring,cstring_literals"), 4900193326Sed 1, true); 4901193326Sed 4902198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 4903193326Sed} 4904193326Sed 4905193326Sed// FIXME: Merge into a single cstring creation function. 4906193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) { 4907193326Sed return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID)); 4908193326Sed} 4909193326Sed 4910193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) { 4911193326Sed std::string TypeStr; 4912193326Sed CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field); 4913193326Sed 4914193326Sed llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; 4915193326Sed 4916193326Sed if (!Entry) 4917193326Sed Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", 4918234353Sdim llvm::ConstantDataArray::getString(VMContext, TypeStr), 4919221345Sdim ((ObjCABI == 2) ? 4920221345Sdim "__TEXT,__objc_methtype,cstring_literals" : 4921221345Sdim "__TEXT,__cstring,cstring_literals"), 4922193326Sed 1, true); 4923198092Srdivacky 4924198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 4925193326Sed} 4926193326Sed 4927234353Sdimllvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D, 4928234353Sdim bool Extended) { 4929193326Sed std::string TypeStr; 4930234353Sdim if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended)) 4931223017Sdim return 0; 4932193326Sed 4933193326Sed llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; 4934193326Sed 4935193326Sed if (!Entry) 4936193326Sed Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", 4937234353Sdim llvm::ConstantDataArray::getString(VMContext, TypeStr), 4938221345Sdim ((ObjCABI == 2) ? 4939221345Sdim "__TEXT,__objc_methtype,cstring_literals" : 4940221345Sdim "__TEXT,__cstring,cstring_literals"), 4941193326Sed 1, true); 4942193326Sed 4943198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 4944193326Sed} 4945193326Sed 4946193326Sed// FIXME: Merge into a single cstring creation function. 4947193326Sedllvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) { 4948193326Sed llvm::GlobalVariable *&Entry = PropertyNames[Ident]; 4949198092Srdivacky 4950193326Sed if (!Entry) 4951198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_", 4952234353Sdim llvm::ConstantDataArray::getString(VMContext, 4953234353Sdim Ident->getNameStart()), 4954193326Sed "__TEXT,__cstring,cstring_literals", 4955193326Sed 1, true); 4956193326Sed 4957198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 4958193326Sed} 4959193326Sed 4960193326Sed// FIXME: Merge into a single cstring creation function. 4961193326Sed// FIXME: This Decl should be more precise. 4962193326Sedllvm::Constant * 4963198092SrdivackyCGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD, 4964198092Srdivacky const Decl *Container) { 4965193326Sed std::string TypeStr; 4966193326Sed CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr); 4967193326Sed return GetPropertyName(&CGM.getContext().Idents.get(TypeStr)); 4968193326Sed} 4969193326Sed 4970198092Srdivackyvoid CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D, 4971193326Sed const ObjCContainerDecl *CD, 4972226633Sdim SmallVectorImpl<char> &Name) { 4973198398Srdivacky llvm::raw_svector_ostream OS(Name); 4974193326Sed assert (CD && "Missing container decl in GetNameForMethod"); 4975198398Srdivacky OS << '\01' << (D->isInstanceMethod() ? '-' : '+') 4976198398Srdivacky << '[' << CD->getName(); 4977198092Srdivacky if (const ObjCCategoryImplDecl *CID = 4978198398Srdivacky dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) 4979234353Sdim OS << '(' << *CID << ')'; 4980198398Srdivacky OS << ' ' << D->getSelector().getAsString() << ']'; 4981193326Sed} 4982193326Sed 4983193326Sedvoid CGObjCMac::FinishModule() { 4984193326Sed EmitModuleInfo(); 4985193326Sed 4986193326Sed // Emit the dummy bodies for any protocols which were referenced but 4987193326Sed // never defined. 4988198092Srdivacky for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator 4989198092Srdivacky I = Protocols.begin(), e = Protocols.end(); I != e; ++I) { 4990198092Srdivacky if (I->second->hasInitializer()) 4991193326Sed continue; 4992193326Sed 4993234353Sdim llvm::Constant *Values[5]; 4994193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); 4995198092Srdivacky Values[1] = GetClassName(I->first); 4996193326Sed Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 4997193326Sed Values[3] = Values[4] = 4998193326Sed llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); 4999198092Srdivacky I->second->setLinkage(llvm::GlobalValue::InternalLinkage); 5000198092Srdivacky I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, 5001193326Sed Values)); 5002198092Srdivacky CGM.AddUsedGlobal(I->second); 5003193326Sed } 5004193326Sed 5005193326Sed // Add assembler directives to add lazy undefined symbol references 5006193326Sed // for classes which are referenced but not defined. This is 5007193326Sed // important for correct linker interaction. 5008198092Srdivacky // 5009198092Srdivacky // FIXME: It would be nice if we had an LLVM construct for this. 5010198092Srdivacky if (!LazySymbols.empty() || !DefinedSymbols.empty()) { 5011234353Sdim SmallString<256> Asm; 5012198092Srdivacky Asm += CGM.getModule().getModuleInlineAsm(); 5013198092Srdivacky if (!Asm.empty() && Asm.back() != '\n') 5014198092Srdivacky Asm += '\n'; 5015193326Sed 5016198092Srdivacky llvm::raw_svector_ostream OS(Asm); 5017198092Srdivacky for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(), 5018198092Srdivacky e = DefinedSymbols.end(); I != e; ++I) 5019198092Srdivacky OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n" 5020198092Srdivacky << "\t.globl .objc_class_name_" << (*I)->getName() << "\n"; 5021207619Srdivacky for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(), 5022210299Sed e = LazySymbols.end(); I != e; ++I) { 5023207619Srdivacky OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n"; 5024210299Sed } 5025210299Sed 5026234353Sdim for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) { 5027210299Sed OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n" 5028210299Sed << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n"; 5029210299Sed } 5030207619Srdivacky 5031198092Srdivacky CGM.getModule().setModuleInlineAsm(OS.str()); 5032193326Sed } 5033193326Sed} 5034193326Sed 5035198092SrdivackyCGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm) 5036193326Sed : CGObjCCommonMac(cgm), 5037198092Srdivacky ObjCTypes(cgm) { 5038193326Sed ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL; 5039193326Sed ObjCABI = 2; 5040193326Sed} 5041193326Sed 5042193326Sed/* *** */ 5043193326Sed 5044193326SedObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) 5045234353Sdim : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(0) 5046234353Sdim{ 5047193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 5048193326Sed ASTContext &Ctx = CGM.getContext(); 5049198092Srdivacky 5050193326Sed ShortTy = Types.ConvertType(Ctx.ShortTy); 5051193326Sed IntTy = Types.ConvertType(Ctx.IntTy); 5052193326Sed LongTy = Types.ConvertType(Ctx.LongTy); 5053193326Sed LongLongTy = Types.ConvertType(Ctx.LongLongTy); 5054234353Sdim Int8PtrTy = CGM.Int8PtrTy; 5055234353Sdim Int8PtrPtrTy = CGM.Int8PtrPtrTy; 5056198092Srdivacky 5057193326Sed ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType()); 5058193326Sed PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy); 5059193326Sed SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType()); 5060198092Srdivacky 5061193326Sed // I'm not sure I like this. The implicit coordination is a bit 5062193326Sed // gross. We should solve this in a reasonable fashion because this 5063193326Sed // is a pretty common task (match some runtime data structure with 5064193326Sed // an LLVM data structure). 5065198092Srdivacky 5066193326Sed // FIXME: This is leaked. 5067193326Sed // FIXME: Merge with rewriter code? 5068198092Srdivacky 5069193326Sed // struct _objc_super { 5070193326Sed // id self; 5071193326Sed // Class cls; 5072193326Sed // } 5073208600Srdivacky RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, 5074207619Srdivacky Ctx.getTranslationUnitDecl(), 5075221345Sdim SourceLocation(), SourceLocation(), 5076198092Srdivacky &Ctx.Idents.get("_objc_super")); 5077221345Sdim RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0, 5078239462Sdim Ctx.getObjCIdType(), 0, 0, false, ICIS_NoInit)); 5079221345Sdim RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0, 5080239462Sdim Ctx.getObjCClassType(), 0, 0, false, 5081239462Sdim ICIS_NoInit)); 5082203955Srdivacky RD->completeDefinition(); 5083198092Srdivacky 5084193326Sed SuperCTy = Ctx.getTagDeclType(RD); 5085193326Sed SuperPtrCTy = Ctx.getPointerType(SuperCTy); 5086198092Srdivacky 5087193326Sed SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy)); 5088198092Srdivacky SuperPtrTy = llvm::PointerType::getUnqual(SuperTy); 5089198092Srdivacky 5090193326Sed // struct _prop_t { 5091193326Sed // char *name; 5092198092Srdivacky // char *attributes; 5093193326Sed // } 5094226633Sdim PropertyTy = llvm::StructType::create("struct._prop_t", 5095226633Sdim Int8PtrTy, Int8PtrTy, NULL); 5096198092Srdivacky 5097193326Sed // struct _prop_list_t { 5098193326Sed // uint32_t entsize; // sizeof(struct _prop_t) 5099193326Sed // uint32_t count_of_properties; 5100193326Sed // struct _prop_t prop_list[count_of_properties]; 5101193326Sed // } 5102224145Sdim PropertyListTy = 5103226633Sdim llvm::StructType::create("struct._prop_list_t", IntTy, IntTy, 5104226633Sdim llvm::ArrayType::get(PropertyTy, 0), NULL); 5105193326Sed // struct _prop_list_t * 5106193326Sed PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy); 5107198092Srdivacky 5108193326Sed // struct _objc_method { 5109193326Sed // SEL _cmd; 5110193326Sed // char *method_type; 5111193326Sed // char *_imp; 5112193326Sed // } 5113226633Sdim MethodTy = llvm::StructType::create("struct._objc_method", 5114226633Sdim SelectorPtrTy, Int8PtrTy, Int8PtrTy, 5115226633Sdim NULL); 5116198092Srdivacky 5117193326Sed // struct _objc_cache * 5118226633Sdim CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache"); 5119193326Sed CachePtrTy = llvm::PointerType::getUnqual(CacheTy); 5120224145Sdim 5121193326Sed} 5122193326Sed 5123198092SrdivackyObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) 5124198092Srdivacky : ObjCCommonTypesHelper(cgm) { 5125193326Sed // struct _objc_method_description { 5126193326Sed // SEL name; 5127193326Sed // char *types; 5128193326Sed // } 5129198092Srdivacky MethodDescriptionTy = 5130226633Sdim llvm::StructType::create("struct._objc_method_description", 5131226633Sdim SelectorPtrTy, Int8PtrTy, NULL); 5132193326Sed 5133193326Sed // struct _objc_method_description_list { 5134193326Sed // int count; 5135193326Sed // struct _objc_method_description[1]; 5136193326Sed // } 5137198092Srdivacky MethodDescriptionListTy = 5138226633Sdim llvm::StructType::create("struct._objc_method_description_list", 5139226633Sdim IntTy, 5140226633Sdim llvm::ArrayType::get(MethodDescriptionTy, 0),NULL); 5141198092Srdivacky 5142193326Sed // struct _objc_method_description_list * 5143198092Srdivacky MethodDescriptionListPtrTy = 5144193326Sed llvm::PointerType::getUnqual(MethodDescriptionListTy); 5145193326Sed 5146193326Sed // Protocol description structures 5147193326Sed 5148193326Sed // struct _objc_protocol_extension { 5149193326Sed // uint32_t size; // sizeof(struct _objc_protocol_extension) 5150193326Sed // struct _objc_method_description_list *optional_instance_methods; 5151193326Sed // struct _objc_method_description_list *optional_class_methods; 5152193326Sed // struct _objc_property_list *instance_properties; 5153234353Sdim // const char ** extendedMethodTypes; 5154193326Sed // } 5155198092Srdivacky ProtocolExtensionTy = 5156226633Sdim llvm::StructType::create("struct._objc_protocol_extension", 5157226633Sdim IntTy, MethodDescriptionListPtrTy, 5158226633Sdim MethodDescriptionListPtrTy, PropertyListPtrTy, 5159234353Sdim Int8PtrPtrTy, NULL); 5160198092Srdivacky 5161193326Sed // struct _objc_protocol_extension * 5162193326Sed ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy); 5163193326Sed 5164193326Sed // Handle recursive construction of Protocol and ProtocolList types 5165193326Sed 5166224145Sdim ProtocolTy = 5167226633Sdim llvm::StructType::create(VMContext, "struct._objc_protocol"); 5168193326Sed 5169224145Sdim ProtocolListTy = 5170226633Sdim llvm::StructType::create(VMContext, "struct._objc_protocol_list"); 5171224145Sdim ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy), 5172193326Sed LongTy, 5173224145Sdim llvm::ArrayType::get(ProtocolTy, 0), 5174193326Sed NULL); 5175193326Sed 5176193326Sed // struct _objc_protocol { 5177193326Sed // struct _objc_protocol_extension *isa; 5178193326Sed // char *protocol_name; 5179193326Sed // struct _objc_protocol **_objc_protocol_list; 5180193326Sed // struct _objc_method_description_list *instance_methods; 5181193326Sed // struct _objc_method_description_list *class_methods; 5182193326Sed // } 5183224145Sdim ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy, 5184224145Sdim llvm::PointerType::getUnqual(ProtocolListTy), 5185224145Sdim MethodDescriptionListPtrTy, 5186224145Sdim MethodDescriptionListPtrTy, 5187224145Sdim NULL); 5188193326Sed 5189193326Sed // struct _objc_protocol_list * 5190193326Sed ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy); 5191193326Sed 5192193326Sed ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy); 5193193326Sed 5194193326Sed // Class description structures 5195193326Sed 5196193326Sed // struct _objc_ivar { 5197193326Sed // char *ivar_name; 5198193326Sed // char *ivar_type; 5199193326Sed // int ivar_offset; 5200193326Sed // } 5201226633Sdim IvarTy = llvm::StructType::create("struct._objc_ivar", 5202226633Sdim Int8PtrTy, Int8PtrTy, IntTy, NULL); 5203193326Sed 5204193326Sed // struct _objc_ivar_list * 5205224145Sdim IvarListTy = 5206226633Sdim llvm::StructType::create(VMContext, "struct._objc_ivar_list"); 5207193326Sed IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy); 5208193326Sed 5209193326Sed // struct _objc_method_list * 5210224145Sdim MethodListTy = 5211226633Sdim llvm::StructType::create(VMContext, "struct._objc_method_list"); 5212193326Sed MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy); 5213193326Sed 5214193326Sed // struct _objc_class_extension * 5215198092Srdivacky ClassExtensionTy = 5216226633Sdim llvm::StructType::create("struct._objc_class_extension", 5217226633Sdim IntTy, Int8PtrTy, PropertyListPtrTy, NULL); 5218193326Sed ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy); 5219193326Sed 5220226633Sdim ClassTy = llvm::StructType::create(VMContext, "struct._objc_class"); 5221193326Sed 5222193326Sed // struct _objc_class { 5223193326Sed // Class isa; 5224193326Sed // Class super_class; 5225193326Sed // char *name; 5226193326Sed // long version; 5227193326Sed // long info; 5228193326Sed // long instance_size; 5229193326Sed // struct _objc_ivar_list *ivars; 5230193326Sed // struct _objc_method_list *methods; 5231193326Sed // struct _objc_cache *cache; 5232193326Sed // struct _objc_protocol_list *protocols; 5233193326Sed // char *ivar_layout; 5234193326Sed // struct _objc_class_ext *ext; 5235193326Sed // }; 5236224145Sdim ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy), 5237224145Sdim llvm::PointerType::getUnqual(ClassTy), 5238224145Sdim Int8PtrTy, 5239224145Sdim LongTy, 5240224145Sdim LongTy, 5241224145Sdim LongTy, 5242224145Sdim IvarListPtrTy, 5243224145Sdim MethodListPtrTy, 5244224145Sdim CachePtrTy, 5245224145Sdim ProtocolListPtrTy, 5246224145Sdim Int8PtrTy, 5247224145Sdim ClassExtensionPtrTy, 5248224145Sdim NULL); 5249198092Srdivacky 5250193326Sed ClassPtrTy = llvm::PointerType::getUnqual(ClassTy); 5251193326Sed 5252193326Sed // struct _objc_category { 5253193326Sed // char *category_name; 5254193326Sed // char *class_name; 5255193326Sed // struct _objc_method_list *instance_method; 5256193326Sed // struct _objc_method_list *class_method; 5257193326Sed // uint32_t size; // sizeof(struct _objc_category) 5258193326Sed // struct _objc_property_list *instance_properties;// category's @property 5259193326Sed // } 5260224145Sdim CategoryTy = 5261226633Sdim llvm::StructType::create("struct._objc_category", 5262226633Sdim Int8PtrTy, Int8PtrTy, MethodListPtrTy, 5263226633Sdim MethodListPtrTy, ProtocolListPtrTy, 5264226633Sdim IntTy, PropertyListPtrTy, NULL); 5265193326Sed 5266193326Sed // Global metadata structures 5267193326Sed 5268193326Sed // struct _objc_symtab { 5269193326Sed // long sel_ref_cnt; 5270193326Sed // SEL *refs; 5271193326Sed // short cls_def_cnt; 5272193326Sed // short cat_def_cnt; 5273193326Sed // char *defs[cls_def_cnt + cat_def_cnt]; 5274193326Sed // } 5275224145Sdim SymtabTy = 5276226633Sdim llvm::StructType::create("struct._objc_symtab", 5277226633Sdim LongTy, SelectorPtrTy, ShortTy, ShortTy, 5278226633Sdim llvm::ArrayType::get(Int8PtrTy, 0), NULL); 5279193326Sed SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy); 5280193326Sed 5281193326Sed // struct _objc_module { 5282193326Sed // long version; 5283193326Sed // long size; // sizeof(struct _objc_module) 5284193326Sed // char *name; 5285193326Sed // struct _objc_symtab* symtab; 5286193326Sed // } 5287198092Srdivacky ModuleTy = 5288226633Sdim llvm::StructType::create("struct._objc_module", 5289226633Sdim LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL); 5290193326Sed 5291198092Srdivacky 5292193326Sed // FIXME: This is the size of the setjmp buffer and should be target 5293193326Sed // specific. 18 is what's used on 32-bit X86. 5294193326Sed uint64_t SetJmpBufferSize = 18; 5295198092Srdivacky 5296193326Sed // Exceptions 5297234353Sdim llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4); 5298198092Srdivacky 5299198092Srdivacky ExceptionDataTy = 5300226633Sdim llvm::StructType::create("struct._objc_exception_data", 5301234353Sdim llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize), 5302234353Sdim StackPtrTy, NULL); 5303193326Sed 5304193326Sed} 5305193326Sed 5306198092SrdivackyObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm) 5307198092Srdivacky : ObjCCommonTypesHelper(cgm) { 5308193326Sed // struct _method_list_t { 5309193326Sed // uint32_t entsize; // sizeof(struct _objc_method) 5310193326Sed // uint32_t method_count; 5311193326Sed // struct _objc_method method_list[method_count]; 5312193326Sed // } 5313224145Sdim MethodListnfABITy = 5314226633Sdim llvm::StructType::create("struct.__method_list_t", IntTy, IntTy, 5315226633Sdim llvm::ArrayType::get(MethodTy, 0), NULL); 5316193326Sed // struct method_list_t * 5317193326Sed MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy); 5318198092Srdivacky 5319193326Sed // struct _protocol_t { 5320193326Sed // id isa; // NULL 5321193326Sed // const char * const protocol_name; 5322193326Sed // const struct _protocol_list_t * protocol_list; // super protocols 5323193326Sed // const struct method_list_t * const instance_methods; 5324193326Sed // const struct method_list_t * const class_methods; 5325193326Sed // const struct method_list_t *optionalInstanceMethods; 5326193326Sed // const struct method_list_t *optionalClassMethods; 5327193326Sed // const struct _prop_list_t * properties; 5328193326Sed // const uint32_t size; // sizeof(struct _protocol_t) 5329193326Sed // const uint32_t flags; // = 0 5330234353Sdim // const char ** extendedMethodTypes; 5331193326Sed // } 5332198092Srdivacky 5333193326Sed // Holder for struct _protocol_list_t * 5334224145Sdim ProtocolListnfABITy = 5335226633Sdim llvm::StructType::create(VMContext, "struct._objc_protocol_list"); 5336198092Srdivacky 5337224145Sdim ProtocolnfABITy = 5338226633Sdim llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy, 5339226633Sdim llvm::PointerType::getUnqual(ProtocolListnfABITy), 5340226633Sdim MethodListnfABIPtrTy, MethodListnfABIPtrTy, 5341226633Sdim MethodListnfABIPtrTy, MethodListnfABIPtrTy, 5342234353Sdim PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, 5343234353Sdim NULL); 5344193326Sed 5345193326Sed // struct _protocol_t* 5346193326Sed ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy); 5347198092Srdivacky 5348193326Sed // struct _protocol_list_t { 5349193326Sed // long protocol_count; // Note, this is 32/64 bit 5350193326Sed // struct _protocol_t *[protocol_count]; 5351193326Sed // } 5352224145Sdim ProtocolListnfABITy->setBody(LongTy, 5353224145Sdim llvm::ArrayType::get(ProtocolnfABIPtrTy, 0), 5354224145Sdim NULL); 5355198092Srdivacky 5356193326Sed // struct _objc_protocol_list* 5357193326Sed ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy); 5358198092Srdivacky 5359193326Sed // struct _ivar_t { 5360193326Sed // unsigned long int *offset; // pointer to ivar offset location 5361193326Sed // char *name; 5362193326Sed // char *type; 5363193326Sed // uint32_t alignment; 5364193326Sed // uint32_t size; 5365193326Sed // } 5366224145Sdim IvarnfABITy = 5367226633Sdim llvm::StructType::create("struct._ivar_t", 5368226633Sdim llvm::PointerType::getUnqual(LongTy), 5369226633Sdim Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL); 5370198092Srdivacky 5371193326Sed // struct _ivar_list_t { 5372193326Sed // uint32 entsize; // sizeof(struct _ivar_t) 5373193326Sed // uint32 count; 5374193326Sed // struct _iver_t list[count]; 5375193326Sed // } 5376224145Sdim IvarListnfABITy = 5377226633Sdim llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy, 5378226633Sdim llvm::ArrayType::get(IvarnfABITy, 0), NULL); 5379198092Srdivacky 5380193326Sed IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy); 5381198092Srdivacky 5382193326Sed // struct _class_ro_t { 5383193326Sed // uint32_t const flags; 5384193326Sed // uint32_t const instanceStart; 5385193326Sed // uint32_t const instanceSize; 5386193326Sed // uint32_t const reserved; // only when building for 64bit targets 5387193326Sed // const uint8_t * const ivarLayout; 5388193326Sed // const char *const name; 5389193326Sed // const struct _method_list_t * const baseMethods; 5390193326Sed // const struct _objc_protocol_list *const baseProtocols; 5391193326Sed // const struct _ivar_list_t *const ivars; 5392193326Sed // const uint8_t * const weakIvarLayout; 5393193326Sed // const struct _prop_list_t * const properties; 5394193326Sed // } 5395198092Srdivacky 5396193326Sed // FIXME. Add 'reserved' field in 64bit abi mode! 5397226633Sdim ClassRonfABITy = llvm::StructType::create("struct._class_ro_t", 5398226633Sdim IntTy, IntTy, IntTy, Int8PtrTy, 5399226633Sdim Int8PtrTy, MethodListnfABIPtrTy, 5400226633Sdim ProtocolListnfABIPtrTy, 5401226633Sdim IvarListnfABIPtrTy, 5402226633Sdim Int8PtrTy, PropertyListPtrTy, NULL); 5403198092Srdivacky 5404193326Sed // ImpnfABITy - LLVM for id (*)(id, SEL, ...) 5405224145Sdim llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; 5406223017Sdim ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false) 5407223017Sdim ->getPointerTo(); 5408198092Srdivacky 5409193326Sed // struct _class_t { 5410193326Sed // struct _class_t *isa; 5411193326Sed // struct _class_t * const superclass; 5412193326Sed // void *cache; 5413193326Sed // IMP *vtable; 5414193326Sed // struct class_ro_t *ro; 5415193326Sed // } 5416198092Srdivacky 5417226633Sdim ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t"); 5418224145Sdim ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy), 5419224145Sdim llvm::PointerType::getUnqual(ClassnfABITy), 5420224145Sdim CachePtrTy, 5421224145Sdim llvm::PointerType::getUnqual(ImpnfABITy), 5422224145Sdim llvm::PointerType::getUnqual(ClassRonfABITy), 5423224145Sdim NULL); 5424193326Sed 5425193326Sed // LLVM for struct _class_t * 5426193326Sed ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy); 5427198092Srdivacky 5428193326Sed // struct _category_t { 5429193326Sed // const char * const name; 5430193326Sed // struct _class_t *const cls; 5431193326Sed // const struct _method_list_t * const instance_methods; 5432193326Sed // const struct _method_list_t * const class_methods; 5433193326Sed // const struct _protocol_list_t * const protocols; 5434193326Sed // const struct _prop_list_t * const properties; 5435193326Sed // } 5436226633Sdim CategorynfABITy = llvm::StructType::create("struct._category_t", 5437226633Sdim Int8PtrTy, ClassnfABIPtrTy, 5438226633Sdim MethodListnfABIPtrTy, 5439226633Sdim MethodListnfABIPtrTy, 5440226633Sdim ProtocolListnfABIPtrTy, 5441226633Sdim PropertyListPtrTy, 5442226633Sdim NULL); 5443198092Srdivacky 5444193326Sed // New types for nonfragile abi messaging. 5445193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 5446193326Sed ASTContext &Ctx = CGM.getContext(); 5447198092Srdivacky 5448193326Sed // MessageRefTy - LLVM for: 5449193326Sed // struct _message_ref_t { 5450193326Sed // IMP messenger; 5451193326Sed // SEL name; 5452193326Sed // }; 5453198092Srdivacky 5454193326Sed // First the clang type for struct _message_ref_t 5455208600Srdivacky RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, 5456207619Srdivacky Ctx.getTranslationUnitDecl(), 5457221345Sdim SourceLocation(), SourceLocation(), 5458193326Sed &Ctx.Idents.get("_message_ref_t")); 5459221345Sdim RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0, 5460239462Sdim Ctx.VoidPtrTy, 0, 0, false, ICIS_NoInit)); 5461221345Sdim RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0, 5462239462Sdim Ctx.getObjCSelType(), 0, 0, false, 5463239462Sdim ICIS_NoInit)); 5464203955Srdivacky RD->completeDefinition(); 5465198092Srdivacky 5466193326Sed MessageRefCTy = Ctx.getTagDeclType(RD); 5467193326Sed MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy); 5468193326Sed MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy)); 5469198092Srdivacky 5470193326Sed // MessageRefPtrTy - LLVM for struct _message_ref_t* 5471193326Sed MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy); 5472198092Srdivacky 5473193326Sed // SuperMessageRefTy - LLVM for: 5474193326Sed // struct _super_message_ref_t { 5475193326Sed // SUPER_IMP messenger; 5476193326Sed // SEL name; 5477193326Sed // }; 5478224145Sdim SuperMessageRefTy = 5479226633Sdim llvm::StructType::create("struct._super_message_ref_t", 5480226633Sdim ImpnfABITy, SelectorPtrTy, NULL); 5481198092Srdivacky 5482193326Sed // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* 5483198092Srdivacky SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); 5484224145Sdim 5485193326Sed 5486193326Sed // struct objc_typeinfo { 5487193326Sed // const void** vtable; // objc_ehtype_vtable + 2 5488193326Sed // const char* name; // c++ typeinfo string 5489193326Sed // Class cls; 5490193326Sed // }; 5491224145Sdim EHTypeTy = 5492226633Sdim llvm::StructType::create("struct._objc_typeinfo", 5493226633Sdim llvm::PointerType::getUnqual(Int8PtrTy), 5494226633Sdim Int8PtrTy, ClassnfABIPtrTy, NULL); 5495193326Sed EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy); 5496193326Sed} 5497193326Sed 5498198092Srdivackyllvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() { 5499193326Sed FinishNonFragileABIModule(); 5500198092Srdivacky 5501193326Sed return NULL; 5502193326Sed} 5503193326Sed 5504234353Sdimvoid CGObjCNonFragileABIMac:: 5505234353SdimAddModuleClassList(ArrayRef<llvm::GlobalValue*> Container, 5506234353Sdim const char *SymbolName, 5507234353Sdim const char *SectionName) { 5508193326Sed unsigned NumClasses = Container.size(); 5509198092Srdivacky 5510193326Sed if (!NumClasses) 5511193326Sed return; 5512198092Srdivacky 5513234353Sdim SmallVector<llvm::Constant*, 8> Symbols(NumClasses); 5514193326Sed for (unsigned i=0; i<NumClasses; i++) 5515193326Sed Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i], 5516193326Sed ObjCTypes.Int8PtrTy); 5517234353Sdim llvm::Constant *Init = 5518193326Sed llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 5519234353Sdim Symbols.size()), 5520193326Sed Symbols); 5521198092Srdivacky 5522193326Sed llvm::GlobalVariable *GV = 5523198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 5524193326Sed llvm::GlobalValue::InternalLinkage, 5525193326Sed Init, 5526198092Srdivacky SymbolName); 5527243830Sdim GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType())); 5528193326Sed GV->setSection(SectionName); 5529198092Srdivacky CGM.AddUsedGlobal(GV); 5530193326Sed} 5531198092Srdivacky 5532193326Sedvoid CGObjCNonFragileABIMac::FinishNonFragileABIModule() { 5533193326Sed // nonfragile abi has no module definition. 5534198092Srdivacky 5535193326Sed // Build list of all implemented class addresses in array 5536193326Sed // L_OBJC_LABEL_CLASS_$. 5537198092Srdivacky AddModuleClassList(DefinedClasses, 5538193326Sed "\01L_OBJC_LABEL_CLASS_$", 5539193326Sed "__DATA, __objc_classlist, regular, no_dead_strip"); 5540199482Srdivacky 5541234353Sdim for (unsigned i = 0, e = DefinedClasses.size(); i < e; i++) { 5542199482Srdivacky llvm::GlobalValue *IMPLGV = DefinedClasses[i]; 5543199482Srdivacky if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) 5544199482Srdivacky continue; 5545199482Srdivacky IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage); 5546199482Srdivacky } 5547199482Srdivacky 5548234353Sdim for (unsigned i = 0, e = DefinedMetaClasses.size(); i < e; i++) { 5549200583Srdivacky llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i]; 5550200583Srdivacky if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) 5551200583Srdivacky continue; 5552200583Srdivacky IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage); 5553200583Srdivacky } 5554199482Srdivacky 5555198092Srdivacky AddModuleClassList(DefinedNonLazyClasses, 5556193326Sed "\01L_OBJC_LABEL_NONLAZY_CLASS_$", 5557193326Sed "__DATA, __objc_nlclslist, regular, no_dead_strip"); 5558198092Srdivacky 5559193326Sed // Build list of all implemented category addresses in array 5560193326Sed // L_OBJC_LABEL_CATEGORY_$. 5561198092Srdivacky AddModuleClassList(DefinedCategories, 5562193326Sed "\01L_OBJC_LABEL_CATEGORY_$", 5563193326Sed "__DATA, __objc_catlist, regular, no_dead_strip"); 5564198092Srdivacky AddModuleClassList(DefinedNonLazyCategories, 5565193326Sed "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$", 5566193326Sed "__DATA, __objc_nlcatlist, regular, no_dead_strip"); 5567198092Srdivacky 5568207619Srdivacky EmitImageInfo(); 5569193326Sed} 5570193326Sed 5571223017Sdim/// isVTableDispatchedSelector - Returns true if SEL is not in the list of 5572223017Sdim/// VTableDispatchMethods; false otherwise. What this means is that 5573198092Srdivacky/// except for the 19 selectors in the list, we generate 32bit-style 5574193326Sed/// message dispatch call for all the rest. 5575223017Sdimbool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) { 5576223017Sdim // At various points we've experimented with using vtable-based 5577223017Sdim // dispatch for all methods. 5578207619Srdivacky switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) { 5579207619Srdivacky case CodeGenOptions::Legacy: 5580223017Sdim return false; 5581223017Sdim case CodeGenOptions::NonLegacy: 5582203955Srdivacky return true; 5583207619Srdivacky case CodeGenOptions::Mixed: 5584207619Srdivacky break; 5585207619Srdivacky } 5586203955Srdivacky 5587207619Srdivacky // If so, see whether this selector is in the white-list of things which must 5588207619Srdivacky // use the new dispatch convention. We lazily build a dense set for this. 5589223017Sdim if (VTableDispatchMethods.empty()) { 5590223017Sdim VTableDispatchMethods.insert(GetNullarySelector("alloc")); 5591223017Sdim VTableDispatchMethods.insert(GetNullarySelector("class")); 5592223017Sdim VTableDispatchMethods.insert(GetNullarySelector("self")); 5593223017Sdim VTableDispatchMethods.insert(GetNullarySelector("isFlipped")); 5594223017Sdim VTableDispatchMethods.insert(GetNullarySelector("length")); 5595223017Sdim VTableDispatchMethods.insert(GetNullarySelector("count")); 5596198092Srdivacky 5597223017Sdim // These are vtable-based if GC is disabled. 5598223017Sdim // Optimistically use vtable dispatch for hybrid compiles. 5599234353Sdim if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) { 5600223017Sdim VTableDispatchMethods.insert(GetNullarySelector("retain")); 5601223017Sdim VTableDispatchMethods.insert(GetNullarySelector("release")); 5602223017Sdim VTableDispatchMethods.insert(GetNullarySelector("autorelease")); 5603223017Sdim } 5604223017Sdim 5605223017Sdim VTableDispatchMethods.insert(GetUnarySelector("allocWithZone")); 5606223017Sdim VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass")); 5607223017Sdim VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector")); 5608223017Sdim VTableDispatchMethods.insert(GetUnarySelector("objectForKey")); 5609223017Sdim VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex")); 5610223017Sdim VTableDispatchMethods.insert(GetUnarySelector("isEqualToString")); 5611223017Sdim VTableDispatchMethods.insert(GetUnarySelector("isEqual")); 5612223017Sdim 5613223017Sdim // These are vtable-based if GC is enabled. 5614223017Sdim // Optimistically use vtable dispatch for hybrid compiles. 5615234353Sdim if (CGM.getLangOpts().getGC() != LangOptions::NonGC) { 5616223017Sdim VTableDispatchMethods.insert(GetNullarySelector("hash")); 5617223017Sdim VTableDispatchMethods.insert(GetUnarySelector("addObject")); 5618223017Sdim 5619223017Sdim // "countByEnumeratingWithState:objects:count" 5620223017Sdim IdentifierInfo *KeyIdents[] = { 5621223017Sdim &CGM.getContext().Idents.get("countByEnumeratingWithState"), 5622223017Sdim &CGM.getContext().Idents.get("objects"), 5623223017Sdim &CGM.getContext().Idents.get("count") 5624223017Sdim }; 5625223017Sdim VTableDispatchMethods.insert( 5626223017Sdim CGM.getContext().Selectors.getSelector(3, KeyIdents)); 5627223017Sdim } 5628193326Sed } 5629207619Srdivacky 5630223017Sdim return VTableDispatchMethods.count(Sel); 5631193326Sed} 5632193326Sed 5633193326Sed/// BuildClassRoTInitializer - generate meta-data for: 5634193326Sed/// struct _class_ro_t { 5635193326Sed/// uint32_t const flags; 5636193326Sed/// uint32_t const instanceStart; 5637193326Sed/// uint32_t const instanceSize; 5638193326Sed/// uint32_t const reserved; // only when building for 64bit targets 5639193326Sed/// const uint8_t * const ivarLayout; 5640193326Sed/// const char *const name; 5641193326Sed/// const struct _method_list_t * const baseMethods; 5642193326Sed/// const struct _protocol_list_t *const baseProtocols; 5643193326Sed/// const struct _ivar_list_t *const ivars; 5644193326Sed/// const uint8_t * const weakIvarLayout; 5645193326Sed/// const struct _prop_list_t * const properties; 5646193326Sed/// } 5647193326Sed/// 5648193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( 5649198092Srdivacky unsigned flags, 5650198092Srdivacky unsigned InstanceStart, 5651198092Srdivacky unsigned InstanceSize, 5652198092Srdivacky const ObjCImplementationDecl *ID) { 5653193326Sed std::string ClassName = ID->getNameAsString(); 5654234353Sdim llvm::Constant *Values[10]; // 11 for 64bit targets! 5655224145Sdim 5656234353Sdim if (CGM.getLangOpts().ObjCAutoRefCount) 5657243830Sdim flags |= NonFragileABI_Class_CompiledByARC; 5658224145Sdim 5659193326Sed Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags); 5660193326Sed Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart); 5661193326Sed Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize); 5662193326Sed // FIXME. For 64bit targets add 0 here. 5663243830Sdim Values[ 3] = (flags & NonFragileABI_Class_Meta) 5664243830Sdim ? GetIvarLayoutName(0, ObjCTypes) 5665198092Srdivacky : BuildIvarLayout(ID, true); 5666193326Sed Values[ 4] = GetClassName(ID->getIdentifier()); 5667193326Sed // const struct _method_list_t * const baseMethods; 5668193326Sed std::vector<llvm::Constant*> Methods; 5669193326Sed std::string MethodListName("\01l_OBJC_$_"); 5670243830Sdim if (flags & NonFragileABI_Class_Meta) { 5671193326Sed MethodListName += "CLASS_METHODS_" + ID->getNameAsString(); 5672198092Srdivacky for (ObjCImplementationDecl::classmeth_iterator 5673195341Sed i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { 5674193326Sed // Class methods should always be defined. 5675193326Sed Methods.push_back(GetMethodConstant(*i)); 5676193326Sed } 5677193326Sed } else { 5678193326Sed MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString(); 5679198092Srdivacky for (ObjCImplementationDecl::instmeth_iterator 5680195341Sed i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { 5681193326Sed // Instance methods should always be defined. 5682193326Sed Methods.push_back(GetMethodConstant(*i)); 5683193326Sed } 5684198092Srdivacky for (ObjCImplementationDecl::propimpl_iterator 5685195341Sed i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { 5686193326Sed ObjCPropertyImplDecl *PID = *i; 5687198092Srdivacky 5688193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){ 5689193326Sed ObjCPropertyDecl *PD = PID->getPropertyDecl(); 5690198092Srdivacky 5691193326Sed if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) 5692193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 5693193326Sed Methods.push_back(C); 5694193326Sed if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) 5695193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 5696193326Sed Methods.push_back(C); 5697193326Sed } 5698193326Sed } 5699193326Sed } 5700198092Srdivacky Values[ 5] = EmitMethodList(MethodListName, 5701198092Srdivacky "__DATA, __objc_const", Methods); 5702198092Srdivacky 5703193326Sed const ObjCInterfaceDecl *OID = ID->getClassInterface(); 5704193326Sed assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer"); 5705198092Srdivacky Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_" 5706198398Srdivacky + OID->getName(), 5707212904Sdim OID->all_referenced_protocol_begin(), 5708212904Sdim OID->all_referenced_protocol_end()); 5709198092Srdivacky 5710243830Sdim if (flags & NonFragileABI_Class_Meta) { 5711193326Sed Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); 5712243830Sdim Values[ 8] = GetIvarLayoutName(0, ObjCTypes); 5713243830Sdim Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 5714243830Sdim } else { 5715193326Sed Values[ 7] = EmitIvarList(ID); 5716243830Sdim Values[ 8] = BuildIvarLayout(ID, false); 5717198398Srdivacky Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), 5718198398Srdivacky ID, ID->getClassInterface(), ObjCTypes); 5719243830Sdim } 5720193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy, 5721193326Sed Values); 5722193326Sed llvm::GlobalVariable *CLASS_RO_GV = 5723198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false, 5724198092Srdivacky llvm::GlobalValue::InternalLinkage, 5725198092Srdivacky Init, 5726243830Sdim (flags & NonFragileABI_Class_Meta) ? 5727198092Srdivacky std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName : 5728198092Srdivacky std::string("\01l_OBJC_CLASS_RO_$_")+ClassName); 5729193326Sed CLASS_RO_GV->setAlignment( 5730243830Sdim CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy)); 5731193326Sed CLASS_RO_GV->setSection("__DATA, __objc_const"); 5732193326Sed return CLASS_RO_GV; 5733193326Sed 5734193326Sed} 5735193326Sed 5736193326Sed/// BuildClassMetaData - This routine defines that to-level meta-data 5737193326Sed/// for the given ClassName for: 5738193326Sed/// struct _class_t { 5739193326Sed/// struct _class_t *isa; 5740193326Sed/// struct _class_t * const superclass; 5741193326Sed/// void *cache; 5742193326Sed/// IMP *vtable; 5743193326Sed/// struct class_ro_t *ro; 5744193326Sed/// } 5745193326Sed/// 5746193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( 5747198092Srdivacky std::string &ClassName, 5748198092Srdivacky llvm::Constant *IsAGV, 5749198092Srdivacky llvm::Constant *SuperClassGV, 5750198092Srdivacky llvm::Constant *ClassRoGV, 5751198092Srdivacky bool HiddenVisibility) { 5752234353Sdim llvm::Constant *Values[] = { 5753234353Sdim IsAGV, 5754234353Sdim SuperClassGV, 5755234353Sdim ObjCEmptyCacheVar, // &ObjCEmptyCacheVar 5756234353Sdim ObjCEmptyVtableVar, // &ObjCEmptyVtableVar 5757234353Sdim ClassRoGV // &CLASS_RO_GV 5758234353Sdim }; 5759198092Srdivacky if (!Values[1]) 5760198092Srdivacky Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy); 5761263508Sdim if (!Values[3]) 5762263508Sdim Values[3] = llvm::Constant::getNullValue( 5763263508Sdim llvm::PointerType::getUnqual(ObjCTypes.ImpnfABITy)); 5764198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy, 5765193326Sed Values); 5766193326Sed llvm::GlobalVariable *GV = GetClassGlobal(ClassName); 5767193326Sed GV->setInitializer(Init); 5768193326Sed GV->setSection("__DATA, __objc_data"); 5769193326Sed GV->setAlignment( 5770243830Sdim CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy)); 5771193326Sed if (HiddenVisibility) 5772193326Sed GV->setVisibility(llvm::GlobalValue::HiddenVisibility); 5773193326Sed return GV; 5774193326Sed} 5775193326Sed 5776198092Srdivackybool 5777193326SedCGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const { 5778195341Sed return OD->getClassMethod(GetNullarySelector("load")) != 0; 5779193326Sed} 5780193326Sed 5781193326Sedvoid CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, 5782193326Sed uint32_t &InstanceStart, 5783193326Sed uint32_t &InstanceSize) { 5784198092Srdivacky const ASTRecordLayout &RL = 5785193326Sed CGM.getContext().getASTObjCImplementationLayout(OID); 5786198092Srdivacky 5787193326Sed // InstanceSize is really instance end. 5788218893Sdim InstanceSize = RL.getDataSize().getQuantity(); 5789193326Sed 5790193326Sed // If there are no fields, the start is the same as the end. 5791193326Sed if (!RL.getFieldCount()) 5792193326Sed InstanceStart = InstanceSize; 5793193326Sed else 5794221345Sdim InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth(); 5795193326Sed} 5796193326Sed 5797193326Sedvoid CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { 5798193326Sed std::string ClassName = ID->getNameAsString(); 5799193326Sed if (!ObjCEmptyCacheVar) { 5800193326Sed ObjCEmptyCacheVar = new llvm::GlobalVariable( 5801198092Srdivacky CGM.getModule(), 5802198092Srdivacky ObjCTypes.CacheTy, 5803198092Srdivacky false, 5804198092Srdivacky llvm::GlobalValue::ExternalLinkage, 5805198092Srdivacky 0, 5806198092Srdivacky "_objc_empty_cache"); 5807263508Sdim 5808263508Sdim // Make this entry NULL for any iOS device target, any iOS simulator target, 5809263508Sdim // OS X with deployment target 10.9 or later. 5810263508Sdim const llvm::Triple &Triple = CGM.getTarget().getTriple(); 5811263508Sdim if (Triple.isiOS() || (Triple.isMacOSX() && !Triple.isMacOSXVersionLT(10, 9))) 5812263508Sdim // This entry will be null. 5813263508Sdim ObjCEmptyVtableVar = 0; 5814263508Sdim else 5815263508Sdim ObjCEmptyVtableVar = new llvm::GlobalVariable( 5816263508Sdim CGM.getModule(), 5817263508Sdim ObjCTypes.ImpnfABITy, 5818263508Sdim false, 5819263508Sdim llvm::GlobalValue::ExternalLinkage, 5820263508Sdim 0, 5821263508Sdim "_objc_empty_vtable"); 5822193326Sed } 5823198092Srdivacky assert(ID->getClassInterface() && 5824193326Sed "CGObjCNonFragileABIMac::GenerateClass - class is 0"); 5825193326Sed // FIXME: Is this correct (that meta class size is never computed)? 5826198092Srdivacky uint32_t InstanceStart = 5827243830Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy); 5828193326Sed uint32_t InstanceSize = InstanceStart; 5829243830Sdim uint32_t flags = NonFragileABI_Class_Meta; 5830193326Sed std::string ObjCMetaClassName(getMetaclassSymbolPrefix()); 5831193326Sed std::string ObjCClassName(getClassSymbolPrefix()); 5832198092Srdivacky 5833193326Sed llvm::GlobalVariable *SuperClassGV, *IsAGV; 5834198092Srdivacky 5835243830Sdim // Build the flags for the metaclass. 5836198092Srdivacky bool classIsHidden = 5837218893Sdim ID->getClassInterface()->getVisibility() == HiddenVisibility; 5838193326Sed if (classIsHidden) 5839243830Sdim flags |= NonFragileABI_Class_Hidden; 5840243830Sdim 5841243830Sdim // FIXME: why is this flag set on the metaclass? 5842243830Sdim // ObjC metaclasses have no fields and don't really get constructed. 5843243830Sdim if (ID->hasNonZeroConstructors() || ID->hasDestructors()) { 5844243830Sdim flags |= NonFragileABI_Class_HasCXXStructors; 5845243830Sdim if (!ID->hasNonZeroConstructors()) 5846243830Sdim flags |= NonFragileABI_Class_HasCXXDestructorOnly; 5847243830Sdim } 5848243830Sdim 5849193326Sed if (!ID->getClassInterface()->getSuperClass()) { 5850193326Sed // class is root 5851243830Sdim flags |= NonFragileABI_Class_Root; 5852193326Sed SuperClassGV = GetClassGlobal(ObjCClassName + ClassName); 5853193326Sed IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName); 5854193326Sed } else { 5855193326Sed // Has a root. Current class is not a root. 5856193326Sed const ObjCInterfaceDecl *Root = ID->getClassInterface(); 5857193326Sed while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) 5858193326Sed Root = Super; 5859193326Sed IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString()); 5860221345Sdim if (Root->isWeakImported()) 5861200583Srdivacky IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5862193326Sed // work on super class metadata symbol. 5863198092Srdivacky std::string SuperClassName = 5864200583Srdivacky ObjCMetaClassName + 5865200583Srdivacky ID->getClassInterface()->getSuperClass()->getNameAsString(); 5866193326Sed SuperClassGV = GetClassGlobal(SuperClassName); 5867221345Sdim if (ID->getClassInterface()->getSuperClass()->isWeakImported()) 5868199482Srdivacky SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5869193326Sed } 5870193326Sed llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags, 5871193326Sed InstanceStart, 5872193326Sed InstanceSize,ID); 5873193326Sed std::string TClassName = ObjCMetaClassName + ClassName; 5874198092Srdivacky llvm::GlobalVariable *MetaTClass = 5875193326Sed BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV, 5876193326Sed classIsHidden); 5877199482Srdivacky DefinedMetaClasses.push_back(MetaTClass); 5878193326Sed 5879193326Sed // Metadata for the class 5880243830Sdim flags = 0; 5881193326Sed if (classIsHidden) 5882243830Sdim flags |= NonFragileABI_Class_Hidden; 5883193326Sed 5884243830Sdim if (ID->hasNonZeroConstructors() || ID->hasDestructors()) { 5885243830Sdim flags |= NonFragileABI_Class_HasCXXStructors; 5886243830Sdim 5887243830Sdim // Set a flag to enable a runtime optimization when a class has 5888243830Sdim // fields that require destruction but which don't require 5889243830Sdim // anything except zero-initialization during construction. This 5890243830Sdim // is most notably true of __strong and __weak types, but you can 5891243830Sdim // also imagine there being C++ types with non-trivial default 5892243830Sdim // constructors that merely set all fields to null. 5893243830Sdim if (!ID->hasNonZeroConstructors()) 5894243830Sdim flags |= NonFragileABI_Class_HasCXXDestructorOnly; 5895243830Sdim } 5896243830Sdim 5897194613Sed if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface())) 5898243830Sdim flags |= NonFragileABI_Class_Exception; 5899193326Sed 5900193326Sed if (!ID->getClassInterface()->getSuperClass()) { 5901243830Sdim flags |= NonFragileABI_Class_Root; 5902193326Sed SuperClassGV = 0; 5903193326Sed } else { 5904193326Sed // Has a root. Current class is not a root. 5905193326Sed std::string RootClassName = 5906193326Sed ID->getClassInterface()->getSuperClass()->getNameAsString(); 5907193326Sed SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName); 5908221345Sdim if (ID->getClassInterface()->getSuperClass()->isWeakImported()) 5909199482Srdivacky SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5910193326Sed } 5911193326Sed GetClassSizeInfo(ID, InstanceStart, InstanceSize); 5912193326Sed CLASS_RO_GV = BuildClassRoTInitializer(flags, 5913193326Sed InstanceStart, 5914198092Srdivacky InstanceSize, 5915193326Sed ID); 5916198092Srdivacky 5917193326Sed TClassName = ObjCClassName + ClassName; 5918198092Srdivacky llvm::GlobalVariable *ClassMD = 5919193326Sed BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV, 5920193326Sed classIsHidden); 5921193326Sed DefinedClasses.push_back(ClassMD); 5922193326Sed 5923193326Sed // Determine if this class is also "non-lazy". 5924193326Sed if (ImplementationIsNonLazy(ID)) 5925193326Sed DefinedNonLazyClasses.push_back(ClassMD); 5926193326Sed 5927193326Sed // Force the definition of the EHType if necessary. 5928243830Sdim if (flags & NonFragileABI_Class_Exception) 5929193326Sed GetInterfaceEHType(ID->getClassInterface(), true); 5930221345Sdim // Make sure method definition entries are all clear for next implementation. 5931221345Sdim MethodDefinitions.clear(); 5932193326Sed} 5933193326Sed 5934193326Sed/// GenerateProtocolRef - This routine is called to generate code for 5935193326Sed/// a protocol reference expression; as in: 5936193326Sed/// @code 5937193326Sed/// @protocol(Proto1); 5938193326Sed/// @endcode 5939193326Sed/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1 5940193326Sed/// which will hold address of the protocol meta-data. 5941193326Sed/// 5942249423Sdimllvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, 5943198092Srdivacky const ObjCProtocolDecl *PD) { 5944198092Srdivacky 5945193326Sed // This routine is called for @protocol only. So, we must build definition 5946193326Sed // of protocol's meta-data (not a reference to it!) 5947193326Sed // 5948198092Srdivacky llvm::Constant *Init = 5949198092Srdivacky llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD), 5950234353Sdim ObjCTypes.getExternalProtocolPtrTy()); 5951198092Srdivacky 5952193326Sed std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_"); 5953212904Sdim ProtocolName += PD->getName(); 5954198092Srdivacky 5955193326Sed llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName); 5956193326Sed if (PTGV) 5957249423Sdim return CGF.Builder.CreateLoad(PTGV); 5958193326Sed PTGV = new llvm::GlobalVariable( 5959198092Srdivacky CGM.getModule(), 5960198092Srdivacky Init->getType(), false, 5961198092Srdivacky llvm::GlobalValue::WeakAnyLinkage, 5962198092Srdivacky Init, 5963198092Srdivacky ProtocolName); 5964193326Sed PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip"); 5965193326Sed PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 5966198092Srdivacky CGM.AddUsedGlobal(PTGV); 5967249423Sdim return CGF.Builder.CreateLoad(PTGV); 5968193326Sed} 5969193326Sed 5970193326Sed/// GenerateCategory - Build metadata for a category implementation. 5971193326Sed/// struct _category_t { 5972193326Sed/// const char * const name; 5973193326Sed/// struct _class_t *const cls; 5974193326Sed/// const struct _method_list_t * const instance_methods; 5975193326Sed/// const struct _method_list_t * const class_methods; 5976193326Sed/// const struct _protocol_list_t * const protocols; 5977193326Sed/// const struct _prop_list_t * const properties; 5978193326Sed/// } 5979193326Sed/// 5980193326Sedvoid CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 5981193326Sed const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); 5982193326Sed const char *Prefix = "\01l_OBJC_$_CATEGORY_"; 5983198092Srdivacky std::string ExtCatName(Prefix + Interface->getNameAsString()+ 5984198092Srdivacky "_$_" + OCD->getNameAsString()); 5985198092Srdivacky std::string ExtClassName(getClassSymbolPrefix() + 5986193326Sed Interface->getNameAsString()); 5987198092Srdivacky 5988234353Sdim llvm::Constant *Values[6]; 5989193326Sed Values[0] = GetClassName(OCD->getIdentifier()); 5990193326Sed // meta-class entry symbol 5991193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName); 5992221345Sdim if (Interface->isWeakImported()) 5993199482Srdivacky ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5994199482Srdivacky 5995193326Sed Values[1] = ClassGV; 5996193326Sed std::vector<llvm::Constant*> Methods; 5997193326Sed std::string MethodListName(Prefix); 5998198092Srdivacky MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() + 5999193326Sed "_$_" + OCD->getNameAsString(); 6000198092Srdivacky 6001198092Srdivacky for (ObjCCategoryImplDecl::instmeth_iterator 6002195341Sed i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { 6003193326Sed // Instance methods should always be defined. 6004193326Sed Methods.push_back(GetMethodConstant(*i)); 6005193326Sed } 6006198092Srdivacky 6007198092Srdivacky Values[2] = EmitMethodList(MethodListName, 6008198092Srdivacky "__DATA, __objc_const", 6009193326Sed Methods); 6010193326Sed 6011193326Sed MethodListName = Prefix; 6012193326Sed MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" + 6013193326Sed OCD->getNameAsString(); 6014193326Sed Methods.clear(); 6015198092Srdivacky for (ObjCCategoryImplDecl::classmeth_iterator 6016195341Sed i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { 6017193326Sed // Class methods should always be defined. 6018193326Sed Methods.push_back(GetMethodConstant(*i)); 6019193326Sed } 6020198092Srdivacky 6021198092Srdivacky Values[3] = EmitMethodList(MethodListName, 6022198092Srdivacky "__DATA, __objc_const", 6023193326Sed Methods); 6024198092Srdivacky const ObjCCategoryDecl *Category = 6025193326Sed Interface->FindCategoryDeclaration(OCD->getIdentifier()); 6026193326Sed if (Category) { 6027234353Sdim SmallString<256> ExtName; 6028198398Srdivacky llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_" 6029198398Srdivacky << OCD->getName(); 6030193326Sed Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_" 6031198398Srdivacky + Interface->getName() + "_$_" 6032198398Srdivacky + Category->getName(), 6033193326Sed Category->protocol_begin(), 6034193326Sed Category->protocol_end()); 6035198398Srdivacky Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), 6036198398Srdivacky OCD, Category, ObjCTypes); 6037198092Srdivacky } else { 6038193326Sed Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); 6039193326Sed Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 6040193326Sed } 6041198092Srdivacky 6042198092Srdivacky llvm::Constant *Init = 6043198092Srdivacky llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy, 6044193326Sed Values); 6045193326Sed llvm::GlobalVariable *GCATV 6046198092Srdivacky = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy, 6047193326Sed false, 6048193326Sed llvm::GlobalValue::InternalLinkage, 6049193326Sed Init, 6050198092Srdivacky ExtCatName); 6051193326Sed GCATV->setAlignment( 6052243830Sdim CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy)); 6053193326Sed GCATV->setSection("__DATA, __objc_const"); 6054198092Srdivacky CGM.AddUsedGlobal(GCATV); 6055193326Sed DefinedCategories.push_back(GCATV); 6056193326Sed 6057193326Sed // Determine if this category is also "non-lazy". 6058193326Sed if (ImplementationIsNonLazy(OCD)) 6059193326Sed DefinedNonLazyCategories.push_back(GCATV); 6060221345Sdim // method definition entries must be clear for next implementation. 6061221345Sdim MethodDefinitions.clear(); 6062193326Sed} 6063193326Sed 6064193326Sed/// GetMethodConstant - Return a struct objc_method constant for the 6065193326Sed/// given method if it has been defined. The result is null if the 6066193326Sed/// method has not been defined. The return value has type MethodPtrTy. 6067193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant( 6068198092Srdivacky const ObjCMethodDecl *MD) { 6069212904Sdim llvm::Function *Fn = GetMethodDefinition(MD); 6070193326Sed if (!Fn) 6071193326Sed return 0; 6072198092Srdivacky 6073234353Sdim llvm::Constant *Method[] = { 6074198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 6075234353Sdim ObjCTypes.SelectorPtrTy), 6076234353Sdim GetMethodVarType(MD), 6077234353Sdim llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy) 6078234353Sdim }; 6079193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method); 6080193326Sed} 6081193326Sed 6082193326Sed/// EmitMethodList - Build meta-data for method declarations 6083193326Sed/// struct _method_list_t { 6084193326Sed/// uint32_t entsize; // sizeof(struct _objc_method) 6085193326Sed/// uint32_t method_count; 6086193326Sed/// struct _objc_method method_list[method_count]; 6087193326Sed/// } 6088193326Sed/// 6089234353Sdimllvm::Constant * 6090234353SdimCGObjCNonFragileABIMac::EmitMethodList(Twine Name, 6091234353Sdim const char *Section, 6092234353Sdim ArrayRef<llvm::Constant*> Methods) { 6093193326Sed // Return null for empty list. 6094193326Sed if (Methods.empty()) 6095193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy); 6096198092Srdivacky 6097224145Sdim llvm::Constant *Values[3]; 6098193326Sed // sizeof(struct _objc_method) 6099243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy); 6100193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 6101193326Sed // method_count 6102193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 6103193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy, 6104193326Sed Methods.size()); 6105193326Sed Values[2] = llvm::ConstantArray::get(AT, Methods); 6106224145Sdim llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values); 6107198092Srdivacky 6108193326Sed llvm::GlobalVariable *GV = 6109198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 6110224145Sdim llvm::GlobalValue::InternalLinkage, Init, Name); 6111243830Sdim GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType())); 6112193326Sed GV->setSection(Section); 6113198092Srdivacky CGM.AddUsedGlobal(GV); 6114224145Sdim return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy); 6115193326Sed} 6116193326Sed 6117193326Sed/// ObjCIvarOffsetVariable - Returns the ivar offset variable for 6118193326Sed/// the given ivar. 6119206125Srdivackyllvm::GlobalVariable * 6120206125SrdivackyCGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, 6121206125Srdivacky const ObjCIvarDecl *Ivar) { 6122206125Srdivacky const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); 6123193326Sed std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() + 6124193326Sed '.' + Ivar->getNameAsString(); 6125198092Srdivacky llvm::GlobalVariable *IvarOffsetGV = 6126193326Sed CGM.getModule().getGlobalVariable(Name); 6127193326Sed if (!IvarOffsetGV) 6128198092Srdivacky IvarOffsetGV = 6129198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy, 6130193326Sed false, 6131193326Sed llvm::GlobalValue::ExternalLinkage, 6132193326Sed 0, 6133198092Srdivacky Name); 6134193326Sed return IvarOffsetGV; 6135193326Sed} 6136193326Sed 6137206125Srdivackyllvm::Constant * 6138206125SrdivackyCGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, 6139206125Srdivacky const ObjCIvarDecl *Ivar, 6140206125Srdivacky unsigned long int Offset) { 6141193326Sed llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar); 6142198092Srdivacky IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy, 6143193326Sed Offset)); 6144193326Sed IvarOffsetGV->setAlignment( 6145243830Sdim CGM.getDataLayout().getABITypeAlignment(ObjCTypes.LongTy)); 6146193326Sed 6147193326Sed // FIXME: This matches gcc, but shouldn't the visibility be set on the use as 6148193326Sed // well (i.e., in ObjCIvarOffsetVariable). 6149193326Sed if (Ivar->getAccessControl() == ObjCIvarDecl::Private || 6150193326Sed Ivar->getAccessControl() == ObjCIvarDecl::Package || 6151218893Sdim ID->getVisibility() == HiddenVisibility) 6152193326Sed IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 6153193326Sed else 6154193326Sed IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); 6155223017Sdim IvarOffsetGV->setSection("__DATA, __objc_ivar"); 6156193326Sed return IvarOffsetGV; 6157193326Sed} 6158193326Sed 6159193326Sed/// EmitIvarList - Emit the ivar list for the given 6160193326Sed/// implementation. The return value has type 6161193326Sed/// IvarListnfABIPtrTy. 6162193326Sed/// struct _ivar_t { 6163193326Sed/// unsigned long int *offset; // pointer to ivar offset location 6164193326Sed/// char *name; 6165193326Sed/// char *type; 6166193326Sed/// uint32_t alignment; 6167193326Sed/// uint32_t size; 6168193326Sed/// } 6169193326Sed/// struct _ivar_list_t { 6170193326Sed/// uint32 entsize; // sizeof(struct _ivar_t) 6171193326Sed/// uint32 count; 6172193326Sed/// struct _iver_t list[count]; 6173193326Sed/// } 6174193326Sed/// 6175193326Sed 6176193326Sedllvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( 6177198092Srdivacky const ObjCImplementationDecl *ID) { 6178198092Srdivacky 6179234353Sdim std::vector<llvm::Constant*> Ivars; 6180198092Srdivacky 6181226633Sdim const ObjCInterfaceDecl *OID = ID->getClassInterface(); 6182193326Sed assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface"); 6183198092Srdivacky 6184193326Sed // FIXME. Consolidate this with similar code in GenerateClass. 6185198092Srdivacky 6186226633Sdim for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); 6187224145Sdim IVD; IVD = IVD->getNextIvar()) { 6188193576Sed // Ignore unnamed bit-fields. 6189193576Sed if (!IVD->getDeclName()) 6190193576Sed continue; 6191234353Sdim llvm::Constant *Ivar[5]; 6192198092Srdivacky Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD, 6193193326Sed ComputeIvarBaseOffset(CGM, ID, IVD)); 6194193326Sed Ivar[1] = GetMethodVarName(IVD->getIdentifier()); 6195193326Sed Ivar[2] = GetMethodVarType(IVD); 6196226633Sdim llvm::Type *FieldTy = 6197193326Sed CGM.getTypes().ConvertTypeForMem(IVD->getType()); 6198243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy); 6199193326Sed unsigned Align = CGM.getContext().getPreferredTypeAlign( 6200198092Srdivacky IVD->getType().getTypePtr()) >> 3; 6201193326Sed Align = llvm::Log2_32(Align); 6202193326Sed Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align); 6203193326Sed // NOTE. Size of a bitfield does not match gcc's, because of the 6204193326Sed // way bitfields are treated special in each. But I am told that 6205193326Sed // 'size' for bitfield ivars is ignored by the runtime so it does 6206193326Sed // not matter. If it matters, there is enough info to get the 6207193326Sed // bitfield right! 6208193326Sed Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 6209193326Sed Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar)); 6210193326Sed } 6211193326Sed // Return null for empty list. 6212193326Sed if (Ivars.empty()) 6213193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); 6214224145Sdim 6215224145Sdim llvm::Constant *Values[3]; 6216243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy); 6217193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 6218193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size()); 6219193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy, 6220193326Sed Ivars.size()); 6221193326Sed Values[2] = llvm::ConstantArray::get(AT, Ivars); 6222224145Sdim llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values); 6223193326Sed const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_"; 6224193326Sed llvm::GlobalVariable *GV = 6225198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 6226193326Sed llvm::GlobalValue::InternalLinkage, 6227193326Sed Init, 6228198398Srdivacky Prefix + OID->getName()); 6229193326Sed GV->setAlignment( 6230243830Sdim CGM.getDataLayout().getABITypeAlignment(Init->getType())); 6231193326Sed GV->setSection("__DATA, __objc_const"); 6232198092Srdivacky 6233198092Srdivacky CGM.AddUsedGlobal(GV); 6234198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy); 6235193326Sed} 6236193326Sed 6237193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( 6238198092Srdivacky const ObjCProtocolDecl *PD) { 6239193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 6240198092Srdivacky 6241193326Sed if (!Entry) { 6242193326Sed // We use the initializer as a marker of whether this is a forward 6243193326Sed // reference or not. At module finalization we add the empty 6244193326Sed // contents for protocols which were referenced but never defined. 6245198092Srdivacky Entry = 6246198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false, 6247198092Srdivacky llvm::GlobalValue::ExternalLinkage, 6248198092Srdivacky 0, 6249198398Srdivacky "\01l_OBJC_PROTOCOL_$_" + PD->getName()); 6250193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 6251193326Sed } 6252198092Srdivacky 6253193326Sed return Entry; 6254193326Sed} 6255193326Sed 6256193326Sed/// GetOrEmitProtocol - Generate the protocol meta-data: 6257193326Sed/// @code 6258193326Sed/// struct _protocol_t { 6259193326Sed/// id isa; // NULL 6260193326Sed/// const char * const protocol_name; 6261193326Sed/// const struct _protocol_list_t * protocol_list; // super protocols 6262193326Sed/// const struct method_list_t * const instance_methods; 6263193326Sed/// const struct method_list_t * const class_methods; 6264193326Sed/// const struct method_list_t *optionalInstanceMethods; 6265193326Sed/// const struct method_list_t *optionalClassMethods; 6266193326Sed/// const struct _prop_list_t * properties; 6267193326Sed/// const uint32_t size; // sizeof(struct _protocol_t) 6268193326Sed/// const uint32_t flags; // = 0 6269234353Sdim/// const char ** extendedMethodTypes; 6270193326Sed/// } 6271193326Sed/// @endcode 6272193326Sed/// 6273193326Sed 6274193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( 6275198092Srdivacky const ObjCProtocolDecl *PD) { 6276234353Sdim llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()]; 6277198092Srdivacky 6278193326Sed // Early exit if a defining object has already been generated. 6279193326Sed if (Entry && Entry->hasInitializer()) 6280193326Sed return Entry; 6281193326Sed 6282234353Sdim // Use the protocol definition, if there is one. 6283234353Sdim if (const ObjCProtocolDecl *Def = PD->getDefinition()) 6284234353Sdim PD = Def; 6285234353Sdim 6286193326Sed // Construct method lists. 6287193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 6288193326Sed std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; 6289234353Sdim std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt; 6290198092Srdivacky for (ObjCProtocolDecl::instmeth_iterator 6291195341Sed i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { 6292193326Sed ObjCMethodDecl *MD = *i; 6293193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 6294223017Sdim if (!C) 6295223017Sdim return GetOrEmitProtocolRef(PD); 6296223017Sdim 6297193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 6298193326Sed OptInstanceMethods.push_back(C); 6299234353Sdim OptMethodTypesExt.push_back(GetMethodVarType(MD, true)); 6300193326Sed } else { 6301193326Sed InstanceMethods.push_back(C); 6302234353Sdim MethodTypesExt.push_back(GetMethodVarType(MD, true)); 6303198092Srdivacky } 6304193326Sed } 6305198092Srdivacky 6306198092Srdivacky for (ObjCProtocolDecl::classmeth_iterator 6307195341Sed i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { 6308193326Sed ObjCMethodDecl *MD = *i; 6309193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 6310223017Sdim if (!C) 6311223017Sdim return GetOrEmitProtocolRef(PD); 6312223017Sdim 6313193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 6314193326Sed OptClassMethods.push_back(C); 6315234353Sdim OptMethodTypesExt.push_back(GetMethodVarType(MD, true)); 6316193326Sed } else { 6317193326Sed ClassMethods.push_back(C); 6318234353Sdim MethodTypesExt.push_back(GetMethodVarType(MD, true)); 6319198092Srdivacky } 6320193326Sed } 6321198092Srdivacky 6322234353Sdim MethodTypesExt.insert(MethodTypesExt.end(), 6323234353Sdim OptMethodTypesExt.begin(), OptMethodTypesExt.end()); 6324234353Sdim 6325234353Sdim llvm::Constant *Values[11]; 6326193326Sed // isa is NULL 6327193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy); 6328193326Sed Values[1] = GetClassName(PD->getIdentifier()); 6329198398Srdivacky Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(), 6330198398Srdivacky PD->protocol_begin(), 6331198398Srdivacky PD->protocol_end()); 6332198092Srdivacky 6333193326Sed Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_" 6334198398Srdivacky + PD->getName(), 6335193326Sed "__DATA, __objc_const", 6336193326Sed InstanceMethods); 6337198092Srdivacky Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_" 6338198398Srdivacky + PD->getName(), 6339193326Sed "__DATA, __objc_const", 6340193326Sed ClassMethods); 6341193326Sed Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_" 6342198398Srdivacky + PD->getName(), 6343193326Sed "__DATA, __objc_const", 6344193326Sed OptInstanceMethods); 6345198092Srdivacky Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_" 6346198398Srdivacky + PD->getName(), 6347193326Sed "__DATA, __objc_const", 6348193326Sed OptClassMethods); 6349198398Srdivacky Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(), 6350193326Sed 0, PD, ObjCTypes); 6351198092Srdivacky uint32_t Size = 6352243830Sdim CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); 6353193326Sed Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 6354193326Sed Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy); 6355234353Sdim Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_" 6356234353Sdim + PD->getName(), 6357234353Sdim MethodTypesExt, ObjCTypes); 6358193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy, 6359193326Sed Values); 6360198092Srdivacky 6361193326Sed if (Entry) { 6362193326Sed // Already created, fix the linkage and update the initializer. 6363193326Sed Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6364193326Sed Entry->setInitializer(Init); 6365193326Sed } else { 6366198092Srdivacky Entry = 6367198398Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, 6368198398Srdivacky false, llvm::GlobalValue::WeakAnyLinkage, Init, 6369198398Srdivacky "\01l_OBJC_PROTOCOL_$_" + PD->getName()); 6370193326Sed Entry->setAlignment( 6371243830Sdim CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy)); 6372193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 6373234353Sdim 6374234353Sdim Protocols[PD->getIdentifier()] = Entry; 6375193326Sed } 6376193326Sed Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); 6377198092Srdivacky CGM.AddUsedGlobal(Entry); 6378198092Srdivacky 6379193326Sed // Use this protocol meta-data to build protocol list table in section 6380193326Sed // __DATA, __objc_protolist 6381198398Srdivacky llvm::GlobalVariable *PTGV = 6382198398Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, 6383198398Srdivacky false, llvm::GlobalValue::WeakAnyLinkage, Entry, 6384198398Srdivacky "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName()); 6385193326Sed PTGV->setAlignment( 6386243830Sdim CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); 6387193326Sed PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip"); 6388193326Sed PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 6389198092Srdivacky CGM.AddUsedGlobal(PTGV); 6390193326Sed return Entry; 6391193326Sed} 6392193326Sed 6393193326Sed/// EmitProtocolList - Generate protocol list meta-data: 6394193326Sed/// @code 6395193326Sed/// struct _protocol_list_t { 6396193326Sed/// long protocol_count; // Note, this is 32/64 bit 6397193326Sed/// struct _protocol_t[protocol_count]; 6398193326Sed/// } 6399193326Sed/// @endcode 6400193326Sed/// 6401193326Sedllvm::Constant * 6402226633SdimCGObjCNonFragileABIMac::EmitProtocolList(Twine Name, 6403198398Srdivacky ObjCProtocolDecl::protocol_iterator begin, 6404198398Srdivacky ObjCProtocolDecl::protocol_iterator end) { 6405249423Sdim SmallVector<llvm::Constant *, 16> ProtocolRefs; 6406198092Srdivacky 6407193326Sed // Just return null for empty protocol lists 6408198092Srdivacky if (begin == end) 6409193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); 6410198092Srdivacky 6411193326Sed // FIXME: We shouldn't need to do this lookup here, should we? 6412234353Sdim SmallString<256> TmpName; 6413198398Srdivacky Name.toVector(TmpName); 6414198398Srdivacky llvm::GlobalVariable *GV = 6415198398Srdivacky CGM.getModule().getGlobalVariable(TmpName.str(), true); 6416193326Sed if (GV) 6417198398Srdivacky return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy); 6418198092Srdivacky 6419193326Sed for (; begin != end; ++begin) 6420193326Sed ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented??? 6421193326Sed 6422193326Sed // This list is null terminated. 6423193326Sed ProtocolRefs.push_back(llvm::Constant::getNullValue( 6424198092Srdivacky ObjCTypes.ProtocolnfABIPtrTy)); 6425198092Srdivacky 6426224145Sdim llvm::Constant *Values[2]; 6427198092Srdivacky Values[0] = 6428198092Srdivacky llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1); 6429198092Srdivacky Values[1] = 6430234353Sdim llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy, 6431234353Sdim ProtocolRefs.size()), 6432234353Sdim ProtocolRefs); 6433198092Srdivacky 6434224145Sdim llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values); 6435198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 6436193326Sed llvm::GlobalValue::InternalLinkage, 6437224145Sdim Init, Name); 6438193326Sed GV->setSection("__DATA, __objc_const"); 6439193326Sed GV->setAlignment( 6440243830Sdim CGM.getDataLayout().getABITypeAlignment(Init->getType())); 6441198092Srdivacky CGM.AddUsedGlobal(GV); 6442198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, 6443193326Sed ObjCTypes.ProtocolListnfABIPtrTy); 6444193326Sed} 6445193326Sed 6446193326Sed/// GetMethodDescriptionConstant - This routine build following meta-data: 6447193326Sed/// struct _objc_method { 6448193326Sed/// SEL _cmd; 6449193326Sed/// char *method_type; 6450193326Sed/// char *_imp; 6451193326Sed/// } 6452193326Sed 6453193326Sedllvm::Constant * 6454193326SedCGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { 6455234353Sdim llvm::Constant *Desc[3]; 6456198092Srdivacky Desc[0] = 6457198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 6458198092Srdivacky ObjCTypes.SelectorPtrTy); 6459193326Sed Desc[1] = GetMethodVarType(MD); 6460223017Sdim if (!Desc[1]) 6461223017Sdim return 0; 6462223017Sdim 6463193326Sed // Protocol methods have no implementation. So, this entry is always NULL. 6464193326Sed Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 6465193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc); 6466193326Sed} 6467193326Sed 6468193326Sed/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference. 6469193326Sed/// This code gen. amounts to generating code for: 6470193326Sed/// @code 6471193326Sed/// (type *)((char *)base + _OBJC_IVAR_$_.ivar; 6472193326Sed/// @encode 6473198092Srdivacky/// 6474193326SedLValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( 6475208600Srdivacky CodeGen::CodeGenFunction &CGF, 6476208600Srdivacky QualType ObjectTy, 6477208600Srdivacky llvm::Value *BaseValue, 6478208600Srdivacky const ObjCIvarDecl *Ivar, 6479208600Srdivacky unsigned CVRQualifiers) { 6480208600Srdivacky ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface(); 6481234353Sdim llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar); 6482249423Sdim 6483249423Sdim if (IsIvarOffsetKnownIdempotent(CGF, ID, Ivar)) 6484249423Sdim if (llvm::LoadInst *LI = cast<llvm::LoadInst>(Offset)) 6485249423Sdim LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"), 6486249423Sdim llvm::MDNode::get(VMContext, ArrayRef<llvm::Value*>())); 6487249423Sdim 6488193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 6489234353Sdim Offset); 6490193326Sed} 6491193326Sed 6492193326Sedllvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset( 6493198092Srdivacky CodeGen::CodeGenFunction &CGF, 6494198092Srdivacky const ObjCInterfaceDecl *Interface, 6495198092Srdivacky const ObjCIvarDecl *Ivar) { 6496199990Srdivacky return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar"); 6497193326Sed} 6498193326Sed 6499223017Sdimstatic void appendSelectorForMessageRefTable(std::string &buffer, 6500223017Sdim Selector selector) { 6501223017Sdim if (selector.isUnarySelector()) { 6502223017Sdim buffer += selector.getNameForSlot(0); 6503223017Sdim return; 6504223017Sdim } 6505198092Srdivacky 6506223017Sdim for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) { 6507223017Sdim buffer += selector.getNameForSlot(i); 6508223017Sdim buffer += '_'; 6509223017Sdim } 6510223017Sdim} 6511223017Sdim 6512223017Sdim/// Emit a "v-table" message send. We emit a weak hidden-visibility 6513223017Sdim/// struct, initially containing the selector pointer and a pointer to 6514223017Sdim/// a "fixup" variant of the appropriate objc_msgSend. To call, we 6515223017Sdim/// load and call the function pointer, passing the address of the 6516223017Sdim/// struct as the second parameter. The runtime determines whether 6517223017Sdim/// the selector is currently emitted using vtable dispatch; if so, it 6518223017Sdim/// substitutes a stub function which simply tail-calls through the 6519223017Sdim/// appropriate vtable slot, and if not, it substitues a stub function 6520223017Sdim/// which tail-calls objc_msgSend. Both stubs adjust the selector 6521223017Sdim/// argument to correctly point to the selector. 6522223017SdimRValue 6523223017SdimCGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, 6524223017Sdim ReturnValueSlot returnSlot, 6525223017Sdim QualType resultType, 6526223017Sdim Selector selector, 6527223017Sdim llvm::Value *arg0, 6528223017Sdim QualType arg0Type, 6529223017Sdim bool isSuper, 6530223017Sdim const CallArgList &formalArgs, 6531223017Sdim const ObjCMethodDecl *method) { 6532223017Sdim // Compute the actual arguments. 6533223017Sdim CallArgList args; 6534223017Sdim 6535223017Sdim // First argument: the receiver / super-call structure. 6536223017Sdim if (!isSuper) 6537223017Sdim arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy); 6538223017Sdim args.add(RValue::get(arg0), arg0Type); 6539223017Sdim 6540223017Sdim // Second argument: a pointer to the message ref structure. Leave 6541223017Sdim // the actual argument value blank for now. 6542223017Sdim args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy); 6543223017Sdim 6544223017Sdim args.insert(args.end(), formalArgs.begin(), formalArgs.end()); 6545223017Sdim 6546234353Sdim MessageSendInfo MSI = getMessageSendInfo(method, resultType, args); 6547223017Sdim 6548223017Sdim NullReturnState nullReturn; 6549223017Sdim 6550223017Sdim // Find the function to call and the mangled name for the message 6551223017Sdim // ref structure. Using a different mangled name wouldn't actually 6552223017Sdim // be a problem; it would just be a waste. 6553223017Sdim // 6554223017Sdim // The runtime currently never uses vtable dispatch for anything 6555223017Sdim // except normal, non-super message-sends. 6556223017Sdim // FIXME: don't use this for that. 6557223017Sdim llvm::Constant *fn = 0; 6558223017Sdim std::string messageRefName("\01l_"); 6559234353Sdim if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) { 6560223017Sdim if (isSuper) { 6561223017Sdim fn = ObjCTypes.getMessageSendSuper2StretFixupFn(); 6562223017Sdim messageRefName += "objc_msgSendSuper2_stret_fixup"; 6563212904Sdim } else { 6564223017Sdim nullReturn.init(CGF, arg0); 6565223017Sdim fn = ObjCTypes.getMessageSendStretFixupFn(); 6566223017Sdim messageRefName += "objc_msgSend_stret_fixup"; 6567212904Sdim } 6568223017Sdim } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) { 6569223017Sdim fn = ObjCTypes.getMessageSendFpretFixupFn(); 6570223017Sdim messageRefName += "objc_msgSend_fpret_fixup"; 6571198092Srdivacky } else { 6572223017Sdim if (isSuper) { 6573223017Sdim fn = ObjCTypes.getMessageSendSuper2FixupFn(); 6574223017Sdim messageRefName += "objc_msgSendSuper2_fixup"; 6575212904Sdim } else { 6576223017Sdim fn = ObjCTypes.getMessageSendFixupFn(); 6577223017Sdim messageRefName += "objc_msgSend_fixup"; 6578212904Sdim } 6579193326Sed } 6580223017Sdim assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend"); 6581223017Sdim messageRefName += '_'; 6582223017Sdim 6583223017Sdim // Append the selector name, except use underscores anywhere we 6584223017Sdim // would have used colons. 6585223017Sdim appendSelectorForMessageRefTable(messageRefName, selector); 6586223017Sdim 6587223017Sdim llvm::GlobalVariable *messageRef 6588223017Sdim = CGM.getModule().getGlobalVariable(messageRefName); 6589223017Sdim if (!messageRef) { 6590223017Sdim // Build the message ref structure. 6591223017Sdim llvm::Constant *values[] = { fn, GetMethodVarName(selector) }; 6592224145Sdim llvm::Constant *init = llvm::ConstantStruct::getAnon(values); 6593223017Sdim messageRef = new llvm::GlobalVariable(CGM.getModule(), 6594223017Sdim init->getType(), 6595223017Sdim /*constant*/ false, 6596223017Sdim llvm::GlobalValue::WeakAnyLinkage, 6597223017Sdim init, 6598223017Sdim messageRefName); 6599223017Sdim messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility); 6600223017Sdim messageRef->setAlignment(16); 6601223017Sdim messageRef->setSection("__DATA, __objc_msgrefs, coalesced"); 6602193326Sed } 6603234353Sdim 6604234353Sdim bool requiresnullCheck = false; 6605234353Sdim if (CGM.getLangOpts().ObjCAutoRefCount && method) 6606234353Sdim for (ObjCMethodDecl::param_const_iterator i = method->param_begin(), 6607234353Sdim e = method->param_end(); i != e; ++i) { 6608234353Sdim const ParmVarDecl *ParamDecl = (*i); 6609234353Sdim if (ParamDecl->hasAttr<NSConsumedAttr>()) { 6610234353Sdim if (!nullReturn.NullBB) 6611234353Sdim nullReturn.init(CGF, arg0); 6612234353Sdim requiresnullCheck = true; 6613234353Sdim break; 6614234353Sdim } 6615234353Sdim } 6616234353Sdim 6617223017Sdim llvm::Value *mref = 6618223017Sdim CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy); 6619198092Srdivacky 6620223017Sdim // Update the message ref argument. 6621223017Sdim args[1].RV = RValue::get(mref); 6622223017Sdim 6623223017Sdim // Load the function to call from the message ref table. 6624223017Sdim llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0); 6625223017Sdim callee = CGF.Builder.CreateLoad(callee, "msgSend_fn"); 6626223017Sdim 6627234353Sdim callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType); 6628223017Sdim 6629234353Sdim RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args); 6630234353Sdim return nullReturn.complete(CGF, result, resultType, formalArgs, 6631234353Sdim requiresnullCheck ? method : 0); 6632193326Sed} 6633193326Sed 6634193326Sed/// Generate code for a message send expression in the nonfragile abi. 6635198092SrdivackyCodeGen::RValue 6636198092SrdivackyCGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 6637208600Srdivacky ReturnValueSlot Return, 6638198092Srdivacky QualType ResultType, 6639198092Srdivacky Selector Sel, 6640198092Srdivacky llvm::Value *Receiver, 6641198092Srdivacky const CallArgList &CallArgs, 6642207619Srdivacky const ObjCInterfaceDecl *Class, 6643198092Srdivacky const ObjCMethodDecl *Method) { 6644223017Sdim return isVTableDispatchedSelector(Sel) 6645223017Sdim ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, 6646198092Srdivacky Receiver, CGF.getContext().getObjCIdType(), 6647223017Sdim false, CallArgs, Method) 6648223017Sdim : EmitMessageSend(CGF, Return, ResultType, 6649249423Sdim EmitSelector(CGF, Sel), 6650198092Srdivacky Receiver, CGF.getContext().getObjCIdType(), 6651223017Sdim false, CallArgs, Method, ObjCTypes); 6652193326Sed} 6653193326Sed 6654193326Sedllvm::GlobalVariable * 6655193326SedCGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) { 6656193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 6657193326Sed 6658193326Sed if (!GV) { 6659198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy, 6660198092Srdivacky false, llvm::GlobalValue::ExternalLinkage, 6661198092Srdivacky 0, Name); 6662193326Sed } 6663193326Sed 6664193326Sed return GV; 6665193326Sed} 6666193326Sed 6667249423Sdimllvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, 6668224145Sdim IdentifierInfo *II) { 6669224145Sdim llvm::GlobalVariable *&Entry = ClassReferences[II]; 6670224145Sdim 6671193326Sed if (!Entry) { 6672224145Sdim std::string ClassName(getClassSymbolPrefix() + II->getName().str()); 6673193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 6674198092Srdivacky Entry = 6675224145Sdim new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, 6676224145Sdim false, llvm::GlobalValue::InternalLinkage, 6677224145Sdim ClassGV, 6678224145Sdim "\01L_OBJC_CLASSLIST_REFERENCES_$_"); 6679193326Sed Entry->setAlignment( 6680243830Sdim CGM.getDataLayout().getABITypeAlignment( 6681224145Sdim ObjCTypes.ClassnfABIPtrTy)); 6682193326Sed Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip"); 6683198092Srdivacky CGM.AddUsedGlobal(Entry); 6684193326Sed } 6685224145Sdim 6686249423Sdim return CGF.Builder.CreateLoad(Entry); 6687193326Sed} 6688193326Sed 6689249423Sdimllvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF, 6690224145Sdim const ObjCInterfaceDecl *ID) { 6691249423Sdim return EmitClassRefFromId(CGF, ID->getIdentifier()); 6692224145Sdim} 6693224145Sdim 6694224145Sdimllvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef( 6695249423Sdim CodeGenFunction &CGF) { 6696224145Sdim IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool"); 6697249423Sdim return EmitClassRefFromId(CGF, II); 6698224145Sdim} 6699224145Sdim 6700193326Sedllvm::Value * 6701249423SdimCGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF, 6702193326Sed const ObjCInterfaceDecl *ID) { 6703193326Sed llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()]; 6704198092Srdivacky 6705193326Sed if (!Entry) { 6706193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 6707193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 6708198092Srdivacky Entry = 6709198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, 6710198092Srdivacky false, llvm::GlobalValue::InternalLinkage, 6711198092Srdivacky ClassGV, 6712198092Srdivacky "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); 6713193326Sed Entry->setAlignment( 6714243830Sdim CGM.getDataLayout().getABITypeAlignment( 6715198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 6716193326Sed Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); 6717198092Srdivacky CGM.AddUsedGlobal(Entry); 6718193326Sed } 6719198092Srdivacky 6720249423Sdim return CGF.Builder.CreateLoad(Entry); 6721193326Sed} 6722193326Sed 6723193326Sed/// EmitMetaClassRef - Return a Value * of the address of _class_t 6724193326Sed/// meta-data 6725193326Sed/// 6726249423Sdimllvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF, 6727198092Srdivacky const ObjCInterfaceDecl *ID) { 6728193326Sed llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; 6729193326Sed if (Entry) 6730249423Sdim return CGF.Builder.CreateLoad(Entry); 6731198092Srdivacky 6732193326Sed std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString()); 6733193326Sed llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName); 6734198092Srdivacky Entry = 6735198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false, 6736193326Sed llvm::GlobalValue::InternalLinkage, 6737198092Srdivacky MetaClassGV, 6738198092Srdivacky "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); 6739193326Sed Entry->setAlignment( 6740243830Sdim CGM.getDataLayout().getABITypeAlignment( 6741198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 6742198092Srdivacky 6743193326Sed Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); 6744198092Srdivacky CGM.AddUsedGlobal(Entry); 6745198092Srdivacky 6746249423Sdim return CGF.Builder.CreateLoad(Entry); 6747193326Sed} 6748193326Sed 6749193326Sed/// GetClass - Return a reference to the class for the given interface 6750193326Sed/// decl. 6751249423Sdimllvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF, 6752193326Sed const ObjCInterfaceDecl *ID) { 6753221345Sdim if (ID->isWeakImported()) { 6754199482Srdivacky std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 6755199482Srdivacky llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 6756199482Srdivacky ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 6757199482Srdivacky } 6758199482Srdivacky 6759249423Sdim return EmitClassRef(CGF, ID); 6760193326Sed} 6761193326Sed 6762193326Sed/// Generates a message send where the super is the receiver. This is 6763193326Sed/// a message send to self with special delivery semantics indicating 6764193326Sed/// which class's method should be called. 6765193326SedCodeGen::RValue 6766193326SedCGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 6767208600Srdivacky ReturnValueSlot Return, 6768198092Srdivacky QualType ResultType, 6769198092Srdivacky Selector Sel, 6770198092Srdivacky const ObjCInterfaceDecl *Class, 6771198092Srdivacky bool isCategoryImpl, 6772198092Srdivacky llvm::Value *Receiver, 6773198092Srdivacky bool IsClassMessage, 6774198092Srdivacky const CodeGen::CallArgList &CallArgs, 6775198092Srdivacky const ObjCMethodDecl *Method) { 6776193326Sed // ... 6777193326Sed // Create and init a super structure; this is a (receiver, class) 6778193326Sed // pair we will pass to objc_msgSendSuper. 6779193326Sed llvm::Value *ObjCSuper = 6780221345Sdim CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super"); 6781198092Srdivacky 6782193326Sed llvm::Value *ReceiverAsObject = 6783193326Sed CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); 6784193326Sed CGF.Builder.CreateStore(ReceiverAsObject, 6785193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 6786198092Srdivacky 6787193326Sed // If this is a class message the metaclass is passed as the target. 6788193326Sed llvm::Value *Target; 6789243830Sdim if (IsClassMessage) 6790249423Sdim Target = EmitMetaClassRef(CGF, Class); 6791243830Sdim else 6792249423Sdim Target = EmitSuperClassRef(CGF, Class); 6793198092Srdivacky 6794193326Sed // FIXME: We shouldn't need to do this cast, rectify the ASTContext and 6795193326Sed // ObjCTypes types. 6796226633Sdim llvm::Type *ClassTy = 6797193326Sed CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); 6798193326Sed Target = CGF.Builder.CreateBitCast(Target, ClassTy); 6799193326Sed CGF.Builder.CreateStore(Target, 6800193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 6801198092Srdivacky 6802223017Sdim return (isVTableDispatchedSelector(Sel)) 6803223017Sdim ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, 6804198092Srdivacky ObjCSuper, ObjCTypes.SuperPtrCTy, 6805223017Sdim true, CallArgs, Method) 6806223017Sdim : EmitMessageSend(CGF, Return, ResultType, 6807249423Sdim EmitSelector(CGF, Sel), 6808198092Srdivacky ObjCSuper, ObjCTypes.SuperPtrCTy, 6809223017Sdim true, CallArgs, Method, ObjCTypes); 6810193326Sed} 6811193326Sed 6812249423Sdimllvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF, 6813210299Sed Selector Sel, bool lval) { 6814193326Sed llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; 6815198092Srdivacky 6816193326Sed if (!Entry) { 6817198092Srdivacky llvm::Constant *Casted = 6818198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), 6819198092Srdivacky ObjCTypes.SelectorPtrTy); 6820198092Srdivacky Entry = 6821198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false, 6822198092Srdivacky llvm::GlobalValue::InternalLinkage, 6823198092Srdivacky Casted, "\01L_OBJC_SELECTOR_REFERENCES_"); 6824249423Sdim Entry->setExternallyInitialized(true); 6825193326Sed Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip"); 6826198092Srdivacky CGM.AddUsedGlobal(Entry); 6827193326Sed } 6828198092Srdivacky 6829210299Sed if (lval) 6830210299Sed return Entry; 6831249423Sdim llvm::LoadInst* LI = CGF.Builder.CreateLoad(Entry); 6832234353Sdim 6833234353Sdim LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"), 6834234353Sdim llvm::MDNode::get(VMContext, 6835234353Sdim ArrayRef<llvm::Value*>())); 6836234353Sdim return LI; 6837193326Sed} 6838193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. 6839198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t) 6840193326Sed/// 6841193326Sedvoid CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 6842198092Srdivacky llvm::Value *src, 6843198092Srdivacky llvm::Value *dst, 6844198092Srdivacky llvm::Value *ivarOffset) { 6845226633Sdim llvm::Type * SrcTy = src->getType(); 6846193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 6847243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 6848193326Sed assert(Size <= 8 && "does not support size > 8"); 6849193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 6850193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 6851193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 6852193326Sed } 6853193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 6854193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 6855249423Sdim llvm::Value *args[] = { src, dst, ivarOffset }; 6856249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args); 6857193326Sed} 6858193326Sed 6859193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. 6860193326Sed/// objc_assign_strongCast (id src, id *dst) 6861193326Sed/// 6862193326Sedvoid CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( 6863198092Srdivacky CodeGen::CodeGenFunction &CGF, 6864198092Srdivacky llvm::Value *src, llvm::Value *dst) { 6865226633Sdim llvm::Type * SrcTy = src->getType(); 6866193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 6867243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 6868193326Sed assert(Size <= 8 && "does not support size > 8"); 6869193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 6870198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 6871193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 6872193326Sed } 6873193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 6874193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 6875249423Sdim llvm::Value *args[] = { src, dst }; 6876249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), 6877249423Sdim args, "weakassign"); 6878193326Sed} 6879193326Sed 6880198092Srdivackyvoid CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( 6881198092Srdivacky CodeGen::CodeGenFunction &CGF, 6882198092Srdivacky llvm::Value *DestPtr, 6883198092Srdivacky llvm::Value *SrcPtr, 6884210299Sed llvm::Value *Size) { 6885198092Srdivacky SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); 6886198092Srdivacky DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); 6887249423Sdim llvm::Value *args[] = { DestPtr, SrcPtr, Size }; 6888249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args); 6889198092Srdivacky} 6890198092Srdivacky 6891193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak 6892193326Sed/// object: objc_read_weak (id *src) 6893193326Sed/// 6894193326Sedllvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( 6895198092Srdivacky CodeGen::CodeGenFunction &CGF, 6896198092Srdivacky llvm::Value *AddrWeakObj) { 6897226633Sdim llvm::Type* DestTy = 6898198092Srdivacky cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); 6899198092Srdivacky AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy); 6900249423Sdim llvm::Value *read_weak = 6901249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), 6902249423Sdim AddrWeakObj, "weakread"); 6903193326Sed read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); 6904193326Sed return read_weak; 6905193326Sed} 6906193326Sed 6907193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. 6908193326Sed/// objc_assign_weak (id src, id *dst) 6909193326Sed/// 6910193326Sedvoid CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 6911198092Srdivacky llvm::Value *src, llvm::Value *dst) { 6912226633Sdim llvm::Type * SrcTy = src->getType(); 6913193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 6914243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 6915193326Sed assert(Size <= 8 && "does not support size > 8"); 6916193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 6917193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 6918193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 6919193326Sed } 6920193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 6921193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 6922249423Sdim llvm::Value *args[] = { src, dst }; 6923249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), 6924249423Sdim args, "weakassign"); 6925193326Sed} 6926193326Sed 6927193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. 6928193326Sed/// objc_assign_global (id src, id *dst) 6929193326Sed/// 6930193326Sedvoid CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 6931212904Sdim llvm::Value *src, llvm::Value *dst, 6932212904Sdim bool threadlocal) { 6933226633Sdim llvm::Type * SrcTy = src->getType(); 6934193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 6935243830Sdim unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); 6936193326Sed assert(Size <= 8 && "does not support size > 8"); 6937193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 6938193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 6939193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 6940193326Sed } 6941193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 6942193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 6943249423Sdim llvm::Value *args[] = { src, dst }; 6944212904Sdim if (!threadlocal) 6945249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), 6946249423Sdim args, "globalassign"); 6947212904Sdim else 6948249423Sdim CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), 6949249423Sdim args, "threadlocalassign"); 6950193326Sed} 6951193326Sed 6952198092Srdivackyvoid 6953210299SedCGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 6954210299Sed const ObjCAtSynchronizedStmt &S) { 6955221345Sdim EmitAtSynchronizedStmt(CGF, S, 6956221345Sdim cast<llvm::Function>(ObjCTypes.getSyncEnterFn()), 6957221345Sdim cast<llvm::Function>(ObjCTypes.getSyncExitFn())); 6958210299Sed} 6959193326Sed 6960212904Sdimllvm::Constant * 6961212904SdimCGObjCNonFragileABIMac::GetEHType(QualType T) { 6962212904Sdim // There's a particular fixed type info for 'id'. 6963212904Sdim if (T->isObjCIdType() || 6964212904Sdim T->isObjCQualifiedIdType()) { 6965212904Sdim llvm::Constant *IDEHType = 6966212904Sdim CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id"); 6967212904Sdim if (!IDEHType) 6968212904Sdim IDEHType = 6969212904Sdim new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, 6970212904Sdim false, 6971212904Sdim llvm::GlobalValue::ExternalLinkage, 6972212904Sdim 0, "OBJC_EHTYPE_id"); 6973212904Sdim return IDEHType; 6974212904Sdim } 6975212904Sdim 6976212904Sdim // All other types should be Objective-C interface pointer types. 6977212904Sdim const ObjCObjectPointerType *PT = 6978212904Sdim T->getAs<ObjCObjectPointerType>(); 6979212904Sdim assert(PT && "Invalid @catch type."); 6980212904Sdim const ObjCInterfaceType *IT = PT->getInterfaceType(); 6981212904Sdim assert(IT && "Invalid @catch type."); 6982212904Sdim return GetInterfaceEHType(IT->getDecl(), false); 6983212904Sdim} 6984212904Sdim 6985210299Sedvoid CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF, 6986210299Sed const ObjCAtTryStmt &S) { 6987221345Sdim EmitTryCatchStmt(CGF, S, 6988221345Sdim cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()), 6989221345Sdim cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()), 6990221345Sdim cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn())); 6991193326Sed} 6992193326Sed 6993193326Sed/// EmitThrowStmt - Generate code for a throw statement. 6994193326Sedvoid CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 6995249423Sdim const ObjCAtThrowStmt &S, 6996249423Sdim bool ClearInsertionPoint) { 6997193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 6998226633Sdim llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr); 6999226633Sdim Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy); 7000249423Sdim CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception) 7001218893Sdim .setDoesNotReturn(); 7002193326Sed } else { 7003249423Sdim CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn()) 7004218893Sdim .setDoesNotReturn(); 7005193326Sed } 7006193326Sed 7007218893Sdim CGF.Builder.CreateUnreachable(); 7008249423Sdim if (ClearInsertionPoint) 7009249423Sdim CGF.Builder.ClearInsertionPoint(); 7010193326Sed} 7011193326Sed 7012212904Sdimllvm::Constant * 7013198092SrdivackyCGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, 7014193326Sed bool ForDefinition) { 7015193326Sed llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()]; 7016193326Sed 7017193326Sed // If we don't need a definition, return the entry if found or check 7018193326Sed // if we use an external reference. 7019193326Sed if (!ForDefinition) { 7020193326Sed if (Entry) 7021193326Sed return Entry; 7022193326Sed 7023193326Sed // If this type (or a super class) has the __objc_exception__ 7024193326Sed // attribute, emit an external reference. 7025194613Sed if (hasObjCExceptionAttribute(CGM.getContext(), ID)) 7026198092Srdivacky return Entry = 7027198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, 7028193326Sed llvm::GlobalValue::ExternalLinkage, 7029198092Srdivacky 0, 7030198398Srdivacky ("OBJC_EHTYPE_$_" + 7031198092Srdivacky ID->getIdentifier()->getName())); 7032193326Sed } 7033198092Srdivacky 7034193326Sed // Otherwise we need to either make a new entry or fill in the 7035193326Sed // initializer. 7036193326Sed assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition"); 7037193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 7038193326Sed std::string VTableName = "objc_ehtype_vtable"; 7039198092Srdivacky llvm::GlobalVariable *VTableGV = 7040193326Sed CGM.getModule().getGlobalVariable(VTableName); 7041193326Sed if (!VTableGV) 7042198092Srdivacky VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, 7043198092Srdivacky false, 7044193326Sed llvm::GlobalValue::ExternalLinkage, 7045198092Srdivacky 0, VTableName); 7046193326Sed 7047234353Sdim llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2); 7048193326Sed 7049234353Sdim llvm::Constant *Values[] = { 7050234353Sdim llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx), 7051234353Sdim GetClassName(ID->getIdentifier()), 7052234353Sdim GetClassGlobal(ClassName) 7053234353Sdim }; 7054198092Srdivacky llvm::Constant *Init = 7055198092Srdivacky llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values); 7056193326Sed 7057193326Sed if (Entry) { 7058193326Sed Entry->setInitializer(Init); 7059193326Sed } else { 7060198092Srdivacky Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, 7061193326Sed llvm::GlobalValue::WeakAnyLinkage, 7062198092Srdivacky Init, 7063198398Srdivacky ("OBJC_EHTYPE_$_" + 7064198092Srdivacky ID->getIdentifier()->getName())); 7065193326Sed } 7066193326Sed 7067249423Sdim if (ID->getVisibility() == HiddenVisibility) 7068193326Sed Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); 7069243830Sdim Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment( 7070207619Srdivacky ObjCTypes.EHTypeTy)); 7071193326Sed 7072193326Sed if (ForDefinition) { 7073193326Sed Entry->setSection("__DATA,__objc_const"); 7074193326Sed Entry->setLinkage(llvm::GlobalValue::ExternalLinkage); 7075193326Sed } else { 7076193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 7077193326Sed } 7078193326Sed 7079193326Sed return Entry; 7080193326Sed} 7081198092Srdivacky 7082193326Sed/* *** */ 7083193326Sed 7084193326SedCodeGen::CGObjCRuntime * 7085193326SedCodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) { 7086239462Sdim switch (CGM.getLangOpts().ObjCRuntime.getKind()) { 7087239462Sdim case ObjCRuntime::FragileMacOSX: 7088239462Sdim return new CGObjCMac(CGM); 7089239462Sdim 7090239462Sdim case ObjCRuntime::MacOSX: 7091239462Sdim case ObjCRuntime::iOS: 7092221345Sdim return new CGObjCNonFragileABIMac(CGM); 7093239462Sdim 7094239462Sdim case ObjCRuntime::GNUstep: 7095239462Sdim case ObjCRuntime::GCC: 7096239462Sdim case ObjCRuntime::ObjFW: 7097239462Sdim llvm_unreachable("these runtimes are not Mac runtimes"); 7098239462Sdim } 7099239462Sdim llvm_unreachable("bad runtime"); 7100193326Sed} 7101