CGObjCMac.cpp revision 199482
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// 10193326Sed// This provides Objective-C code generation targetting the Apple runtime. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14193326Sed#include "CGObjCRuntime.h" 15193326Sed 16193326Sed#include "CodeGenModule.h" 17193326Sed#include "CodeGenFunction.h" 18193326Sed#include "clang/AST/ASTContext.h" 19193326Sed#include "clang/AST/Decl.h" 20193326Sed#include "clang/AST/DeclObjC.h" 21193326Sed#include "clang/AST/RecordLayout.h" 22193326Sed#include "clang/AST/StmtObjC.h" 23193326Sed#include "clang/Basic/LangOptions.h" 24193326Sed 25193326Sed#include "llvm/Intrinsics.h" 26198092Srdivacky#include "llvm/LLVMContext.h" 27193326Sed#include "llvm/Module.h" 28193326Sed#include "llvm/ADT/DenseSet.h" 29198092Srdivacky#include "llvm/ADT/SetVector.h" 30198092Srdivacky#include "llvm/ADT/SmallString.h" 31198092Srdivacky#include "llvm/Support/raw_ostream.h" 32193326Sed#include "llvm/Target/TargetData.h" 33198092Srdivacky#include <cstdio> 34193326Sed 35193326Sedusing namespace clang; 36193326Sedusing namespace CodeGen; 37193326Sed 38193326Sed// Common CGObjCRuntime functions, these don't belong here, but they 39193326Sed// don't belong in CGObjCRuntime either so we will live with it for 40193326Sed// now. 41193326Sed 42198092Srdivacky/// FindIvarInterface - Find the interface containing the ivar. 43193326Sed/// 44193326Sed/// FIXME: We shouldn't need to do this, the containing context should 45193326Sed/// be fixed. 46193326Sedstatic const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, 47193326Sed const ObjCInterfaceDecl *OID, 48193326Sed const ObjCIvarDecl *OIVD, 49193326Sed unsigned &Index) { 50193326Sed // FIXME: The index here is closely tied to how 51193326Sed // ASTContext::getObjCLayout is implemented. This should be fixed to 52193326Sed // get the information from the layout directly. 53193326Sed Index = 0; 54193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; 55193576Sed Context.ShallowCollectObjCIvars(OID, Ivars); 56193326Sed for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { 57193326Sed if (OIVD == Ivars[k]) 58193326Sed return OID; 59193326Sed ++Index; 60193326Sed } 61198092Srdivacky 62193326Sed // Otherwise check in the super class. 63193326Sed if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 64193326Sed return FindIvarInterface(Context, Super, OIVD, Index); 65198092Srdivacky 66193326Sed return 0; 67193326Sed} 68193326Sed 69193326Sedstatic uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, 70193326Sed const ObjCInterfaceDecl *OID, 71193326Sed const ObjCImplementationDecl *ID, 72193326Sed const ObjCIvarDecl *Ivar) { 73193326Sed unsigned Index; 74198092Srdivacky const ObjCInterfaceDecl *Container = 75193326Sed FindIvarInterface(CGM.getContext(), OID, Ivar, Index); 76193326Sed assert(Container && "Unable to find ivar container"); 77193326Sed 78193326Sed // If we know have an implementation (and the ivar is in it) then 79193326Sed // look up in the implementation layout. 80198092Srdivacky const ASTRecordLayout *RL; 81193326Sed if (ID && ID->getClassInterface() == Container) 82193326Sed RL = &CGM.getContext().getASTObjCImplementationLayout(ID); 83193326Sed else 84193326Sed RL = &CGM.getContext().getASTObjCInterfaceLayout(Container); 85193326Sed return RL->getFieldOffset(Index); 86193326Sed} 87193326Sed 88193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, 89193326Sed const ObjCInterfaceDecl *OID, 90193326Sed const ObjCIvarDecl *Ivar) { 91193326Sed return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8; 92193326Sed} 93193326Sed 94193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, 95193326Sed const ObjCImplementationDecl *OID, 96193326Sed const ObjCIvarDecl *Ivar) { 97193326Sed return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8; 98193326Sed} 99193326Sed 100193326SedLValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, 101193326Sed const ObjCInterfaceDecl *OID, 102193326Sed llvm::Value *BaseValue, 103193326Sed const ObjCIvarDecl *Ivar, 104193326Sed unsigned CVRQualifiers, 105193326Sed llvm::Value *Offset) { 106193326Sed // Compute (type*) ( (char *) BaseValue + Offset) 107198092Srdivacky const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 108193326Sed QualType IvarTy = Ivar->getType(); 109193326Sed const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); 110193326Sed llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr); 111193326Sed V = CGF.Builder.CreateGEP(V, Offset, "add.ptr"); 112193326Sed V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); 113198092Srdivacky 114198092Srdivacky Qualifiers Quals = CGF.MakeQualifiers(IvarTy); 115198092Srdivacky Quals.addCVRQualifiers(CVRQualifiers); 116198092Srdivacky 117193326Sed if (Ivar->isBitField()) { 118193326Sed // We need to compute the bit offset for the bit-field, the offset 119193326Sed // is to the byte. Note, there is a subtle invariant here: we can 120193326Sed // only call this routine on non-sythesized ivars but we may be 121193326Sed // called for synthesized ivars. However, a synthesized ivar can 122193326Sed // never be a bit-field so this is safe. 123193326Sed uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar) % 8; 124193326Sed 125193326Sed uint64_t BitFieldSize = 126193326Sed Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); 127193326Sed return LValue::MakeBitfield(V, BitOffset, BitFieldSize, 128193326Sed IvarTy->isSignedIntegerType(), 129198092Srdivacky Quals.getCVRQualifiers()); 130193326Sed } 131193326Sed 132198092Srdivacky 133198092Srdivacky LValue LV = LValue::MakeAddr(V, Quals); 134193326Sed return LV; 135193326Sed} 136193326Sed 137193326Sed/// 138193326Sed 139193326Sednamespace { 140193326Sed 141198092Srdivackytypedef std::vector<llvm::Constant*> ConstantVector; 142193326Sed 143198092Srdivacky// FIXME: We should find a nicer way to make the labels for metadata, string 144198092Srdivacky// concatenation is lame. 145193326Sed 146193326Sedclass ObjCCommonTypesHelper { 147198092Srdivackyprotected: 148198092Srdivacky llvm::LLVMContext &VMContext; 149198092Srdivacky 150193326Sedprivate: 151193326Sed llvm::Constant *getMessageSendFn() const { 152193326Sed // id objc_msgSend (id, SEL, ...) 153193326Sed std::vector<const llvm::Type*> Params; 154193326Sed Params.push_back(ObjectPtrTy); 155193326Sed Params.push_back(SelectorPtrTy); 156193326Sed return 157198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 158198092Srdivacky Params, true), 159198092Srdivacky "objc_msgSend"); 160193326Sed } 161198092Srdivacky 162193326Sed llvm::Constant *getMessageSendStretFn() const { 163193326Sed // id objc_msgSend_stret (id, SEL, ...) 164193326Sed std::vector<const llvm::Type*> Params; 165193326Sed Params.push_back(ObjectPtrTy); 166193326Sed Params.push_back(SelectorPtrTy); 167193326Sed return 168198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 169198092Srdivacky Params, true), 170198092Srdivacky "objc_msgSend_stret"); 171198092Srdivacky 172193326Sed } 173198092Srdivacky 174193326Sed llvm::Constant *getMessageSendFpretFn() const { 175193326Sed // FIXME: This should be long double on x86_64? 176193326Sed // [double | long double] objc_msgSend_fpret(id self, SEL op, ...) 177193326Sed std::vector<const llvm::Type*> Params; 178193326Sed Params.push_back(ObjectPtrTy); 179193326Sed Params.push_back(SelectorPtrTy); 180193326Sed return 181198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get( 182198092Srdivacky llvm::Type::getDoubleTy(VMContext), 183198092Srdivacky Params, 184198092Srdivacky true), 185198092Srdivacky "objc_msgSend_fpret"); 186198092Srdivacky 187193326Sed } 188198092Srdivacky 189193326Sed llvm::Constant *getMessageSendSuperFn() const { 190193326Sed // id objc_msgSendSuper(struct objc_super *super, SEL op, ...) 191193326Sed const char *SuperName = "objc_msgSendSuper"; 192193326Sed std::vector<const llvm::Type*> Params; 193193326Sed Params.push_back(SuperPtrTy); 194193326Sed Params.push_back(SelectorPtrTy); 195193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 196193326Sed Params, true), 197193326Sed SuperName); 198193326Sed } 199198092Srdivacky 200193326Sed llvm::Constant *getMessageSendSuperFn2() const { 201193326Sed // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...) 202193326Sed const char *SuperName = "objc_msgSendSuper2"; 203193326Sed std::vector<const llvm::Type*> Params; 204193326Sed Params.push_back(SuperPtrTy); 205193326Sed Params.push_back(SelectorPtrTy); 206193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 207193326Sed Params, true), 208193326Sed SuperName); 209193326Sed } 210198092Srdivacky 211193326Sed llvm::Constant *getMessageSendSuperStretFn() const { 212193326Sed // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super, 213193326Sed // SEL op, ...) 214193326Sed std::vector<const llvm::Type*> Params; 215193326Sed Params.push_back(Int8PtrTy); 216193326Sed Params.push_back(SuperPtrTy); 217193326Sed Params.push_back(SelectorPtrTy); 218198092Srdivacky return CGM.CreateRuntimeFunction( 219198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 220198092Srdivacky Params, true), 221198092Srdivacky "objc_msgSendSuper_stret"); 222193326Sed } 223198092Srdivacky 224193326Sed llvm::Constant *getMessageSendSuperStretFn2() const { 225193326Sed // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super, 226193326Sed // SEL op, ...) 227193326Sed std::vector<const llvm::Type*> Params; 228193326Sed Params.push_back(Int8PtrTy); 229193326Sed Params.push_back(SuperPtrTy); 230193326Sed Params.push_back(SelectorPtrTy); 231198092Srdivacky return CGM.CreateRuntimeFunction( 232198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 233198092Srdivacky Params, true), 234198092Srdivacky "objc_msgSendSuper2_stret"); 235193326Sed } 236198092Srdivacky 237193326Sed llvm::Constant *getMessageSendSuperFpretFn() const { 238193326Sed // There is no objc_msgSendSuper_fpret? How can that work? 239193326Sed return getMessageSendSuperFn(); 240193326Sed } 241198092Srdivacky 242193326Sed llvm::Constant *getMessageSendSuperFpretFn2() const { 243193326Sed // There is no objc_msgSendSuper_fpret? How can that work? 244193326Sed return getMessageSendSuperFn2(); 245193326Sed } 246198092Srdivacky 247193326Sedprotected: 248193326Sed CodeGen::CodeGenModule &CGM; 249198092Srdivacky 250193326Sedpublic: 251193326Sed const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy; 252193326Sed const llvm::Type *Int8PtrTy; 253198092Srdivacky 254193326Sed /// ObjectPtrTy - LLVM type for object handles (typeof(id)) 255193326Sed const llvm::Type *ObjectPtrTy; 256198092Srdivacky 257193326Sed /// PtrObjectPtrTy - LLVM type for id * 258193326Sed const llvm::Type *PtrObjectPtrTy; 259198092Srdivacky 260193326Sed /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL)) 261193326Sed const llvm::Type *SelectorPtrTy; 262193326Sed /// ProtocolPtrTy - LLVM type for external protocol handles 263193326Sed /// (typeof(Protocol)) 264193326Sed const llvm::Type *ExternalProtocolPtrTy; 265198092Srdivacky 266193326Sed // SuperCTy - clang type for struct objc_super. 267193326Sed QualType SuperCTy; 268193326Sed // SuperPtrCTy - clang type for struct objc_super *. 269193326Sed QualType SuperPtrCTy; 270198092Srdivacky 271193326Sed /// SuperTy - LLVM type for struct objc_super. 272193326Sed const llvm::StructType *SuperTy; 273193326Sed /// SuperPtrTy - LLVM type for struct objc_super *. 274193326Sed const llvm::Type *SuperPtrTy; 275198092Srdivacky 276193326Sed /// PropertyTy - LLVM type for struct objc_property (struct _prop_t 277193326Sed /// in GCC parlance). 278193326Sed const llvm::StructType *PropertyTy; 279198092Srdivacky 280193326Sed /// PropertyListTy - LLVM type for struct objc_property_list 281193326Sed /// (_prop_list_t in GCC parlance). 282193326Sed const llvm::StructType *PropertyListTy; 283193326Sed /// PropertyListPtrTy - LLVM type for struct objc_property_list*. 284193326Sed const llvm::Type *PropertyListPtrTy; 285198092Srdivacky 286193326Sed // MethodTy - LLVM type for struct objc_method. 287193326Sed const llvm::StructType *MethodTy; 288198092Srdivacky 289193326Sed /// CacheTy - LLVM type for struct objc_cache. 290193326Sed const llvm::Type *CacheTy; 291193326Sed /// CachePtrTy - LLVM type for struct objc_cache *. 292193326Sed const llvm::Type *CachePtrTy; 293198092Srdivacky 294193326Sed llvm::Constant *getGetPropertyFn() { 295193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 296193326Sed ASTContext &Ctx = CGM.getContext(); 297193326Sed // id objc_getProperty (id, SEL, ptrdiff_t, bool) 298193326Sed llvm::SmallVector<QualType,16> Params; 299193326Sed QualType IdType = Ctx.getObjCIdType(); 300193326Sed QualType SelType = Ctx.getObjCSelType(); 301193326Sed Params.push_back(IdType); 302193326Sed Params.push_back(SelType); 303193326Sed Params.push_back(Ctx.LongTy); 304193326Sed Params.push_back(Ctx.BoolTy); 305193326Sed const llvm::FunctionType *FTy = 306193326Sed Types.GetFunctionType(Types.getFunctionInfo(IdType, Params), false); 307193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_getProperty"); 308193326Sed } 309198092Srdivacky 310193326Sed llvm::Constant *getSetPropertyFn() { 311193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 312193326Sed ASTContext &Ctx = CGM.getContext(); 313193326Sed // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) 314193326Sed llvm::SmallVector<QualType,16> Params; 315193326Sed QualType IdType = Ctx.getObjCIdType(); 316193326Sed QualType SelType = Ctx.getObjCSelType(); 317193326Sed Params.push_back(IdType); 318193326Sed Params.push_back(SelType); 319193326Sed Params.push_back(Ctx.LongTy); 320193326Sed Params.push_back(IdType); 321193326Sed Params.push_back(Ctx.BoolTy); 322193326Sed Params.push_back(Ctx.BoolTy); 323193326Sed const llvm::FunctionType *FTy = 324193326Sed Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false); 325193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_setProperty"); 326193326Sed } 327198092Srdivacky 328193326Sed llvm::Constant *getEnumerationMutationFn() { 329198092Srdivacky CodeGen::CodeGenTypes &Types = CGM.getTypes(); 330198092Srdivacky ASTContext &Ctx = CGM.getContext(); 331193326Sed // void objc_enumerationMutation (id) 332198092Srdivacky llvm::SmallVector<QualType,16> Params; 333198092Srdivacky Params.push_back(Ctx.getObjCIdType()); 334198092Srdivacky const llvm::FunctionType *FTy = 335198092Srdivacky Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false); 336193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); 337193326Sed } 338198092Srdivacky 339193326Sed /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function. 340193326Sed llvm::Constant *getGcReadWeakFn() { 341193326Sed // id objc_read_weak (id *) 342193326Sed std::vector<const llvm::Type*> Args; 343193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 344198092Srdivacky llvm::FunctionType *FTy = 345198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 346193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); 347198092Srdivacky } 348198092Srdivacky 349193326Sed /// GcAssignWeakFn -- LLVM objc_assign_weak function. 350193326Sed llvm::Constant *getGcAssignWeakFn() { 351193326Sed // id objc_assign_weak (id, id *) 352193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 353193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 354193326Sed llvm::FunctionType *FTy = 355193326Sed llvm::FunctionType::get(ObjectPtrTy, Args, false); 356193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); 357193326Sed } 358198092Srdivacky 359193326Sed /// GcAssignGlobalFn -- LLVM objc_assign_global function. 360193326Sed llvm::Constant *getGcAssignGlobalFn() { 361193326Sed // id objc_assign_global(id, id *) 362193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 363193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 364198092Srdivacky llvm::FunctionType *FTy = 365198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 366193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); 367193326Sed } 368198092Srdivacky 369193326Sed /// GcAssignIvarFn -- LLVM objc_assign_ivar function. 370193326Sed llvm::Constant *getGcAssignIvarFn() { 371198092Srdivacky // id objc_assign_ivar(id, id *, ptrdiff_t) 372193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 373193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 374198092Srdivacky Args.push_back(LongTy); 375198092Srdivacky llvm::FunctionType *FTy = 376198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 377193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); 378193326Sed } 379198092Srdivacky 380198092Srdivacky /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function. 381198092Srdivacky llvm::Constant *GcMemmoveCollectableFn() { 382198092Srdivacky // void *objc_memmove_collectable(void *dst, const void *src, size_t size) 383198092Srdivacky std::vector<const llvm::Type*> Args(1, Int8PtrTy); 384198092Srdivacky Args.push_back(Int8PtrTy); 385198092Srdivacky Args.push_back(LongTy); 386198092Srdivacky llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false); 387198092Srdivacky return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); 388198092Srdivacky } 389198092Srdivacky 390193326Sed /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function. 391193326Sed llvm::Constant *getGcAssignStrongCastFn() { 392193326Sed // id objc_assign_global(id, id *) 393193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 394193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 395198092Srdivacky llvm::FunctionType *FTy = 396198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 397193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); 398193326Sed } 399193326Sed 400193326Sed /// ExceptionThrowFn - LLVM objc_exception_throw function. 401193326Sed llvm::Constant *getExceptionThrowFn() { 402193326Sed // void objc_exception_throw(id) 403193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 404193326Sed llvm::FunctionType *FTy = 405198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 406193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); 407193326Sed } 408198092Srdivacky 409193326Sed /// SyncEnterFn - LLVM object_sync_enter function. 410193326Sed llvm::Constant *getSyncEnterFn() { 411193326Sed // void objc_sync_enter (id) 412193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 413193326Sed llvm::FunctionType *FTy = 414198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 415193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); 416193326Sed } 417198092Srdivacky 418193326Sed /// SyncExitFn - LLVM object_sync_exit function. 419193326Sed llvm::Constant *getSyncExitFn() { 420193326Sed // void objc_sync_exit (id) 421193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 422193326Sed llvm::FunctionType *FTy = 423198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 424193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); 425193326Sed } 426198092Srdivacky 427193326Sed llvm::Constant *getSendFn(bool IsSuper) const { 428193326Sed return IsSuper ? getMessageSendSuperFn() : getMessageSendFn(); 429193326Sed } 430198092Srdivacky 431193326Sed llvm::Constant *getSendFn2(bool IsSuper) const { 432193326Sed return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn(); 433193326Sed } 434198092Srdivacky 435193326Sed llvm::Constant *getSendStretFn(bool IsSuper) const { 436193326Sed return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn(); 437193326Sed } 438198092Srdivacky 439193326Sed llvm::Constant *getSendStretFn2(bool IsSuper) const { 440193326Sed return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn(); 441193326Sed } 442198092Srdivacky 443193326Sed llvm::Constant *getSendFpretFn(bool IsSuper) const { 444193326Sed return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn(); 445193326Sed } 446198092Srdivacky 447193326Sed llvm::Constant *getSendFpretFn2(bool IsSuper) const { 448193326Sed return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn(); 449193326Sed } 450198092Srdivacky 451193326Sed ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm); 452193326Sed ~ObjCCommonTypesHelper(){} 453193326Sed}; 454193326Sed 455193326Sed/// ObjCTypesHelper - Helper class that encapsulates lazy 456193326Sed/// construction of varies types used during ObjC generation. 457193326Sedclass ObjCTypesHelper : public ObjCCommonTypesHelper { 458193326Sedpublic: 459193326Sed /// SymtabTy - LLVM type for struct objc_symtab. 460193326Sed const llvm::StructType *SymtabTy; 461193326Sed /// SymtabPtrTy - LLVM type for struct objc_symtab *. 462193326Sed const llvm::Type *SymtabPtrTy; 463193326Sed /// ModuleTy - LLVM type for struct objc_module. 464193326Sed const llvm::StructType *ModuleTy; 465193326Sed 466193326Sed /// ProtocolTy - LLVM type for struct objc_protocol. 467193326Sed const llvm::StructType *ProtocolTy; 468193326Sed /// ProtocolPtrTy - LLVM type for struct objc_protocol *. 469193326Sed const llvm::Type *ProtocolPtrTy; 470193326Sed /// ProtocolExtensionTy - LLVM type for struct 471193326Sed /// objc_protocol_extension. 472193326Sed const llvm::StructType *ProtocolExtensionTy; 473193326Sed /// ProtocolExtensionTy - LLVM type for struct 474193326Sed /// objc_protocol_extension *. 475193326Sed const llvm::Type *ProtocolExtensionPtrTy; 476193326Sed /// MethodDescriptionTy - LLVM type for struct 477193326Sed /// objc_method_description. 478193326Sed const llvm::StructType *MethodDescriptionTy; 479193326Sed /// MethodDescriptionListTy - LLVM type for struct 480193326Sed /// objc_method_description_list. 481193326Sed const llvm::StructType *MethodDescriptionListTy; 482193326Sed /// MethodDescriptionListPtrTy - LLVM type for struct 483193326Sed /// objc_method_description_list *. 484193326Sed const llvm::Type *MethodDescriptionListPtrTy; 485193326Sed /// ProtocolListTy - LLVM type for struct objc_property_list. 486193326Sed const llvm::Type *ProtocolListTy; 487193326Sed /// ProtocolListPtrTy - LLVM type for struct objc_property_list*. 488193326Sed const llvm::Type *ProtocolListPtrTy; 489193326Sed /// CategoryTy - LLVM type for struct objc_category. 490193326Sed const llvm::StructType *CategoryTy; 491193326Sed /// ClassTy - LLVM type for struct objc_class. 492193326Sed const llvm::StructType *ClassTy; 493193326Sed /// ClassPtrTy - LLVM type for struct objc_class *. 494193326Sed const llvm::Type *ClassPtrTy; 495193326Sed /// ClassExtensionTy - LLVM type for struct objc_class_ext. 496193326Sed const llvm::StructType *ClassExtensionTy; 497193326Sed /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *. 498193326Sed const llvm::Type *ClassExtensionPtrTy; 499193326Sed // IvarTy - LLVM type for struct objc_ivar. 500193326Sed const llvm::StructType *IvarTy; 501193326Sed /// IvarListTy - LLVM type for struct objc_ivar_list. 502193326Sed const llvm::Type *IvarListTy; 503193326Sed /// IvarListPtrTy - LLVM type for struct objc_ivar_list *. 504193326Sed const llvm::Type *IvarListPtrTy; 505193326Sed /// MethodListTy - LLVM type for struct objc_method_list. 506193326Sed const llvm::Type *MethodListTy; 507193326Sed /// MethodListPtrTy - LLVM type for struct objc_method_list *. 508193326Sed const llvm::Type *MethodListPtrTy; 509198092Srdivacky 510193326Sed /// ExceptionDataTy - LLVM type for struct _objc_exception_data. 511193326Sed const llvm::Type *ExceptionDataTy; 512198092Srdivacky 513193326Sed /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function. 514193326Sed llvm::Constant *getExceptionTryEnterFn() { 515193326Sed std::vector<const llvm::Type*> Params; 516193326Sed Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); 517198092Srdivacky return CGM.CreateRuntimeFunction( 518198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 519198092Srdivacky Params, false), 520198092Srdivacky "objc_exception_try_enter"); 521193326Sed } 522193326Sed 523193326Sed /// ExceptionTryExitFn - LLVM objc_exception_try_exit function. 524193326Sed llvm::Constant *getExceptionTryExitFn() { 525193326Sed std::vector<const llvm::Type*> Params; 526193326Sed Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); 527198092Srdivacky return CGM.CreateRuntimeFunction( 528198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 529198092Srdivacky Params, false), 530198092Srdivacky "objc_exception_try_exit"); 531193326Sed } 532193326Sed 533193326Sed /// ExceptionExtractFn - LLVM objc_exception_extract function. 534193326Sed llvm::Constant *getExceptionExtractFn() { 535193326Sed std::vector<const llvm::Type*> Params; 536193326Sed Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); 537193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 538193326Sed Params, false), 539193326Sed "objc_exception_extract"); 540198092Srdivacky 541193326Sed } 542198092Srdivacky 543193326Sed /// ExceptionMatchFn - LLVM objc_exception_match function. 544193326Sed llvm::Constant *getExceptionMatchFn() { 545193326Sed std::vector<const llvm::Type*> Params; 546193326Sed Params.push_back(ClassPtrTy); 547193326Sed Params.push_back(ObjectPtrTy); 548198092Srdivacky return CGM.CreateRuntimeFunction( 549198092Srdivacky llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), 550198092Srdivacky Params, false), 551198092Srdivacky "objc_exception_match"); 552198092Srdivacky 553193326Sed } 554198092Srdivacky 555193326Sed /// SetJmpFn - LLVM _setjmp function. 556193326Sed llvm::Constant *getSetJmpFn() { 557193326Sed std::vector<const llvm::Type*> Params; 558198092Srdivacky Params.push_back(llvm::Type::getInt32PtrTy(VMContext)); 559193326Sed return 560198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), 561193326Sed Params, false), 562193326Sed "_setjmp"); 563198092Srdivacky 564193326Sed } 565198092Srdivacky 566193326Sedpublic: 567193326Sed ObjCTypesHelper(CodeGen::CodeGenModule &cgm); 568193326Sed ~ObjCTypesHelper() {} 569193326Sed}; 570193326Sed 571193326Sed/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's 572193326Sed/// modern abi 573193326Sedclass ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper { 574193326Sedpublic: 575198092Srdivacky 576193326Sed // MethodListnfABITy - LLVM for struct _method_list_t 577193326Sed const llvm::StructType *MethodListnfABITy; 578198092Srdivacky 579193326Sed // MethodListnfABIPtrTy - LLVM for struct _method_list_t* 580193326Sed const llvm::Type *MethodListnfABIPtrTy; 581198092Srdivacky 582193326Sed // ProtocolnfABITy = LLVM for struct _protocol_t 583193326Sed const llvm::StructType *ProtocolnfABITy; 584198092Srdivacky 585193326Sed // ProtocolnfABIPtrTy = LLVM for struct _protocol_t* 586193326Sed const llvm::Type *ProtocolnfABIPtrTy; 587193326Sed 588193326Sed // ProtocolListnfABITy - LLVM for struct _objc_protocol_list 589193326Sed const llvm::StructType *ProtocolListnfABITy; 590198092Srdivacky 591193326Sed // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list* 592193326Sed const llvm::Type *ProtocolListnfABIPtrTy; 593198092Srdivacky 594193326Sed // ClassnfABITy - LLVM for struct _class_t 595193326Sed const llvm::StructType *ClassnfABITy; 596198092Srdivacky 597193326Sed // ClassnfABIPtrTy - LLVM for struct _class_t* 598193326Sed const llvm::Type *ClassnfABIPtrTy; 599198092Srdivacky 600193326Sed // IvarnfABITy - LLVM for struct _ivar_t 601193326Sed const llvm::StructType *IvarnfABITy; 602198092Srdivacky 603193326Sed // IvarListnfABITy - LLVM for struct _ivar_list_t 604193326Sed const llvm::StructType *IvarListnfABITy; 605198092Srdivacky 606193326Sed // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t* 607193326Sed const llvm::Type *IvarListnfABIPtrTy; 608198092Srdivacky 609193326Sed // ClassRonfABITy - LLVM for struct _class_ro_t 610193326Sed const llvm::StructType *ClassRonfABITy; 611198092Srdivacky 612193326Sed // ImpnfABITy - LLVM for id (*)(id, SEL, ...) 613193326Sed const llvm::Type *ImpnfABITy; 614198092Srdivacky 615193326Sed // CategorynfABITy - LLVM for struct _category_t 616193326Sed const llvm::StructType *CategorynfABITy; 617198092Srdivacky 618193326Sed // New types for nonfragile abi messaging. 619198092Srdivacky 620193326Sed // MessageRefTy - LLVM for: 621193326Sed // struct _message_ref_t { 622193326Sed // IMP messenger; 623193326Sed // SEL name; 624193326Sed // }; 625193326Sed const llvm::StructType *MessageRefTy; 626193326Sed // MessageRefCTy - clang type for struct _message_ref_t 627193326Sed QualType MessageRefCTy; 628198092Srdivacky 629193326Sed // MessageRefPtrTy - LLVM for struct _message_ref_t* 630193326Sed const llvm::Type *MessageRefPtrTy; 631193326Sed // MessageRefCPtrTy - clang type for struct _message_ref_t* 632193326Sed QualType MessageRefCPtrTy; 633198092Srdivacky 634193326Sed // MessengerTy - Type of the messenger (shown as IMP above) 635193326Sed const llvm::FunctionType *MessengerTy; 636198092Srdivacky 637193326Sed // SuperMessageRefTy - LLVM for: 638193326Sed // struct _super_message_ref_t { 639193326Sed // SUPER_IMP messenger; 640193326Sed // SEL name; 641193326Sed // }; 642193326Sed const llvm::StructType *SuperMessageRefTy; 643198092Srdivacky 644193326Sed // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* 645193326Sed const llvm::Type *SuperMessageRefPtrTy; 646193326Sed 647193326Sed llvm::Constant *getMessageSendFixupFn() { 648193326Sed // id objc_msgSend_fixup(id, struct message_ref_t*, ...) 649193326Sed std::vector<const llvm::Type*> Params; 650193326Sed Params.push_back(ObjectPtrTy); 651193326Sed Params.push_back(MessageRefPtrTy); 652193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 653193326Sed Params, true), 654193326Sed "objc_msgSend_fixup"); 655193326Sed } 656198092Srdivacky 657193326Sed llvm::Constant *getMessageSendFpretFixupFn() { 658193326Sed // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...) 659193326Sed std::vector<const llvm::Type*> Params; 660193326Sed Params.push_back(ObjectPtrTy); 661193326Sed Params.push_back(MessageRefPtrTy); 662193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 663193326Sed Params, true), 664193326Sed "objc_msgSend_fpret_fixup"); 665193326Sed } 666198092Srdivacky 667193326Sed llvm::Constant *getMessageSendStretFixupFn() { 668193326Sed // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...) 669193326Sed std::vector<const llvm::Type*> Params; 670193326Sed Params.push_back(ObjectPtrTy); 671193326Sed Params.push_back(MessageRefPtrTy); 672193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 673193326Sed Params, true), 674193326Sed "objc_msgSend_stret_fixup"); 675193326Sed } 676198092Srdivacky 677193326Sed llvm::Constant *getMessageSendIdFixupFn() { 678193326Sed // id objc_msgSendId_fixup(id, struct message_ref_t*, ...) 679193326Sed std::vector<const llvm::Type*> Params; 680193326Sed Params.push_back(ObjectPtrTy); 681193326Sed Params.push_back(MessageRefPtrTy); 682193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 683193326Sed Params, true), 684193326Sed "objc_msgSendId_fixup"); 685193326Sed } 686198092Srdivacky 687193326Sed llvm::Constant *getMessageSendIdStretFixupFn() { 688193326Sed // id objc_msgSendId_stret_fixup(id, struct message_ref_t*, ...) 689193326Sed std::vector<const llvm::Type*> Params; 690193326Sed Params.push_back(ObjectPtrTy); 691193326Sed Params.push_back(MessageRefPtrTy); 692193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 693193326Sed Params, true), 694193326Sed "objc_msgSendId_stret_fixup"); 695193326Sed } 696193326Sed llvm::Constant *getMessageSendSuper2FixupFn() { 697198092Srdivacky // id objc_msgSendSuper2_fixup (struct objc_super *, 698193326Sed // struct _super_message_ref_t*, ...) 699193326Sed std::vector<const llvm::Type*> Params; 700193326Sed Params.push_back(SuperPtrTy); 701193326Sed Params.push_back(SuperMessageRefPtrTy); 702193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 703193326Sed Params, true), 704193326Sed "objc_msgSendSuper2_fixup"); 705193326Sed } 706198092Srdivacky 707193326Sed llvm::Constant *getMessageSendSuper2StretFixupFn() { 708198092Srdivacky // id objc_msgSendSuper2_stret_fixup(struct objc_super *, 709193326Sed // struct _super_message_ref_t*, ...) 710193326Sed std::vector<const llvm::Type*> Params; 711193326Sed Params.push_back(SuperPtrTy); 712193326Sed Params.push_back(SuperMessageRefPtrTy); 713193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 714193326Sed Params, true), 715193326Sed "objc_msgSendSuper2_stret_fixup"); 716193326Sed } 717198092Srdivacky 718198092Srdivacky 719198092Srdivacky 720193326Sed /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C 721193326Sed /// exception personality function. 722193326Sed llvm::Value *getEHPersonalityPtr() { 723198092Srdivacky llvm::Constant *Personality = 724198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), 725193326Sed true), 726198092Srdivacky "__objc_personality_v0"); 727193326Sed return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy); 728193326Sed } 729193326Sed 730193326Sed llvm::Constant *getUnwindResumeOrRethrowFn() { 731193326Sed std::vector<const llvm::Type*> Params; 732193326Sed Params.push_back(Int8PtrTy); 733198092Srdivacky return CGM.CreateRuntimeFunction( 734198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 735198092Srdivacky Params, false), 736198092Srdivacky "_Unwind_Resume_or_Rethrow"); 737193326Sed } 738198092Srdivacky 739193326Sed llvm::Constant *getObjCEndCatchFn() { 740198092Srdivacky return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 741195341Sed false), 742193326Sed "objc_end_catch"); 743198092Srdivacky 744193326Sed } 745198092Srdivacky 746193326Sed llvm::Constant *getObjCBeginCatchFn() { 747193326Sed std::vector<const llvm::Type*> Params; 748193326Sed Params.push_back(Int8PtrTy); 749193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy, 750193326Sed Params, false), 751193326Sed "objc_begin_catch"); 752193326Sed } 753193326Sed 754193326Sed const llvm::StructType *EHTypeTy; 755193326Sed const llvm::Type *EHTypePtrTy; 756193326Sed 757193326Sed ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm); 758193326Sed ~ObjCNonFragileABITypesHelper(){} 759193326Sed}; 760198092Srdivacky 761193326Sedclass CGObjCCommonMac : public CodeGen::CGObjCRuntime { 762193326Sedpublic: 763193326Sed // FIXME - accessibility 764193326Sed class GC_IVAR { 765193326Sed public: 766193326Sed unsigned ivar_bytepos; 767193326Sed unsigned ivar_size; 768193326Sed GC_IVAR(unsigned bytepos = 0, unsigned size = 0) 769198092Srdivacky : ivar_bytepos(bytepos), ivar_size(size) {} 770193326Sed 771193326Sed // Allow sorting based on byte pos. 772193326Sed bool operator<(const GC_IVAR &b) const { 773193326Sed return ivar_bytepos < b.ivar_bytepos; 774193326Sed } 775193326Sed }; 776198092Srdivacky 777193326Sed class SKIP_SCAN { 778193326Sed public: 779193326Sed unsigned skip; 780193326Sed unsigned scan; 781198092Srdivacky SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0) 782193326Sed : skip(_skip), scan(_scan) {} 783193326Sed }; 784198092Srdivacky 785193326Sedprotected: 786193326Sed CodeGen::CodeGenModule &CGM; 787198092Srdivacky llvm::LLVMContext &VMContext; 788193326Sed // FIXME! May not be needing this after all. 789193326Sed unsigned ObjCABI; 790198092Srdivacky 791193326Sed // gc ivar layout bitmap calculation helper caches. 792193326Sed llvm::SmallVector<GC_IVAR, 16> SkipIvars; 793193326Sed llvm::SmallVector<GC_IVAR, 16> IvarsInfo; 794198092Srdivacky 795193326Sed /// LazySymbols - Symbols to generate a lazy reference for. See 796193326Sed /// DefinedSymbols and FinishModule(). 797198092Srdivacky llvm::SetVector<IdentifierInfo*> LazySymbols; 798198092Srdivacky 799193326Sed /// DefinedSymbols - External symbols which are defined by this 800193326Sed /// module. The symbols in this list and LazySymbols are used to add 801193326Sed /// special linker symbols which ensure that Objective-C modules are 802193326Sed /// linked properly. 803198092Srdivacky llvm::SetVector<IdentifierInfo*> DefinedSymbols; 804198092Srdivacky 805193326Sed /// ClassNames - uniqued class names. 806193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames; 807198092Srdivacky 808193326Sed /// MethodVarNames - uniqued method variable names. 809193326Sed llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames; 810198092Srdivacky 811193326Sed /// MethodVarTypes - uniqued method type signatures. We have to use 812193326Sed /// a StringMap here because have no other unique reference. 813193326Sed llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes; 814198092Srdivacky 815193326Sed /// MethodDefinitions - map of methods which have been defined in 816193326Sed /// this translation unit. 817193326Sed llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions; 818198092Srdivacky 819193326Sed /// PropertyNames - uniqued method variable names. 820193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames; 821198092Srdivacky 822193326Sed /// ClassReferences - uniqued class references. 823193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences; 824198092Srdivacky 825193326Sed /// SelectorReferences - uniqued selector references. 826193326Sed llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences; 827198092Srdivacky 828193326Sed /// Protocols - Protocols for which an objc_protocol structure has 829193326Sed /// been emitted. Forward declarations are handled by creating an 830193326Sed /// empty structure whose initializer is filled in when/if defined. 831193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols; 832198092Srdivacky 833193326Sed /// DefinedProtocols - Protocols which have actually been 834193326Sed /// defined. We should not need this, see FIXME in GenerateProtocol. 835193326Sed llvm::DenseSet<IdentifierInfo*> DefinedProtocols; 836198092Srdivacky 837193326Sed /// DefinedClasses - List of defined classes. 838193326Sed std::vector<llvm::GlobalValue*> DefinedClasses; 839193326Sed 840193326Sed /// DefinedNonLazyClasses - List of defined "non-lazy" classes. 841193326Sed std::vector<llvm::GlobalValue*> DefinedNonLazyClasses; 842198092Srdivacky 843193326Sed /// DefinedCategories - List of defined categories. 844193326Sed std::vector<llvm::GlobalValue*> DefinedCategories; 845198092Srdivacky 846193326Sed /// DefinedNonLazyCategories - List of defined "non-lazy" categories. 847193326Sed std::vector<llvm::GlobalValue*> DefinedNonLazyCategories; 848193326Sed 849193326Sed /// GetNameForMethod - Return a name for the given method. 850193326Sed /// \param[out] NameOut - The return value. 851193326Sed void GetNameForMethod(const ObjCMethodDecl *OMD, 852193326Sed const ObjCContainerDecl *CD, 853198398Srdivacky llvm::SmallVectorImpl<char> &NameOut); 854198092Srdivacky 855193326Sed /// GetMethodVarName - Return a unique constant for the given 856193326Sed /// selector's name. The return value has type char *. 857193326Sed llvm::Constant *GetMethodVarName(Selector Sel); 858193326Sed llvm::Constant *GetMethodVarName(IdentifierInfo *Ident); 859193326Sed llvm::Constant *GetMethodVarName(const std::string &Name); 860198092Srdivacky 861193326Sed /// GetMethodVarType - Return a unique constant for the given 862193326Sed /// selector's name. The return value has type char *. 863198092Srdivacky 864193326Sed // FIXME: This is a horrible name. 865193326Sed llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D); 866193326Sed llvm::Constant *GetMethodVarType(const FieldDecl *D); 867198092Srdivacky 868193326Sed /// GetPropertyName - Return a unique constant for the given 869193326Sed /// name. The return value has type char *. 870193326Sed llvm::Constant *GetPropertyName(IdentifierInfo *Ident); 871198092Srdivacky 872193326Sed // FIXME: This can be dropped once string functions are unified. 873193326Sed llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD, 874193326Sed const Decl *Container); 875198092Srdivacky 876193326Sed /// GetClassName - Return a unique constant for the given selector's 877193326Sed /// name. The return value has type char *. 878193326Sed llvm::Constant *GetClassName(IdentifierInfo *Ident); 879198092Srdivacky 880193326Sed /// BuildIvarLayout - Builds ivar layout bitmap for the class 881193326Sed /// implementation for the __strong or __weak case. 882193326Sed /// 883193326Sed llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI, 884193326Sed bool ForStrongLayout); 885198092Srdivacky 886193326Sed void BuildAggrIvarRecordLayout(const RecordType *RT, 887198092Srdivacky unsigned int BytePos, bool ForStrongLayout, 888198092Srdivacky bool &HasUnion); 889193326Sed void BuildAggrIvarLayout(const ObjCImplementationDecl *OI, 890193326Sed const llvm::StructLayout *Layout, 891193326Sed const RecordDecl *RD, 892193326Sed const llvm::SmallVectorImpl<FieldDecl*> &RecFields, 893193326Sed unsigned int BytePos, bool ForStrongLayout, 894193326Sed bool &HasUnion); 895193326Sed 896193326Sed /// GetIvarLayoutName - Returns a unique constant for the given 897193326Sed /// ivar layout bitmap. 898193326Sed llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident, 899193326Sed const ObjCCommonTypesHelper &ObjCTypes); 900198092Srdivacky 901193326Sed /// EmitPropertyList - Emit the given property list. The return 902193326Sed /// value has type PropertyListPtrTy. 903198398Srdivacky llvm::Constant *EmitPropertyList(llvm::Twine Name, 904198092Srdivacky const Decl *Container, 905193326Sed const ObjCContainerDecl *OCD, 906193326Sed const ObjCCommonTypesHelper &ObjCTypes); 907198092Srdivacky 908193326Sed /// GetProtocolRef - Return a reference to the internal protocol 909193326Sed /// description, creating an empty one if it has not been 910193326Sed /// defined. The return value has type ProtocolPtrTy. 911193326Sed llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD); 912193326Sed 913193326Sed /// CreateMetadataVar - Create a global variable with internal 914193326Sed /// linkage for use by the Objective-C runtime. 915193326Sed /// 916193326Sed /// This is a convenience wrapper which not only creates the 917193326Sed /// variable, but also sets the section and alignment and adds the 918198092Srdivacky /// global to the "llvm.used" list. 919193326Sed /// 920193326Sed /// \param Name - The variable name. 921193326Sed /// \param Init - The variable initializer; this is also used to 922193326Sed /// define the type of the variable. 923193326Sed /// \param Section - The section the variable should go into, or 0. 924193326Sed /// \param Align - The alignment for the variable, or 0. 925193326Sed /// \param AddToUsed - Whether the variable should be added to 926193326Sed /// "llvm.used". 927198398Srdivacky llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name, 928193326Sed llvm::Constant *Init, 929193326Sed const char *Section, 930193326Sed unsigned Align, 931193326Sed bool AddToUsed); 932193326Sed 933193326Sed CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, 934193326Sed QualType ResultType, 935193326Sed llvm::Value *Sel, 936193326Sed llvm::Value *Arg0, 937193326Sed QualType Arg0Ty, 938193326Sed bool IsSuper, 939193326Sed const CallArgList &CallArgs, 940198092Srdivacky const ObjCMethodDecl *OMD, 941193326Sed const ObjCCommonTypesHelper &ObjCTypes); 942193326Sed 943198092Srdivackypublic: 944198092Srdivacky CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : 945198092Srdivacky CGM(cgm), VMContext(cgm.getLLVMContext()) { } 946195099Sed 947193326Sed virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *SL); 948198092Srdivacky 949193326Sed virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, 950193326Sed const ObjCContainerDecl *CD=0); 951198092Srdivacky 952193326Sed virtual void GenerateProtocol(const ObjCProtocolDecl *PD); 953198092Srdivacky 954193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 955193326Sed /// declaration, emitting it if necessary. The return value has type 956193326Sed /// ProtocolPtrTy. 957193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0; 958198092Srdivacky 959193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 960193326Sed /// object for the given declaration, emitting it if needed. These 961193326Sed /// forward references will be filled in with empty bodies if no 962193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 963193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0; 964193326Sed}; 965198092Srdivacky 966193326Sedclass CGObjCMac : public CGObjCCommonMac { 967193326Sedprivate: 968193326Sed ObjCTypesHelper ObjCTypes; 969193326Sed /// EmitImageInfo - Emit the image info marker used to encode some module 970193326Sed /// level information. 971193326Sed void EmitImageInfo(); 972193326Sed 973193326Sed /// EmitModuleInfo - Another marker encoding module level 974198092Srdivacky /// information. 975193326Sed void EmitModuleInfo(); 976193326Sed 977193326Sed /// EmitModuleSymols - Emit module symbols, the list of defined 978193326Sed /// classes and categories. The result has type SymtabPtrTy. 979193326Sed llvm::Constant *EmitModuleSymbols(); 980193326Sed 981193326Sed /// FinishModule - Write out global data structures at the end of 982193326Sed /// processing a translation unit. 983193326Sed void FinishModule(); 984193326Sed 985193326Sed /// EmitClassExtension - Generate the class extension structure used 986193326Sed /// to store the weak ivar layout and properties. The return value 987193326Sed /// has type ClassExtensionPtrTy. 988193326Sed llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID); 989193326Sed 990193326Sed /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 991193326Sed /// for the given class. 992198092Srdivacky llvm::Value *EmitClassRef(CGBuilderTy &Builder, 993193326Sed const ObjCInterfaceDecl *ID); 994199482Srdivacky 995199482Srdivacky /// EmitSuperClassRef - Emits reference to class's main metadata class. 996199482Srdivacky llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID); 997193326Sed 998193326Sed CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, 999193326Sed QualType ResultType, 1000193326Sed Selector Sel, 1001193326Sed llvm::Value *Arg0, 1002193326Sed QualType Arg0Ty, 1003193326Sed bool IsSuper, 1004193326Sed const CallArgList &CallArgs); 1005193326Sed 1006193326Sed /// EmitIvarList - Emit the ivar list for the given 1007193326Sed /// implementation. If ForClass is true the list of class ivars 1008193326Sed /// (i.e. metaclass ivars) is emitted, otherwise the list of 1009193326Sed /// interface ivars will be emitted. The return value has type 1010193326Sed /// IvarListPtrTy. 1011193326Sed llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID, 1012193326Sed bool ForClass); 1013198092Srdivacky 1014193326Sed /// EmitMetaClass - Emit a forward reference to the class structure 1015193326Sed /// for the metaclass of the given interface. The return value has 1016193326Sed /// type ClassPtrTy. 1017193326Sed llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID); 1018193326Sed 1019193326Sed /// EmitMetaClass - Emit a class structure for the metaclass of the 1020193326Sed /// given implementation. The return value has type ClassPtrTy. 1021193326Sed llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID, 1022193326Sed llvm::Constant *Protocols, 1023193326Sed const ConstantVector &Methods); 1024198092Srdivacky 1025193326Sed llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); 1026198092Srdivacky 1027193326Sed llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD); 1028193326Sed 1029193326Sed /// EmitMethodList - Emit the method list for the given 1030193326Sed /// implementation. The return value has type MethodListPtrTy. 1031198398Srdivacky llvm::Constant *EmitMethodList(llvm::Twine Name, 1032193326Sed const char *Section, 1033193326Sed const ConstantVector &Methods); 1034193326Sed 1035193326Sed /// EmitMethodDescList - Emit a method description list for a list of 1036198092Srdivacky /// method declarations. 1037193326Sed /// - TypeName: The name for the type containing the methods. 1038193326Sed /// - IsProtocol: True iff these methods are for a protocol. 1039193326Sed /// - ClassMethds: True iff these are class methods. 1040193326Sed /// - Required: When true, only "required" methods are 1041193326Sed /// listed. Similarly, when false only "optional" methods are 1042193326Sed /// listed. For classes this should always be true. 1043193326Sed /// - begin, end: The method list to output. 1044193326Sed /// 1045193326Sed /// The return value has type MethodDescriptionListPtrTy. 1046198398Srdivacky llvm::Constant *EmitMethodDescList(llvm::Twine Name, 1047193326Sed const char *Section, 1048193326Sed const ConstantVector &Methods); 1049193326Sed 1050193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1051193326Sed /// declaration, emitting it if necessary. The return value has type 1052193326Sed /// ProtocolPtrTy. 1053193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD); 1054193326Sed 1055193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1056193326Sed /// object for the given declaration, emitting it if needed. These 1057193326Sed /// forward references will be filled in with empty bodies if no 1058193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1059193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD); 1060193326Sed 1061193326Sed /// EmitProtocolExtension - Generate the protocol extension 1062193326Sed /// structure used to store optional instance and class methods, and 1063193326Sed /// protocol properties. The return value has type 1064193326Sed /// ProtocolExtensionPtrTy. 1065193326Sed llvm::Constant * 1066193326Sed EmitProtocolExtension(const ObjCProtocolDecl *PD, 1067193326Sed const ConstantVector &OptInstanceMethods, 1068193326Sed const ConstantVector &OptClassMethods); 1069193326Sed 1070193326Sed /// EmitProtocolList - Generate the list of referenced 1071193326Sed /// protocols. The return value has type ProtocolListPtrTy. 1072198398Srdivacky llvm::Constant *EmitProtocolList(llvm::Twine Name, 1073193326Sed ObjCProtocolDecl::protocol_iterator begin, 1074193326Sed ObjCProtocolDecl::protocol_iterator end); 1075193326Sed 1076193326Sed /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, 1077193326Sed /// for the given selector. 1078193326Sed llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel); 1079198092Srdivacky 1080198092Srdivackypublic: 1081193326Sed CGObjCMac(CodeGen::CodeGenModule &cgm); 1082193326Sed 1083193326Sed virtual llvm::Function *ModuleInitFunction(); 1084198092Srdivacky 1085193326Sed virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1086193326Sed QualType ResultType, 1087193326Sed Selector Sel, 1088193326Sed llvm::Value *Receiver, 1089193326Sed bool IsClassMessage, 1090193326Sed const CallArgList &CallArgs, 1091193326Sed const ObjCMethodDecl *Method); 1092193326Sed 1093198092Srdivacky virtual CodeGen::RValue 1094193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1095193326Sed QualType ResultType, 1096193326Sed Selector Sel, 1097193326Sed const ObjCInterfaceDecl *Class, 1098193326Sed bool isCategoryImpl, 1099193326Sed llvm::Value *Receiver, 1100193326Sed bool IsClassMessage, 1101198092Srdivacky const CallArgList &CallArgs, 1102198092Srdivacky const ObjCMethodDecl *Method); 1103198092Srdivacky 1104193326Sed virtual llvm::Value *GetClass(CGBuilderTy &Builder, 1105193326Sed const ObjCInterfaceDecl *ID); 1106193326Sed 1107193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel); 1108193326Sed 1109193326Sed /// The NeXT/Apple runtimes do not support typed selectors; just emit an 1110193326Sed /// untyped one. 1111193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, 1112193326Sed const ObjCMethodDecl *Method); 1113193326Sed 1114193326Sed virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); 1115193326Sed 1116193326Sed virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); 1117193326Sed 1118193326Sed virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, 1119193326Sed const ObjCProtocolDecl *PD); 1120198092Srdivacky 1121193326Sed virtual llvm::Constant *GetPropertyGetFunction(); 1122193326Sed virtual llvm::Constant *GetPropertySetFunction(); 1123193326Sed virtual llvm::Constant *EnumerationMutationFunction(); 1124198092Srdivacky 1125193326Sed virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1126193326Sed const Stmt &S); 1127193326Sed virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 1128193326Sed const ObjCAtThrowStmt &S); 1129193326Sed virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1130198092Srdivacky llvm::Value *AddrWeakObj); 1131193326Sed virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1132198092Srdivacky llvm::Value *src, llvm::Value *dst); 1133193326Sed virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1134193326Sed llvm::Value *src, llvm::Value *dest); 1135193326Sed virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 1136198092Srdivacky llvm::Value *src, llvm::Value *dest, 1137198092Srdivacky llvm::Value *ivarOffset); 1138193326Sed virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 1139193326Sed llvm::Value *src, llvm::Value *dest); 1140198092Srdivacky virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 1141198092Srdivacky llvm::Value *dest, llvm::Value *src, 1142198092Srdivacky QualType Ty); 1143198092Srdivacky 1144193326Sed virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 1145193326Sed QualType ObjectTy, 1146193326Sed llvm::Value *BaseValue, 1147193326Sed const ObjCIvarDecl *Ivar, 1148193326Sed unsigned CVRQualifiers); 1149193326Sed virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 1150193326Sed const ObjCInterfaceDecl *Interface, 1151193326Sed const ObjCIvarDecl *Ivar); 1152193326Sed}; 1153198092Srdivacky 1154193326Sedclass CGObjCNonFragileABIMac : public CGObjCCommonMac { 1155193326Sedprivate: 1156193326Sed ObjCNonFragileABITypesHelper ObjCTypes; 1157193326Sed llvm::GlobalVariable* ObjCEmptyCacheVar; 1158193326Sed llvm::GlobalVariable* ObjCEmptyVtableVar; 1159198092Srdivacky 1160193326Sed /// SuperClassReferences - uniqued super class references. 1161193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences; 1162198092Srdivacky 1163193326Sed /// MetaClassReferences - uniqued meta class references. 1164193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences; 1165193326Sed 1166193326Sed /// EHTypeReferences - uniqued class ehtype references. 1167193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences; 1168198092Srdivacky 1169193326Sed /// NonLegacyDispatchMethods - List of methods for which we do *not* generate 1170193326Sed /// legacy messaging dispatch. 1171193326Sed llvm::DenseSet<Selector> NonLegacyDispatchMethods; 1172198092Srdivacky 1173199482Srdivacky /// DefinedMetaClasses - List of defined meta-classes. 1174199482Srdivacky std::vector<llvm::GlobalValue*> DefinedMetaClasses; 1175199482Srdivacky 1176193326Sed /// LegacyDispatchedSelector - Returns true if SEL is not in the list of 1177193326Sed /// NonLegacyDispatchMethods; false otherwise. 1178193326Sed bool LegacyDispatchedSelector(Selector Sel); 1179198092Srdivacky 1180193326Sed /// FinishNonFragileABIModule - Write out global data structures at the end of 1181193326Sed /// processing a translation unit. 1182193326Sed void FinishNonFragileABIModule(); 1183193326Sed 1184193326Sed /// AddModuleClassList - Add the given list of class pointers to the 1185193326Sed /// module with the provided symbol and section names. 1186193326Sed void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container, 1187193326Sed const char *SymbolName, 1188193326Sed const char *SectionName); 1189193326Sed 1190198092Srdivacky llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags, 1191198092Srdivacky unsigned InstanceStart, 1192198092Srdivacky unsigned InstanceSize, 1193198092Srdivacky const ObjCImplementationDecl *ID); 1194193326Sed llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName, 1195198092Srdivacky llvm::Constant *IsAGV, 1196193326Sed llvm::Constant *SuperClassGV, 1197193326Sed llvm::Constant *ClassRoGV, 1198193326Sed bool HiddenVisibility); 1199198092Srdivacky 1200193326Sed llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); 1201198092Srdivacky 1202193326Sed llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD); 1203198092Srdivacky 1204193326Sed /// EmitMethodList - Emit the method list for the given 1205193326Sed /// implementation. The return value has type MethodListnfABITy. 1206198398Srdivacky llvm::Constant *EmitMethodList(llvm::Twine Name, 1207193326Sed const char *Section, 1208193326Sed const ConstantVector &Methods); 1209193326Sed /// EmitIvarList - Emit the ivar list for the given 1210193326Sed /// implementation. If ForClass is true the list of class ivars 1211193326Sed /// (i.e. metaclass ivars) is emitted, otherwise the list of 1212193326Sed /// interface ivars will be emitted. The return value has type 1213193326Sed /// IvarListnfABIPtrTy. 1214193326Sed llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID); 1215198092Srdivacky 1216193326Sed llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, 1217193326Sed const ObjCIvarDecl *Ivar, 1218193326Sed unsigned long int offset); 1219198092Srdivacky 1220193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1221193326Sed /// declaration, emitting it if necessary. The return value has type 1222193326Sed /// ProtocolPtrTy. 1223193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD); 1224198092Srdivacky 1225193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1226193326Sed /// object for the given declaration, emitting it if needed. These 1227193326Sed /// forward references will be filled in with empty bodies if no 1228193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1229193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD); 1230198092Srdivacky 1231193326Sed /// EmitProtocolList - Generate the list of referenced 1232193326Sed /// protocols. The return value has type ProtocolListPtrTy. 1233198398Srdivacky llvm::Constant *EmitProtocolList(llvm::Twine Name, 1234193326Sed ObjCProtocolDecl::protocol_iterator begin, 1235193326Sed ObjCProtocolDecl::protocol_iterator end); 1236198092Srdivacky 1237193326Sed CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, 1238193326Sed QualType ResultType, 1239193326Sed Selector Sel, 1240193326Sed llvm::Value *Receiver, 1241193326Sed QualType Arg0Ty, 1242193326Sed bool IsSuper, 1243193326Sed const CallArgList &CallArgs); 1244193326Sed 1245193326Sed /// GetClassGlobal - Return the global variable for the Objective-C 1246193326Sed /// class of the given name. 1247193326Sed llvm::GlobalVariable *GetClassGlobal(const std::string &Name); 1248198092Srdivacky 1249193326Sed /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1250193326Sed /// for the given class reference. 1251198092Srdivacky llvm::Value *EmitClassRef(CGBuilderTy &Builder, 1252193326Sed const ObjCInterfaceDecl *ID); 1253198092Srdivacky 1254193326Sed /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1255193326Sed /// for the given super class reference. 1256198092Srdivacky llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder, 1257198092Srdivacky const ObjCInterfaceDecl *ID); 1258198092Srdivacky 1259193326Sed /// EmitMetaClassRef - Return a Value * of the address of _class_t 1260193326Sed /// meta-data 1261198092Srdivacky llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder, 1262193326Sed const ObjCInterfaceDecl *ID); 1263193326Sed 1264193326Sed /// ObjCIvarOffsetVariable - Returns the ivar offset variable for 1265193326Sed /// the given ivar. 1266193326Sed /// 1267193326Sed llvm::GlobalVariable * ObjCIvarOffsetVariable( 1268198092Srdivacky const ObjCInterfaceDecl *ID, 1269198092Srdivacky const ObjCIvarDecl *Ivar); 1270198092Srdivacky 1271193326Sed /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, 1272193326Sed /// for the given selector. 1273193326Sed llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel); 1274193326Sed 1275193326Sed /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C 1276193326Sed /// interface. The return value has type EHTypePtrTy. 1277193326Sed llvm::Value *GetInterfaceEHType(const ObjCInterfaceDecl *ID, 1278193326Sed bool ForDefinition); 1279193326Sed 1280198092Srdivacky const char *getMetaclassSymbolPrefix() const { 1281193326Sed return "OBJC_METACLASS_$_"; 1282193326Sed } 1283198092Srdivacky 1284193326Sed const char *getClassSymbolPrefix() const { 1285193326Sed return "OBJC_CLASS_$_"; 1286193326Sed } 1287193326Sed 1288193326Sed void GetClassSizeInfo(const ObjCImplementationDecl *OID, 1289193326Sed uint32_t &InstanceStart, 1290193326Sed uint32_t &InstanceSize); 1291198092Srdivacky 1292193326Sed // Shamelessly stolen from Analysis/CFRefCount.cpp 1293193326Sed Selector GetNullarySelector(const char* name) const { 1294193326Sed IdentifierInfo* II = &CGM.getContext().Idents.get(name); 1295193326Sed return CGM.getContext().Selectors.getSelector(0, &II); 1296193326Sed } 1297198092Srdivacky 1298193326Sed Selector GetUnarySelector(const char* name) const { 1299193326Sed IdentifierInfo* II = &CGM.getContext().Idents.get(name); 1300193326Sed return CGM.getContext().Selectors.getSelector(1, &II); 1301193326Sed } 1302193326Sed 1303193326Sed /// ImplementationIsNonLazy - Check whether the given category or 1304193326Sed /// class implementation is "non-lazy". 1305193326Sed bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const; 1306193326Sed 1307193326Sedpublic: 1308193326Sed CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); 1309193326Sed // FIXME. All stubs for now! 1310193326Sed virtual llvm::Function *ModuleInitFunction(); 1311198092Srdivacky 1312193326Sed virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1313193326Sed QualType ResultType, 1314193326Sed Selector Sel, 1315193326Sed llvm::Value *Receiver, 1316193326Sed bool IsClassMessage, 1317193326Sed const CallArgList &CallArgs, 1318193326Sed const ObjCMethodDecl *Method); 1319198092Srdivacky 1320198092Srdivacky virtual CodeGen::RValue 1321193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1322193326Sed QualType ResultType, 1323193326Sed Selector Sel, 1324193326Sed const ObjCInterfaceDecl *Class, 1325193326Sed bool isCategoryImpl, 1326193326Sed llvm::Value *Receiver, 1327193326Sed bool IsClassMessage, 1328198092Srdivacky const CallArgList &CallArgs, 1329198092Srdivacky const ObjCMethodDecl *Method); 1330198092Srdivacky 1331193326Sed virtual llvm::Value *GetClass(CGBuilderTy &Builder, 1332193326Sed const ObjCInterfaceDecl *ID); 1333198092Srdivacky 1334193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel) 1335193326Sed { return EmitSelector(Builder, Sel); } 1336193326Sed 1337193326Sed /// The NeXT/Apple runtimes do not support typed selectors; just emit an 1338193326Sed /// untyped one. 1339193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, 1340193326Sed const ObjCMethodDecl *Method) 1341193326Sed { return EmitSelector(Builder, Method->getSelector()); } 1342198092Srdivacky 1343193326Sed virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); 1344198092Srdivacky 1345193326Sed virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); 1346193326Sed virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, 1347193326Sed const ObjCProtocolDecl *PD); 1348198092Srdivacky 1349198092Srdivacky virtual llvm::Constant *GetPropertyGetFunction() { 1350193326Sed return ObjCTypes.getGetPropertyFn(); 1351193326Sed } 1352198092Srdivacky virtual llvm::Constant *GetPropertySetFunction() { 1353198092Srdivacky return ObjCTypes.getSetPropertyFn(); 1354193326Sed } 1355193326Sed virtual llvm::Constant *EnumerationMutationFunction() { 1356193326Sed return ObjCTypes.getEnumerationMutationFn(); 1357193326Sed } 1358198092Srdivacky 1359193326Sed virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1360193326Sed const Stmt &S); 1361193326Sed virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 1362193326Sed const ObjCAtThrowStmt &S); 1363193326Sed virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1364193326Sed llvm::Value *AddrWeakObj); 1365193326Sed virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1366193326Sed llvm::Value *src, llvm::Value *dst); 1367193326Sed virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1368193326Sed llvm::Value *src, llvm::Value *dest); 1369193326Sed virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 1370198092Srdivacky llvm::Value *src, llvm::Value *dest, 1371198092Srdivacky llvm::Value *ivarOffset); 1372193326Sed virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 1373193326Sed llvm::Value *src, llvm::Value *dest); 1374198092Srdivacky virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 1375198092Srdivacky llvm::Value *dest, llvm::Value *src, 1376198092Srdivacky QualType Ty); 1377193326Sed virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 1378193326Sed QualType ObjectTy, 1379193326Sed llvm::Value *BaseValue, 1380193326Sed const ObjCIvarDecl *Ivar, 1381193326Sed unsigned CVRQualifiers); 1382193326Sed virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 1383193326Sed const ObjCInterfaceDecl *Interface, 1384193326Sed const ObjCIvarDecl *Ivar); 1385193326Sed}; 1386198092Srdivacky 1387193326Sed} // end anonymous namespace 1388193326Sed 1389193326Sed/* *** Helper Functions *** */ 1390193326Sed 1391193326Sed/// getConstantGEP() - Help routine to construct simple GEPs. 1392198092Srdivackystatic llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext, 1393198092Srdivacky llvm::Constant *C, 1394193326Sed unsigned idx0, 1395193326Sed unsigned idx1) { 1396193326Sed llvm::Value *Idxs[] = { 1397198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0), 1398198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1) 1399193326Sed }; 1400193326Sed return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2); 1401193326Sed} 1402193326Sed 1403193326Sed/// hasObjCExceptionAttribute - Return true if this class or any super 1404193326Sed/// class has the __objc_exception__ attribute. 1405198092Srdivackystatic bool hasObjCExceptionAttribute(ASTContext &Context, 1406194613Sed const ObjCInterfaceDecl *OID) { 1407195341Sed if (OID->hasAttr<ObjCExceptionAttr>()) 1408193326Sed return true; 1409193326Sed if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 1410194613Sed return hasObjCExceptionAttribute(Context, Super); 1411193326Sed return false; 1412193326Sed} 1413193326Sed 1414193326Sed/* *** CGObjCMac Public Interface *** */ 1415198092Srdivacky 1416193326SedCGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), 1417198092Srdivacky ObjCTypes(cgm) { 1418193326Sed ObjCABI = 1; 1419198092Srdivacky EmitImageInfo(); 1420193326Sed} 1421193326Sed 1422193326Sed/// GetClass - Return a reference to the class for the given interface 1423193326Sed/// decl. 1424193326Sedllvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder, 1425193326Sed const ObjCInterfaceDecl *ID) { 1426193326Sed return EmitClassRef(Builder, ID); 1427193326Sed} 1428193326Sed 1429193326Sed/// GetSelector - Return the pointer to the unique'd string for this selector. 1430193326Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) { 1431193326Sed return EmitSelector(Builder, Sel); 1432193326Sed} 1433193326Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl 1434198092Srdivacky *Method) { 1435193326Sed return EmitSelector(Builder, Method->getSelector()); 1436193326Sed} 1437193326Sed 1438193326Sed/// Generate a constant CFString object. 1439198092Srdivacky/* 1440198092Srdivacky struct __builtin_CFString { 1441198092Srdivacky const int *isa; // point to __CFConstantStringClassReference 1442198092Srdivacky int flags; 1443198092Srdivacky const char *str; 1444198092Srdivacky long length; 1445198092Srdivacky }; 1446193326Sed*/ 1447193326Sed 1448193326Sedllvm::Constant *CGObjCCommonMac::GenerateConstantString( 1449193326Sed const ObjCStringLiteral *SL) { 1450193326Sed return CGM.GetAddrOfConstantCFString(SL->getString()); 1451193326Sed} 1452193326Sed 1453193326Sed/// Generates a message send where the super is the receiver. This is 1454193326Sed/// a message send to self with special delivery semantics indicating 1455193326Sed/// which class's method should be called. 1456193326SedCodeGen::RValue 1457193326SedCGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1458193326Sed QualType ResultType, 1459193326Sed Selector Sel, 1460193326Sed const ObjCInterfaceDecl *Class, 1461193326Sed bool isCategoryImpl, 1462193326Sed llvm::Value *Receiver, 1463193326Sed bool IsClassMessage, 1464198092Srdivacky const CodeGen::CallArgList &CallArgs, 1465198092Srdivacky const ObjCMethodDecl *Method) { 1466193326Sed // Create and init a super structure; this is a (receiver, class) 1467193326Sed // pair we will pass to objc_msgSendSuper. 1468198092Srdivacky llvm::Value *ObjCSuper = 1469193326Sed CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); 1470198092Srdivacky llvm::Value *ReceiverAsObject = 1471193326Sed CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); 1472198092Srdivacky CGF.Builder.CreateStore(ReceiverAsObject, 1473193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 1474193326Sed 1475193326Sed // If this is a class message the metaclass is passed as the target. 1476193326Sed llvm::Value *Target; 1477193326Sed if (IsClassMessage) { 1478193326Sed if (isCategoryImpl) { 1479193326Sed // Message sent to 'super' in a class method defined in a category 1480193326Sed // implementation requires an odd treatment. 1481193326Sed // If we are in a class method, we must retrieve the 1482193326Sed // _metaclass_ for the current class, pointed at by 1483193326Sed // the class's "isa" pointer. The following assumes that 1484193326Sed // isa" is the first ivar in a class (which it must be). 1485193326Sed Target = EmitClassRef(CGF.Builder, Class->getSuperClass()); 1486193326Sed Target = CGF.Builder.CreateStructGEP(Target, 0); 1487193326Sed Target = CGF.Builder.CreateLoad(Target); 1488198092Srdivacky } else { 1489193326Sed llvm::Value *MetaClassPtr = EmitMetaClassRef(Class); 1490193326Sed llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1); 1491193326Sed llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr); 1492193326Sed Target = Super; 1493198092Srdivacky } 1494199482Srdivacky } 1495199482Srdivacky else if (isCategoryImpl) 1496193326Sed Target = EmitClassRef(CGF.Builder, Class->getSuperClass()); 1497199482Srdivacky else { 1498199482Srdivacky llvm::Value *ClassPtr = EmitSuperClassRef(Class); 1499199482Srdivacky ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1); 1500199482Srdivacky Target = CGF.Builder.CreateLoad(ClassPtr); 1501193326Sed } 1502193326Sed // FIXME: We shouldn't need to do this cast, rectify the ASTContext and 1503193326Sed // ObjCTypes types. 1504198092Srdivacky const llvm::Type *ClassTy = 1505193326Sed CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); 1506193326Sed Target = CGF.Builder.CreateBitCast(Target, ClassTy); 1507198092Srdivacky CGF.Builder.CreateStore(Target, 1508193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 1509198092Srdivacky return EmitLegacyMessageSend(CGF, ResultType, 1510193326Sed EmitSelector(CGF.Builder, Sel), 1511193326Sed ObjCSuper, ObjCTypes.SuperPtrCTy, 1512198092Srdivacky true, CallArgs, Method, ObjCTypes); 1513193326Sed} 1514198092Srdivacky 1515198092Srdivacky/// Generate code for a message send expression. 1516193326SedCodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1517193326Sed QualType ResultType, 1518193326Sed Selector Sel, 1519193326Sed llvm::Value *Receiver, 1520193326Sed bool IsClassMessage, 1521193326Sed const CallArgList &CallArgs, 1522193326Sed const ObjCMethodDecl *Method) { 1523193326Sed return EmitLegacyMessageSend(CGF, ResultType, 1524193326Sed EmitSelector(CGF.Builder, Sel), 1525193326Sed Receiver, CGF.getContext().getObjCIdType(), 1526198092Srdivacky false, CallArgs, Method, ObjCTypes); 1527193326Sed} 1528193326Sed 1529198092SrdivackyCodeGen::RValue 1530198092SrdivackyCGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, 1531198092Srdivacky QualType ResultType, 1532198092Srdivacky llvm::Value *Sel, 1533198092Srdivacky llvm::Value *Arg0, 1534198092Srdivacky QualType Arg0Ty, 1535198092Srdivacky bool IsSuper, 1536198092Srdivacky const CallArgList &CallArgs, 1537198092Srdivacky const ObjCMethodDecl *Method, 1538198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 1539193326Sed CallArgList ActualArgs; 1540193326Sed if (!IsSuper) 1541193326Sed Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp"); 1542193326Sed ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty)); 1543193326Sed ActualArgs.push_back(std::make_pair(RValue::get(Sel), 1544193326Sed CGF.getContext().getObjCSelType())); 1545193326Sed ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); 1546198092Srdivacky 1547193326Sed CodeGenTypes &Types = CGM.getTypes(); 1548193326Sed const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs); 1549198092Srdivacky const llvm::FunctionType *FTy = 1550198092Srdivacky Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); 1551198092Srdivacky 1552193326Sed llvm::Constant *Fn = NULL; 1553193326Sed if (CGM.ReturnTypeUsesSret(FnInfo)) { 1554193326Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) 1555198092Srdivacky : ObjCTypes.getSendStretFn(IsSuper); 1556193326Sed } else if (ResultType->isFloatingType()) { 1557193326Sed if (ObjCABI == 2) { 1558198092Srdivacky if (const BuiltinType *BT = ResultType->getAs<BuiltinType>()) { 1559193326Sed BuiltinType::Kind k = BT->getKind(); 1560193326Sed Fn = (k == BuiltinType::LongDouble) ? ObjCTypes.getSendFpretFn2(IsSuper) 1561198092Srdivacky : ObjCTypes.getSendFn2(IsSuper); 1562194179Sed } else { 1563194179Sed Fn = ObjCTypes.getSendFn2(IsSuper); 1564193326Sed } 1565198092Srdivacky } else 1566193326Sed // FIXME. This currently matches gcc's API for x86-32. May need to change 1567193326Sed // for others if we have their API. 1568193326Sed Fn = ObjCTypes.getSendFpretFn(IsSuper); 1569193326Sed } else { 1570193326Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper) 1571198092Srdivacky : ObjCTypes.getSendFn(IsSuper); 1572193326Sed } 1573193326Sed assert(Fn && "EmitLegacyMessageSend - unknown API"); 1574198092Srdivacky Fn = llvm::ConstantExpr::getBitCast(Fn, 1575198092Srdivacky llvm::PointerType::getUnqual(FTy)); 1576193326Sed return CGF.EmitCall(FnInfo, Fn, ActualArgs); 1577193326Sed} 1578193326Sed 1579198092Srdivackyllvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder, 1580193326Sed const ObjCProtocolDecl *PD) { 1581193326Sed // FIXME: I don't understand why gcc generates this, or where it is 1582193326Sed // resolved. Investigate. Its also wasteful to look this up over and over. 1583193326Sed LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); 1584193326Sed 1585193326Sed return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD), 1586193326Sed ObjCTypes.ExternalProtocolPtrTy); 1587193326Sed} 1588193326Sed 1589193326Sedvoid CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) { 1590193326Sed // FIXME: We shouldn't need this, the protocol decl should contain enough 1591193326Sed // information to tell us whether this was a declaration or a definition. 1592193326Sed DefinedProtocols.insert(PD->getIdentifier()); 1593193326Sed 1594193326Sed // If we have generated a forward reference to this protocol, emit 1595193326Sed // it now. Otherwise do nothing, the protocol objects are lazily 1596193326Sed // emitted. 1597198092Srdivacky if (Protocols.count(PD->getIdentifier())) 1598193326Sed GetOrEmitProtocol(PD); 1599193326Sed} 1600193326Sed 1601193326Sedllvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) { 1602193326Sed if (DefinedProtocols.count(PD->getIdentifier())) 1603193326Sed return GetOrEmitProtocol(PD); 1604193326Sed return GetOrEmitProtocolRef(PD); 1605193326Sed} 1606193326Sed 1607193326Sed/* 1608198092Srdivacky// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions 1609198092Srdivackystruct _objc_protocol { 1610198092Srdivackystruct _objc_protocol_extension *isa; 1611198092Srdivackychar *protocol_name; 1612198092Srdivackystruct _objc_protocol_list *protocol_list; 1613198092Srdivackystruct _objc__method_prototype_list *instance_methods; 1614198092Srdivackystruct _objc__method_prototype_list *class_methods 1615198092Srdivacky}; 1616193326Sed 1617198092SrdivackySee EmitProtocolExtension(). 1618193326Sed*/ 1619193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { 1620193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 1621193326Sed 1622193326Sed // Early exit if a defining object has already been generated. 1623193326Sed if (Entry && Entry->hasInitializer()) 1624193326Sed return Entry; 1625193326Sed 1626193326Sed // FIXME: I don't understand why gcc generates this, or where it is 1627193326Sed // resolved. Investigate. Its also wasteful to look this up over and over. 1628193326Sed LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); 1629193326Sed 1630193326Sed // Construct method lists. 1631193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 1632193326Sed std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; 1633198092Srdivacky for (ObjCProtocolDecl::instmeth_iterator 1634195341Sed i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { 1635193326Sed ObjCMethodDecl *MD = *i; 1636193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 1637193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 1638193326Sed OptInstanceMethods.push_back(C); 1639193326Sed } else { 1640193326Sed InstanceMethods.push_back(C); 1641198092Srdivacky } 1642193326Sed } 1643193326Sed 1644198092Srdivacky for (ObjCProtocolDecl::classmeth_iterator 1645195341Sed i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { 1646193326Sed ObjCMethodDecl *MD = *i; 1647193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 1648193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 1649193326Sed OptClassMethods.push_back(C); 1650193326Sed } else { 1651193326Sed ClassMethods.push_back(C); 1652198092Srdivacky } 1653193326Sed } 1654193326Sed 1655193326Sed std::vector<llvm::Constant*> Values(5); 1656193326Sed Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods); 1657193326Sed Values[1] = GetClassName(PD->getIdentifier()); 1658198092Srdivacky Values[2] = 1659198398Srdivacky EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(), 1660193326Sed PD->protocol_begin(), 1661193326Sed PD->protocol_end()); 1662198092Srdivacky Values[3] = 1663198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(), 1664193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 1665193326Sed InstanceMethods); 1666198092Srdivacky Values[4] = 1667198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(), 1668193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1669193326Sed ClassMethods); 1670193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, 1671193326Sed Values); 1672198092Srdivacky 1673193326Sed if (Entry) { 1674193326Sed // Already created, fix the linkage and update the initializer. 1675193326Sed Entry->setLinkage(llvm::GlobalValue::InternalLinkage); 1676193326Sed Entry->setInitializer(Init); 1677193326Sed } else { 1678198092Srdivacky Entry = 1679198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, 1680193326Sed llvm::GlobalValue::InternalLinkage, 1681198092Srdivacky Init, 1682198398Srdivacky "\01L_OBJC_PROTOCOL_" + PD->getName()); 1683193326Sed Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); 1684193326Sed Entry->setAlignment(4); 1685193326Sed // FIXME: Is this necessary? Why only for protocol? 1686193326Sed Entry->setAlignment(4); 1687193326Sed } 1688198092Srdivacky CGM.AddUsedGlobal(Entry); 1689193326Sed 1690193326Sed return Entry; 1691193326Sed} 1692193326Sed 1693193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { 1694193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 1695193326Sed 1696193326Sed if (!Entry) { 1697193326Sed // We use the initializer as a marker of whether this is a forward 1698193326Sed // reference or not. At module finalization we add the empty 1699193326Sed // contents for protocols which were referenced but never defined. 1700198092Srdivacky Entry = 1701198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, 1702193326Sed llvm::GlobalValue::ExternalLinkage, 1703193326Sed 0, 1704198398Srdivacky "\01L_OBJC_PROTOCOL_" + PD->getName()); 1705193326Sed Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); 1706193326Sed Entry->setAlignment(4); 1707193326Sed // FIXME: Is this necessary? Why only for protocol? 1708193326Sed Entry->setAlignment(4); 1709193326Sed } 1710198092Srdivacky 1711193326Sed return Entry; 1712193326Sed} 1713193326Sed 1714193326Sed/* 1715193326Sed struct _objc_protocol_extension { 1716198092Srdivacky uint32_t size; 1717198092Srdivacky struct objc_method_description_list *optional_instance_methods; 1718198092Srdivacky struct objc_method_description_list *optional_class_methods; 1719198092Srdivacky struct objc_property_list *instance_properties; 1720193326Sed }; 1721193326Sed*/ 1722193326Sedllvm::Constant * 1723193326SedCGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, 1724193326Sed const ConstantVector &OptInstanceMethods, 1725193326Sed const ConstantVector &OptClassMethods) { 1726198092Srdivacky uint64_t Size = 1727193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); 1728193326Sed std::vector<llvm::Constant*> Values(4); 1729193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 1730198092Srdivacky Values[1] = 1731198092Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_" 1732198398Srdivacky + PD->getName(), 1733193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 1734193326Sed OptInstanceMethods); 1735198092Srdivacky Values[2] = 1736198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(), 1737193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1738193326Sed OptClassMethods); 1739198398Srdivacky Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 1740193326Sed 0, PD, ObjCTypes); 1741193326Sed 1742193326Sed // Return null if no extension bits are used. 1743198092Srdivacky if (Values[1]->isNullValue() && Values[2]->isNullValue() && 1744193326Sed Values[3]->isNullValue()) 1745193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); 1746193326Sed 1747198092Srdivacky llvm::Constant *Init = 1748193326Sed llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values); 1749193326Sed 1750193326Sed // No special section, but goes in llvm.used 1751198398Srdivacky return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(), 1752198092Srdivacky Init, 1753193326Sed 0, 0, true); 1754193326Sed} 1755193326Sed 1756193326Sed/* 1757193326Sed struct objc_protocol_list { 1758198092Srdivacky struct objc_protocol_list *next; 1759198092Srdivacky long count; 1760198092Srdivacky Protocol *list[]; 1761193326Sed }; 1762193326Sed*/ 1763193326Sedllvm::Constant * 1764198398SrdivackyCGObjCMac::EmitProtocolList(llvm::Twine Name, 1765193326Sed ObjCProtocolDecl::protocol_iterator begin, 1766193326Sed ObjCProtocolDecl::protocol_iterator end) { 1767193326Sed std::vector<llvm::Constant*> ProtocolRefs; 1768193326Sed 1769193326Sed for (; begin != end; ++begin) 1770193326Sed ProtocolRefs.push_back(GetProtocolRef(*begin)); 1771193326Sed 1772193326Sed // Just return null for empty protocol lists 1773198092Srdivacky if (ProtocolRefs.empty()) 1774193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 1775193326Sed 1776193326Sed // This list is null terminated. 1777193326Sed ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy)); 1778193326Sed 1779193326Sed std::vector<llvm::Constant*> Values(3); 1780193326Sed // This field is only used by the runtime. 1781193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 1782198092Srdivacky Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, 1783198092Srdivacky ProtocolRefs.size() - 1); 1784198092Srdivacky Values[2] = 1785198092Srdivacky llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy, 1786198092Srdivacky ProtocolRefs.size()), 1787193326Sed ProtocolRefs); 1788198092Srdivacky 1789198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 1790198092Srdivacky llvm::GlobalVariable *GV = 1791193326Sed CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1792193326Sed 4, false); 1793193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy); 1794193326Sed} 1795193326Sed 1796193326Sed/* 1797193326Sed struct _objc_property { 1798198092Srdivacky const char * const name; 1799198092Srdivacky const char * const attributes; 1800193326Sed }; 1801193326Sed 1802193326Sed struct _objc_property_list { 1803198092Srdivacky uint32_t entsize; // sizeof (struct _objc_property) 1804198092Srdivacky uint32_t prop_count; 1805198092Srdivacky struct _objc_property[prop_count]; 1806193326Sed }; 1807193326Sed*/ 1808198398Srdivackyllvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name, 1809198092Srdivacky const Decl *Container, 1810198092Srdivacky const ObjCContainerDecl *OCD, 1811198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 1812193326Sed std::vector<llvm::Constant*> Properties, Prop(2); 1813198092Srdivacky for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(), 1814198092Srdivacky E = OCD->prop_end(); I != E; ++I) { 1815193326Sed const ObjCPropertyDecl *PD = *I; 1816193326Sed Prop[0] = GetPropertyName(PD->getIdentifier()); 1817193326Sed Prop[1] = GetPropertyTypeString(PD, Container); 1818193326Sed Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, 1819193326Sed Prop)); 1820193326Sed } 1821193326Sed 1822193326Sed // Return null for empty list. 1823193326Sed if (Properties.empty()) 1824193326Sed return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 1825193326Sed 1826198092Srdivacky unsigned PropertySize = 1827193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy); 1828193326Sed std::vector<llvm::Constant*> Values(3); 1829193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize); 1830193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size()); 1831198092Srdivacky llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy, 1832193326Sed Properties.size()); 1833193326Sed Values[2] = llvm::ConstantArray::get(AT, Properties); 1834198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 1835193326Sed 1836198092Srdivacky llvm::GlobalVariable *GV = 1837198092Srdivacky CreateMetadataVar(Name, Init, 1838198092Srdivacky (ObjCABI == 2) ? "__DATA, __objc_const" : 1839193326Sed "__OBJC,__property,regular,no_dead_strip", 1840198092Srdivacky (ObjCABI == 2) ? 8 : 4, 1841193326Sed true); 1842193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy); 1843193326Sed} 1844193326Sed 1845193326Sed/* 1846193326Sed struct objc_method_description_list { 1847198092Srdivacky int count; 1848198092Srdivacky struct objc_method_description list[]; 1849193326Sed }; 1850193326Sed*/ 1851193326Sedllvm::Constant * 1852193326SedCGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { 1853193326Sed std::vector<llvm::Constant*> Desc(2); 1854198092Srdivacky Desc[0] = 1855198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 1856198092Srdivacky ObjCTypes.SelectorPtrTy); 1857193326Sed Desc[1] = GetMethodVarType(MD); 1858193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy, 1859193326Sed Desc); 1860193326Sed} 1861193326Sed 1862198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name, 1863193326Sed const char *Section, 1864193326Sed const ConstantVector &Methods) { 1865193326Sed // Return null for empty list. 1866193326Sed if (Methods.empty()) 1867193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); 1868193326Sed 1869193326Sed std::vector<llvm::Constant*> Values(2); 1870193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 1871198092Srdivacky llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy, 1872193326Sed Methods.size()); 1873193326Sed Values[1] = llvm::ConstantArray::get(AT, Methods); 1874198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 1875193326Sed 1876193326Sed llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true); 1877198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, 1878193326Sed ObjCTypes.MethodDescriptionListPtrTy); 1879193326Sed} 1880193326Sed 1881193326Sed/* 1882193326Sed struct _objc_category { 1883198092Srdivacky char *category_name; 1884198092Srdivacky char *class_name; 1885198092Srdivacky struct _objc_method_list *instance_methods; 1886198092Srdivacky struct _objc_method_list *class_methods; 1887198092Srdivacky struct _objc_protocol_list *protocols; 1888198092Srdivacky uint32_t size; // <rdar://4585769> 1889198092Srdivacky struct _objc_property_list *instance_properties; 1890193326Sed }; 1891198092Srdivacky*/ 1892193326Sedvoid CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 1893193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy); 1894193326Sed 1895193326Sed // FIXME: This is poor design, the OCD should have a pointer to the category 1896193326Sed // decl. Additionally, note that Category can be null for the @implementation 1897193326Sed // w/o an @interface case. Sema should just create one for us as it does for 1898193326Sed // @implementation so everyone else can live life under a clear blue sky. 1899193326Sed const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); 1900198092Srdivacky const ObjCCategoryDecl *Category = 1901193326Sed Interface->FindCategoryDeclaration(OCD->getIdentifier()); 1902193326Sed 1903198398Srdivacky llvm::SmallString<256> ExtName; 1904198398Srdivacky llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_' 1905198398Srdivacky << OCD->getName(); 1906198398Srdivacky 1907193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 1908198092Srdivacky for (ObjCCategoryImplDecl::instmeth_iterator 1909195341Sed i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { 1910193326Sed // Instance methods should always be defined. 1911193326Sed InstanceMethods.push_back(GetMethodConstant(*i)); 1912193326Sed } 1913198092Srdivacky for (ObjCCategoryImplDecl::classmeth_iterator 1914195341Sed i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { 1915193326Sed // Class methods should always be defined. 1916193326Sed ClassMethods.push_back(GetMethodConstant(*i)); 1917193326Sed } 1918193326Sed 1919193326Sed std::vector<llvm::Constant*> Values(7); 1920193326Sed Values[0] = GetClassName(OCD->getIdentifier()); 1921193326Sed Values[1] = GetClassName(Interface->getIdentifier()); 1922193326Sed LazySymbols.insert(Interface->getIdentifier()); 1923198092Srdivacky Values[2] = 1924198398Srdivacky EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(), 1925193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 1926193326Sed InstanceMethods); 1927198092Srdivacky Values[3] = 1928198398Srdivacky EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(), 1929193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1930193326Sed ClassMethods); 1931193326Sed if (Category) { 1932198092Srdivacky Values[4] = 1933198398Srdivacky EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(), 1934193326Sed Category->protocol_begin(), 1935193326Sed Category->protocol_end()); 1936193326Sed } else { 1937193326Sed Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 1938193326Sed } 1939193326Sed Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 1940193326Sed 1941193326Sed // If there is no category @interface then there can be no properties. 1942193326Sed if (Category) { 1943198398Srdivacky Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), 1944193326Sed OCD, Category, ObjCTypes); 1945193326Sed } else { 1946193326Sed Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 1947193326Sed } 1948198092Srdivacky 1949193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy, 1950193326Sed Values); 1951193326Sed 1952198092Srdivacky llvm::GlobalVariable *GV = 1953198398Srdivacky CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init, 1954193326Sed "__OBJC,__category,regular,no_dead_strip", 1955193326Sed 4, true); 1956193326Sed DefinedCategories.push_back(GV); 1957193326Sed} 1958193326Sed 1959193326Sed// FIXME: Get from somewhere? 1960193326Sedenum ClassFlags { 1961193326Sed eClassFlags_Factory = 0x00001, 1962193326Sed eClassFlags_Meta = 0x00002, 1963193326Sed // <rdr://5142207> 1964193326Sed eClassFlags_HasCXXStructors = 0x02000, 1965193326Sed eClassFlags_Hidden = 0x20000, 1966193326Sed eClassFlags_ABI2_Hidden = 0x00010, 1967193326Sed eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634> 1968193326Sed}; 1969193326Sed 1970193326Sed/* 1971193326Sed struct _objc_class { 1972198092Srdivacky Class isa; 1973198092Srdivacky Class super_class; 1974198092Srdivacky const char *name; 1975198092Srdivacky long version; 1976198092Srdivacky long info; 1977198092Srdivacky long instance_size; 1978198092Srdivacky struct _objc_ivar_list *ivars; 1979198092Srdivacky struct _objc_method_list *methods; 1980198092Srdivacky struct _objc_cache *cache; 1981198092Srdivacky struct _objc_protocol_list *protocols; 1982198092Srdivacky // Objective-C 1.0 extensions (<rdr://4585769>) 1983198092Srdivacky const char *ivar_layout; 1984198092Srdivacky struct _objc_class_ext *ext; 1985193326Sed }; 1986193326Sed 1987193326Sed See EmitClassExtension(); 1988198092Srdivacky*/ 1989193326Sedvoid CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { 1990193326Sed DefinedSymbols.insert(ID->getIdentifier()); 1991193326Sed 1992193326Sed std::string ClassName = ID->getNameAsString(); 1993193326Sed // FIXME: Gross 1994198092Srdivacky ObjCInterfaceDecl *Interface = 1995193326Sed const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); 1996198092Srdivacky llvm::Constant *Protocols = 1997198398Srdivacky EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(), 1998193326Sed Interface->protocol_begin(), 1999193326Sed Interface->protocol_end()); 2000193326Sed unsigned Flags = eClassFlags_Factory; 2001198092Srdivacky unsigned Size = 2002193326Sed CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8; 2003193326Sed 2004193326Sed // FIXME: Set CXX-structors flag. 2005193326Sed if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden) 2006193326Sed Flags |= eClassFlags_Hidden; 2007193326Sed 2008193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 2009198092Srdivacky for (ObjCImplementationDecl::instmeth_iterator 2010195341Sed i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { 2011193326Sed // Instance methods should always be defined. 2012193326Sed InstanceMethods.push_back(GetMethodConstant(*i)); 2013193326Sed } 2014198092Srdivacky for (ObjCImplementationDecl::classmeth_iterator 2015195341Sed i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { 2016193326Sed // Class methods should always be defined. 2017193326Sed ClassMethods.push_back(GetMethodConstant(*i)); 2018193326Sed } 2019193326Sed 2020198092Srdivacky for (ObjCImplementationDecl::propimpl_iterator 2021195341Sed i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { 2022193326Sed ObjCPropertyImplDecl *PID = *i; 2023193326Sed 2024193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { 2025193326Sed ObjCPropertyDecl *PD = PID->getPropertyDecl(); 2026193326Sed 2027193326Sed if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) 2028193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 2029193326Sed InstanceMethods.push_back(C); 2030193326Sed if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) 2031193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 2032193326Sed InstanceMethods.push_back(C); 2033193326Sed } 2034193326Sed } 2035193326Sed 2036193326Sed std::vector<llvm::Constant*> Values(12); 2037193326Sed Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods); 2038193326Sed if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) { 2039193326Sed // Record a reference to the super class. 2040193326Sed LazySymbols.insert(Super->getIdentifier()); 2041193326Sed 2042198092Srdivacky Values[ 1] = 2043193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), 2044193326Sed ObjCTypes.ClassPtrTy); 2045193326Sed } else { 2046193326Sed Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy); 2047193326Sed } 2048193326Sed Values[ 2] = GetClassName(ID->getIdentifier()); 2049193326Sed // Version is always 0. 2050193326Sed Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 2051193326Sed Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); 2052193326Sed Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 2053193326Sed Values[ 6] = EmitIvarList(ID, false); 2054198092Srdivacky Values[ 7] = 2055198398Srdivacky EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(), 2056193326Sed "__OBJC,__inst_meth,regular,no_dead_strip", 2057193326Sed InstanceMethods); 2058193326Sed // cache is always NULL. 2059193326Sed Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy); 2060193326Sed Values[ 9] = Protocols; 2061198092Srdivacky Values[10] = BuildIvarLayout(ID, true); 2062193326Sed Values[11] = EmitClassExtension(ID); 2063193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy, 2064193326Sed Values); 2065199482Srdivacky std::string Name("\01L_OBJC_CLASS_"); 2066199482Srdivacky Name += ClassName; 2067199482Srdivacky const char *Section = "__OBJC,__class,regular,no_dead_strip"; 2068199482Srdivacky // Check for a forward reference. 2069199482Srdivacky llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 2070199482Srdivacky if (GV) { 2071199482Srdivacky assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2072199482Srdivacky "Forward metaclass reference has incorrect type."); 2073199482Srdivacky GV->setLinkage(llvm::GlobalValue::InternalLinkage); 2074199482Srdivacky GV->setInitializer(Init); 2075199482Srdivacky GV->setSection(Section); 2076199482Srdivacky GV->setAlignment(4); 2077199482Srdivacky CGM.AddUsedGlobal(GV); 2078199482Srdivacky } 2079199482Srdivacky else 2080199482Srdivacky GV = CreateMetadataVar(Name, Init, Section, 4, true); 2081193326Sed DefinedClasses.push_back(GV); 2082193326Sed} 2083193326Sed 2084193326Sedllvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, 2085193326Sed llvm::Constant *Protocols, 2086193326Sed const ConstantVector &Methods) { 2087193326Sed unsigned Flags = eClassFlags_Meta; 2088193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy); 2089193326Sed 2090193326Sed if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden) 2091193326Sed Flags |= eClassFlags_Hidden; 2092198092Srdivacky 2093193326Sed std::vector<llvm::Constant*> Values(12); 2094193326Sed // The isa for the metaclass is the root of the hierarchy. 2095193326Sed const ObjCInterfaceDecl *Root = ID->getClassInterface(); 2096193326Sed while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) 2097193326Sed Root = Super; 2098198092Srdivacky Values[ 0] = 2099193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()), 2100193326Sed ObjCTypes.ClassPtrTy); 2101193326Sed // The super class for the metaclass is emitted as the name of the 2102193326Sed // super class. The runtime fixes this up to point to the 2103193326Sed // *metaclass* for the super class. 2104193326Sed if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) { 2105198092Srdivacky Values[ 1] = 2106193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), 2107193326Sed ObjCTypes.ClassPtrTy); 2108193326Sed } else { 2109193326Sed Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy); 2110193326Sed } 2111193326Sed Values[ 2] = GetClassName(ID->getIdentifier()); 2112193326Sed // Version is always 0. 2113193326Sed Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 2114193326Sed Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); 2115193326Sed Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 2116193326Sed Values[ 6] = EmitIvarList(ID, true); 2117198092Srdivacky Values[ 7] = 2118193326Sed EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(), 2119193326Sed "__OBJC,__cls_meth,regular,no_dead_strip", 2120193326Sed Methods); 2121193326Sed // cache is always NULL. 2122193326Sed Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy); 2123193326Sed Values[ 9] = Protocols; 2124193326Sed // ivar_layout for metaclass is always NULL. 2125193326Sed Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 2126193326Sed // The class extension is always unused for metaclasses. 2127193326Sed Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); 2128193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy, 2129193326Sed Values); 2130193326Sed 2131193326Sed std::string Name("\01L_OBJC_METACLASS_"); 2132193326Sed Name += ID->getNameAsCString(); 2133193326Sed 2134193326Sed // Check for a forward reference. 2135193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 2136193326Sed if (GV) { 2137193326Sed assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2138193326Sed "Forward metaclass reference has incorrect type."); 2139193326Sed GV->setLinkage(llvm::GlobalValue::InternalLinkage); 2140193326Sed GV->setInitializer(Init); 2141193326Sed } else { 2142198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 2143193326Sed llvm::GlobalValue::InternalLinkage, 2144198092Srdivacky Init, Name); 2145193326Sed } 2146193326Sed GV->setSection("__OBJC,__meta_class,regular,no_dead_strip"); 2147193326Sed GV->setAlignment(4); 2148198092Srdivacky CGM.AddUsedGlobal(GV); 2149193326Sed 2150193326Sed return GV; 2151193326Sed} 2152193326Sed 2153198092Srdivackyllvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) { 2154193326Sed std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString(); 2155193326Sed 2156193326Sed // FIXME: Should we look these up somewhere other than the module. Its a bit 2157193326Sed // silly since we only generate these while processing an implementation, so 2158193326Sed // exactly one pointer would work if know when we entered/exitted an 2159193326Sed // implementation block. 2160193326Sed 2161193326Sed // Check for an existing forward reference. 2162193326Sed // Previously, metaclass with internal linkage may have been defined. 2163193326Sed // pass 'true' as 2nd argument so it is returned. 2164198092Srdivacky if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, 2165198092Srdivacky true)) { 2166193326Sed assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2167193326Sed "Forward metaclass reference has incorrect type."); 2168193326Sed return GV; 2169193326Sed } else { 2170193326Sed // Generate as an external reference to keep a consistent 2171193326Sed // module. This will be patched up when we emit the metaclass. 2172198092Srdivacky return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 2173193326Sed llvm::GlobalValue::ExternalLinkage, 2174193326Sed 0, 2175198092Srdivacky Name); 2176193326Sed } 2177193326Sed} 2178193326Sed 2179199482Srdivackyllvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) { 2180199482Srdivacky std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString(); 2181199482Srdivacky 2182199482Srdivacky if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, 2183199482Srdivacky true)) { 2184199482Srdivacky assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2185199482Srdivacky "Forward class metadata reference has incorrect type."); 2186199482Srdivacky return GV; 2187199482Srdivacky } else { 2188199482Srdivacky return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 2189199482Srdivacky llvm::GlobalValue::ExternalLinkage, 2190199482Srdivacky 0, 2191199482Srdivacky Name); 2192199482Srdivacky } 2193199482Srdivacky} 2194199482Srdivacky 2195193326Sed/* 2196193326Sed struct objc_class_ext { 2197198092Srdivacky uint32_t size; 2198198092Srdivacky const char *weak_ivar_layout; 2199198092Srdivacky struct _objc_property_list *properties; 2200193326Sed }; 2201193326Sed*/ 2202193326Sedllvm::Constant * 2203193326SedCGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) { 2204198092Srdivacky uint64_t Size = 2205193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy); 2206193326Sed 2207193326Sed std::vector<llvm::Constant*> Values(3); 2208193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 2209193326Sed Values[1] = BuildIvarLayout(ID, false); 2210198398Srdivacky Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), 2211193326Sed ID, ID->getClassInterface(), ObjCTypes); 2212193326Sed 2213193326Sed // Return null if no extension bits are used. 2214193326Sed if (Values[1]->isNullValue() && Values[2]->isNullValue()) 2215193326Sed return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); 2216193326Sed 2217198092Srdivacky llvm::Constant *Init = 2218193326Sed llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values); 2219198398Srdivacky return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(), 2220198092Srdivacky Init, "__OBJC,__class_ext,regular,no_dead_strip", 2221193326Sed 4, true); 2222193326Sed} 2223193326Sed 2224193326Sed/* 2225193326Sed struct objc_ivar { 2226198092Srdivacky char *ivar_name; 2227198092Srdivacky char *ivar_type; 2228198092Srdivacky int ivar_offset; 2229193326Sed }; 2230193326Sed 2231193326Sed struct objc_ivar_list { 2232198092Srdivacky int ivar_count; 2233198092Srdivacky struct objc_ivar list[count]; 2234193326Sed }; 2235198092Srdivacky*/ 2236193326Sedllvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, 2237193326Sed bool ForClass) { 2238193326Sed std::vector<llvm::Constant*> Ivars, Ivar(3); 2239193326Sed 2240193326Sed // When emitting the root class GCC emits ivar entries for the 2241193326Sed // actual class structure. It is not clear if we need to follow this 2242193326Sed // behavior; for now lets try and get away with not doing it. If so, 2243193326Sed // the cleanest solution would be to make up an ObjCInterfaceDecl 2244193326Sed // for the class. 2245193326Sed if (ForClass) 2246193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); 2247198092Srdivacky 2248198092Srdivacky ObjCInterfaceDecl *OID = 2249193326Sed const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); 2250198092Srdivacky 2251193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; 2252193576Sed CGM.getContext().ShallowCollectObjCIvars(OID, OIvars); 2253198092Srdivacky 2254193326Sed for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { 2255193326Sed ObjCIvarDecl *IVD = OIvars[i]; 2256193576Sed // Ignore unnamed bit-fields. 2257193576Sed if (!IVD->getDeclName()) 2258198092Srdivacky continue; 2259193326Sed Ivar[0] = GetMethodVarName(IVD->getIdentifier()); 2260193326Sed Ivar[1] = GetMethodVarType(IVD); 2261198092Srdivacky Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, 2262193326Sed ComputeIvarBaseOffset(CGM, OID, IVD)); 2263193326Sed Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar)); 2264193326Sed } 2265193326Sed 2266193326Sed // Return null for empty list. 2267193326Sed if (Ivars.empty()) 2268193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); 2269193326Sed 2270193326Sed std::vector<llvm::Constant*> Values(2); 2271193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size()); 2272193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy, 2273193326Sed Ivars.size()); 2274193326Sed Values[1] = llvm::ConstantArray::get(AT, Ivars); 2275198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 2276193326Sed 2277193326Sed llvm::GlobalVariable *GV; 2278193326Sed if (ForClass) 2279198398Srdivacky GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(), 2280198092Srdivacky Init, "__OBJC,__class_vars,regular,no_dead_strip", 2281193326Sed 4, true); 2282193326Sed else 2283198398Srdivacky GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(), 2284193326Sed Init, "__OBJC,__instance_vars,regular,no_dead_strip", 2285193326Sed 4, true); 2286193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy); 2287193326Sed} 2288193326Sed 2289193326Sed/* 2290193326Sed struct objc_method { 2291198092Srdivacky SEL method_name; 2292198092Srdivacky char *method_types; 2293198092Srdivacky void *method; 2294193326Sed }; 2295198092Srdivacky 2296193326Sed struct objc_method_list { 2297198092Srdivacky struct objc_method_list *obsolete; 2298198092Srdivacky int count; 2299198092Srdivacky struct objc_method methods_list[count]; 2300193326Sed }; 2301193326Sed*/ 2302193326Sed 2303193326Sed/// GetMethodConstant - Return a struct objc_method constant for the 2304193326Sed/// given method if it has been defined. The result is null if the 2305193326Sed/// method has not been defined. The return value has type MethodPtrTy. 2306193326Sedllvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) { 2307193326Sed // FIXME: Use DenseMap::lookup 2308193326Sed llvm::Function *Fn = MethodDefinitions[MD]; 2309193326Sed if (!Fn) 2310193326Sed return 0; 2311198092Srdivacky 2312193326Sed std::vector<llvm::Constant*> Method(3); 2313198092Srdivacky Method[0] = 2314193326Sed llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 2315193326Sed ObjCTypes.SelectorPtrTy); 2316193326Sed Method[1] = GetMethodVarType(MD); 2317193326Sed Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy); 2318193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method); 2319193326Sed} 2320193326Sed 2321198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name, 2322193326Sed const char *Section, 2323193326Sed const ConstantVector &Methods) { 2324193326Sed // Return null for empty list. 2325193326Sed if (Methods.empty()) 2326193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy); 2327193326Sed 2328193326Sed std::vector<llvm::Constant*> Values(3); 2329193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 2330193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 2331193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy, 2332193326Sed Methods.size()); 2333193326Sed Values[2] = llvm::ConstantArray::get(AT, Methods); 2334198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 2335193326Sed 2336193326Sed llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true); 2337193326Sed return llvm::ConstantExpr::getBitCast(GV, 2338193326Sed ObjCTypes.MethodListPtrTy); 2339193326Sed} 2340193326Sed 2341193326Sedllvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD, 2342198092Srdivacky const ObjCContainerDecl *CD) { 2343198398Srdivacky llvm::SmallString<256> Name; 2344193326Sed GetNameForMethod(OMD, CD, Name); 2345193326Sed 2346193326Sed CodeGenTypes &Types = CGM.getTypes(); 2347193326Sed const llvm::FunctionType *MethodTy = 2348193326Sed Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic()); 2349198092Srdivacky llvm::Function *Method = 2350193326Sed llvm::Function::Create(MethodTy, 2351193326Sed llvm::GlobalValue::InternalLinkage, 2352198398Srdivacky Name.str(), 2353193326Sed &CGM.getModule()); 2354193326Sed MethodDefinitions.insert(std::make_pair(OMD, Method)); 2355193326Sed 2356193326Sed return Method; 2357193326Sed} 2358193326Sed 2359193326Sedllvm::GlobalVariable * 2360198398SrdivackyCGObjCCommonMac::CreateMetadataVar(llvm::Twine Name, 2361193326Sed llvm::Constant *Init, 2362193326Sed const char *Section, 2363193326Sed unsigned Align, 2364193326Sed bool AddToUsed) { 2365193326Sed const llvm::Type *Ty = Init->getType(); 2366198092Srdivacky llvm::GlobalVariable *GV = 2367198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Ty, false, 2368198092Srdivacky llvm::GlobalValue::InternalLinkage, Init, Name); 2369193326Sed if (Section) 2370193326Sed GV->setSection(Section); 2371193326Sed if (Align) 2372193326Sed GV->setAlignment(Align); 2373193326Sed if (AddToUsed) 2374198092Srdivacky CGM.AddUsedGlobal(GV); 2375193326Sed return GV; 2376193326Sed} 2377193326Sed 2378198092Srdivackyllvm::Function *CGObjCMac::ModuleInitFunction() { 2379193326Sed // Abuse this interface function as a place to finalize. 2380193326Sed FinishModule(); 2381193326Sed return NULL; 2382193326Sed} 2383193326Sed 2384193326Sedllvm::Constant *CGObjCMac::GetPropertyGetFunction() { 2385193326Sed return ObjCTypes.getGetPropertyFn(); 2386193326Sed} 2387193326Sed 2388193326Sedllvm::Constant *CGObjCMac::GetPropertySetFunction() { 2389193326Sed return ObjCTypes.getSetPropertyFn(); 2390193326Sed} 2391193326Sed 2392193326Sedllvm::Constant *CGObjCMac::EnumerationMutationFunction() { 2393193326Sed return ObjCTypes.getEnumerationMutationFn(); 2394193326Sed} 2395193326Sed 2396198092Srdivacky/* 2397193326Sed 2398198092Srdivacky Objective-C setjmp-longjmp (sjlj) Exception Handling 2399198092Srdivacky -- 2400193326Sed 2401198092Srdivacky The basic framework for a @try-catch-finally is as follows: 2402198092Srdivacky { 2403193326Sed objc_exception_data d; 2404193326Sed id _rethrow = null; 2405193326Sed bool _call_try_exit = true; 2406198092Srdivacky 2407193326Sed objc_exception_try_enter(&d); 2408193326Sed if (!setjmp(d.jmp_buf)) { 2409198092Srdivacky ... try body ... 2410193326Sed } else { 2411198092Srdivacky // exception path 2412198092Srdivacky id _caught = objc_exception_extract(&d); 2413198092Srdivacky 2414198092Srdivacky // enter new try scope for handlers 2415198092Srdivacky if (!setjmp(d.jmp_buf)) { 2416198092Srdivacky ... match exception and execute catch blocks ... 2417198092Srdivacky 2418198092Srdivacky // fell off end, rethrow. 2419198092Srdivacky _rethrow = _caught; 2420198092Srdivacky ... jump-through-finally to finally_rethrow ... 2421198092Srdivacky } else { 2422198092Srdivacky // exception in catch block 2423198092Srdivacky _rethrow = objc_exception_extract(&d); 2424198092Srdivacky _call_try_exit = false; 2425198092Srdivacky ... jump-through-finally to finally_rethrow ... 2426193326Sed } 2427198092Srdivacky } 2428193326Sed ... jump-through-finally to finally_end ... 2429193326Sed 2430198092Srdivacky finally: 2431193326Sed if (_call_try_exit) 2432198092Srdivacky objc_exception_try_exit(&d); 2433193326Sed 2434193326Sed ... finally block .... 2435193326Sed ... dispatch to finally destination ... 2436193326Sed 2437198092Srdivacky finally_rethrow: 2438193326Sed objc_exception_throw(_rethrow); 2439193326Sed 2440198092Srdivacky finally_end: 2441198092Srdivacky } 2442193326Sed 2443198092Srdivacky This framework differs slightly from the one gcc uses, in that gcc 2444198092Srdivacky uses _rethrow to determine if objc_exception_try_exit should be called 2445198092Srdivacky and if the object should be rethrown. This breaks in the face of 2446198092Srdivacky throwing nil and introduces unnecessary branches. 2447193326Sed 2448198092Srdivacky We specialize this framework for a few particular circumstances: 2449193326Sed 2450198092Srdivacky - If there are no catch blocks, then we avoid emitting the second 2451198092Srdivacky exception handling context. 2452193326Sed 2453198092Srdivacky - If there is a catch-all catch block (i.e. @catch(...) or @catch(id 2454198092Srdivacky e)) we avoid emitting the code to rethrow an uncaught exception. 2455193326Sed 2456198092Srdivacky - FIXME: If there is no @finally block we can do a few more 2457198092Srdivacky simplifications. 2458193326Sed 2459198092Srdivacky Rethrows and Jumps-Through-Finally 2460198092Srdivacky -- 2461193326Sed 2462198092Srdivacky Support for implicit rethrows and jumping through the finally block is 2463198092Srdivacky handled by storing the current exception-handling context in 2464198092Srdivacky ObjCEHStack. 2465193326Sed 2466198092Srdivacky In order to implement proper @finally semantics, we support one basic 2467198092Srdivacky mechanism for jumping through the finally block to an arbitrary 2468198092Srdivacky destination. Constructs which generate exits from a @try or @catch 2469198092Srdivacky block use this mechanism to implement the proper semantics by chaining 2470198092Srdivacky jumps, as necessary. 2471193326Sed 2472198092Srdivacky This mechanism works like the one used for indirect goto: we 2473198092Srdivacky arbitrarily assign an ID to each destination and store the ID for the 2474198092Srdivacky destination in a variable prior to entering the finally block. At the 2475198092Srdivacky end of the finally block we simply create a switch to the proper 2476198092Srdivacky destination. 2477198092Srdivacky 2478198092Srdivacky Code gen for @synchronized(expr) stmt; 2479198092Srdivacky Effectively generating code for: 2480198092Srdivacky objc_sync_enter(expr); 2481198092Srdivacky @try stmt @finally { objc_sync_exit(expr); } 2482193326Sed*/ 2483193326Sed 2484193326Sedvoid CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 2485193326Sed const Stmt &S) { 2486193326Sed bool isTry = isa<ObjCAtTryStmt>(S); 2487193326Sed // Create various blocks we refer to for handling @finally. 2488193326Sed llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally"); 2489193326Sed llvm::BasicBlock *FinallyExit = CGF.createBasicBlock("finally.exit"); 2490193326Sed llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit"); 2491193326Sed llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); 2492193326Sed llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); 2493198092Srdivacky 2494193326Sed // For @synchronized, call objc_sync_enter(sync.expr). The 2495193326Sed // evaluation of the expression must occur before we enter the 2496193326Sed // @synchronized. We can safely avoid a temp here because jumps into 2497193326Sed // @synchronized are illegal & this will dominate uses. 2498193326Sed llvm::Value *SyncArg = 0; 2499193326Sed if (!isTry) { 2500198092Srdivacky SyncArg = 2501193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 2502193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); 2503193326Sed CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg); 2504193326Sed } 2505193326Sed 2506193326Sed // Push an EH context entry, used for handling rethrows and jumps 2507193326Sed // through finally. 2508193326Sed CGF.PushCleanupBlock(FinallyBlock); 2509193326Sed 2510193326Sed CGF.ObjCEHValueStack.push_back(0); 2511198092Srdivacky 2512193326Sed // Allocate memory for the exception data and rethrow pointer. 2513193326Sed llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy, 2514193326Sed "exceptiondata.ptr"); 2515198092Srdivacky llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy, 2516193326Sed "_rethrow"); 2517198092Srdivacky llvm::Value *CallTryExitPtr = CGF.CreateTempAlloca( 2518198092Srdivacky llvm::Type::getInt1Ty(VMContext), 2519193326Sed "_call_try_exit"); 2520198092Srdivacky CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), 2521198092Srdivacky CallTryExitPtr); 2522198092Srdivacky 2523193326Sed // Enter a new try block and call setjmp. 2524193326Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData); 2525198092Srdivacky llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0, 2526193326Sed "jmpbufarray"); 2527193326Sed JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp"); 2528193326Sed llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), 2529193326Sed JmpBufPtr, "result"); 2530193326Sed 2531193326Sed llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); 2532193326Sed llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); 2533198092Srdivacky CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"), 2534193326Sed TryHandler, TryBlock); 2535193326Sed 2536193326Sed // Emit the @try block. 2537193326Sed CGF.EmitBlock(TryBlock); 2538198092Srdivacky CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() 2539198092Srdivacky : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); 2540193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 2541198092Srdivacky 2542193326Sed // Emit the "exception in @try" block. 2543193326Sed CGF.EmitBlock(TryHandler); 2544193326Sed 2545193326Sed // Retrieve the exception object. We may emit multiple blocks but 2546193326Sed // nothing can cross this so the value is already in SSA form. 2547193326Sed llvm::Value *Caught = 2548193326Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(), 2549193326Sed ExceptionData, "caught"); 2550193326Sed CGF.ObjCEHValueStack.back() = Caught; 2551198092Srdivacky if (!isTry) { 2552193326Sed CGF.Builder.CreateStore(Caught, RethrowPtr); 2553198092Srdivacky CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), 2554198092Srdivacky CallTryExitPtr); 2555193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 2556198092Srdivacky } else if (const ObjCAtCatchStmt* CatchStmt = 2557198092Srdivacky cast<ObjCAtTryStmt>(S).getCatchStmts()) { 2558193326Sed // Enter a new exception try block (in case a @catch block throws 2559193326Sed // an exception). 2560193326Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData); 2561198092Srdivacky 2562193326Sed llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), 2563193326Sed JmpBufPtr, "result"); 2564193326Sed llvm::Value *Threw = CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"); 2565193326Sed 2566193326Sed llvm::BasicBlock *CatchBlock = CGF.createBasicBlock("catch"); 2567193326Sed llvm::BasicBlock *CatchHandler = CGF.createBasicBlock("catch.handler"); 2568193326Sed CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock); 2569198092Srdivacky 2570193326Sed CGF.EmitBlock(CatchBlock); 2571198092Srdivacky 2572193326Sed // Handle catch list. As a special case we check if everything is 2573193326Sed // matched and avoid generating code for falling off the end if 2574193326Sed // so. 2575193326Sed bool AllMatched = false; 2576193326Sed for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) { 2577193326Sed llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch"); 2578193326Sed 2579193326Sed const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl(); 2580198092Srdivacky const ObjCObjectPointerType *OPT = 0; 2581193326Sed 2582193326Sed // catch(...) always matches. 2583193326Sed if (!CatchParam) { 2584193326Sed AllMatched = true; 2585193326Sed } else { 2586198092Srdivacky OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>(); 2587198092Srdivacky 2588198092Srdivacky // catch(id e) always matches. 2589193326Sed // FIXME: For the time being we also match id<X>; this should 2590193326Sed // be rejected by Sema instead. 2591198092Srdivacky if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())) 2592193326Sed AllMatched = true; 2593193326Sed } 2594198092Srdivacky 2595198092Srdivacky if (AllMatched) { 2596193326Sed if (CatchParam) { 2597193326Sed CGF.EmitLocalBlockVarDecl(*CatchParam); 2598193326Sed assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); 2599193326Sed CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam)); 2600193326Sed } 2601198092Srdivacky 2602193326Sed CGF.EmitStmt(CatchStmt->getCatchBody()); 2603193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 2604193326Sed break; 2605193326Sed } 2606198092Srdivacky 2607198092Srdivacky assert(OPT && "Unexpected non-object pointer type in @catch"); 2608198092Srdivacky QualType T = OPT->getPointeeType(); 2609198092Srdivacky const ObjCInterfaceType *ObjCType = T->getAs<ObjCInterfaceType>(); 2610193326Sed assert(ObjCType && "Catch parameter must have Objective-C type!"); 2611193326Sed 2612193326Sed // Check if the @catch block matches the exception object. 2613193326Sed llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl()); 2614198092Srdivacky 2615193326Sed llvm::Value *Match = 2616193326Sed CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(), 2617193326Sed Class, Caught, "match"); 2618198092Srdivacky 2619193326Sed llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("matched"); 2620198092Srdivacky 2621198092Srdivacky CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"), 2622193326Sed MatchedBlock, NextCatchBlock); 2623198092Srdivacky 2624193326Sed // Emit the @catch block. 2625193326Sed CGF.EmitBlock(MatchedBlock); 2626193326Sed CGF.EmitLocalBlockVarDecl(*CatchParam); 2627193326Sed assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); 2628193326Sed 2629198092Srdivacky llvm::Value *Tmp = 2630198092Srdivacky CGF.Builder.CreateBitCast(Caught, 2631198092Srdivacky CGF.ConvertType(CatchParam->getType()), 2632193326Sed "tmp"); 2633193326Sed CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam)); 2634198092Srdivacky 2635193326Sed CGF.EmitStmt(CatchStmt->getCatchBody()); 2636193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 2637198092Srdivacky 2638193326Sed CGF.EmitBlock(NextCatchBlock); 2639193326Sed } 2640193326Sed 2641193326Sed if (!AllMatched) { 2642193326Sed // None of the handlers caught the exception, so store it to be 2643193326Sed // rethrown at the end of the @finally block. 2644193326Sed CGF.Builder.CreateStore(Caught, RethrowPtr); 2645193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 2646193326Sed } 2647198092Srdivacky 2648193326Sed // Emit the exception handler for the @catch blocks. 2649198092Srdivacky CGF.EmitBlock(CatchHandler); 2650193326Sed CGF.Builder.CreateStore( 2651198092Srdivacky CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(), 2652198092Srdivacky ExceptionData), 2653198092Srdivacky RethrowPtr); 2654198092Srdivacky CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), 2655198092Srdivacky CallTryExitPtr); 2656193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 2657193326Sed } else { 2658193326Sed CGF.Builder.CreateStore(Caught, RethrowPtr); 2659198092Srdivacky CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), 2660198092Srdivacky CallTryExitPtr); 2661193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 2662193326Sed } 2663198092Srdivacky 2664193326Sed // Pop the exception-handling stack entry. It is important to do 2665193326Sed // this now, because the code in the @finally block is not in this 2666193326Sed // context. 2667193326Sed CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); 2668193326Sed 2669193326Sed CGF.ObjCEHValueStack.pop_back(); 2670198092Srdivacky 2671193326Sed // Emit the @finally block. 2672193326Sed CGF.EmitBlock(FinallyBlock); 2673193326Sed llvm::Value* CallTryExit = CGF.Builder.CreateLoad(CallTryExitPtr, "tmp"); 2674198092Srdivacky 2675193326Sed CGF.Builder.CreateCondBr(CallTryExit, FinallyExit, FinallyNoExit); 2676198092Srdivacky 2677193326Sed CGF.EmitBlock(FinallyExit); 2678193326Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData); 2679193326Sed 2680193326Sed CGF.EmitBlock(FinallyNoExit); 2681193326Sed if (isTry) { 2682198092Srdivacky if (const ObjCAtFinallyStmt* FinallyStmt = 2683198092Srdivacky cast<ObjCAtTryStmt>(S).getFinallyStmt()) 2684193326Sed CGF.EmitStmt(FinallyStmt->getFinallyBody()); 2685193326Sed } else { 2686193326Sed // Emit objc_sync_exit(expr); as finally's sole statement for 2687193326Sed // @synchronized. 2688193326Sed CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg); 2689193326Sed } 2690193326Sed 2691193326Sed // Emit the switch block 2692193326Sed if (Info.SwitchBlock) 2693193326Sed CGF.EmitBlock(Info.SwitchBlock); 2694193326Sed if (Info.EndBlock) 2695193326Sed CGF.EmitBlock(Info.EndBlock); 2696198092Srdivacky 2697193326Sed CGF.EmitBlock(FinallyRethrow); 2698198092Srdivacky CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), 2699193326Sed CGF.Builder.CreateLoad(RethrowPtr)); 2700193326Sed CGF.Builder.CreateUnreachable(); 2701198092Srdivacky 2702193326Sed CGF.EmitBlock(FinallyEnd); 2703193326Sed} 2704193326Sed 2705193326Sedvoid CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 2706193326Sed const ObjCAtThrowStmt &S) { 2707193326Sed llvm::Value *ExceptionAsObject; 2708198092Srdivacky 2709193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 2710193326Sed llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr); 2711198092Srdivacky ExceptionAsObject = 2712193326Sed CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp"); 2713193326Sed } else { 2714198092Srdivacky assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && 2715193326Sed "Unexpected rethrow outside @catch block."); 2716193326Sed ExceptionAsObject = CGF.ObjCEHValueStack.back(); 2717193326Sed } 2718198092Srdivacky 2719193326Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject); 2720193326Sed CGF.Builder.CreateUnreachable(); 2721193326Sed 2722193326Sed // Clear the insertion point to indicate we are in unreachable code. 2723193326Sed CGF.Builder.ClearInsertionPoint(); 2724193326Sed} 2725193326Sed 2726193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak 2727193326Sed/// object: objc_read_weak (id *src) 2728193326Sed/// 2729193326Sedllvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 2730198092Srdivacky llvm::Value *AddrWeakObj) { 2731193326Sed const llvm::Type* DestTy = 2732198092Srdivacky cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); 2733198092Srdivacky AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, 2734198092Srdivacky ObjCTypes.PtrObjectPtrTy); 2735193326Sed llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(), 2736193326Sed AddrWeakObj, "weakread"); 2737193326Sed read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); 2738193326Sed return read_weak; 2739193326Sed} 2740193326Sed 2741193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. 2742193326Sed/// objc_assign_weak (id src, id *dst) 2743193326Sed/// 2744193326Sedvoid CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 2745198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2746193326Sed const llvm::Type * SrcTy = src->getType(); 2747193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 2748193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 2749193326Sed assert(Size <= 8 && "does not support size > 8"); 2750193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 2751198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 2752193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 2753193326Sed } 2754193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 2755193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 2756193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(), 2757193326Sed src, dst, "weakassign"); 2758193326Sed return; 2759193326Sed} 2760193326Sed 2761193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. 2762193326Sed/// objc_assign_global (id src, id *dst) 2763193326Sed/// 2764193326Sedvoid CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 2765198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2766193326Sed const llvm::Type * SrcTy = src->getType(); 2767193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 2768193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 2769193326Sed assert(Size <= 8 && "does not support size > 8"); 2770193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 2771198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 2772193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 2773193326Sed } 2774193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 2775193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 2776193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(), 2777193326Sed src, dst, "globalassign"); 2778193326Sed return; 2779193326Sed} 2780193326Sed 2781193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. 2782198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset) 2783193326Sed/// 2784193326Sedvoid CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 2785198092Srdivacky llvm::Value *src, llvm::Value *dst, 2786198092Srdivacky llvm::Value *ivarOffset) { 2787198092Srdivacky assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL"); 2788193326Sed const llvm::Type * SrcTy = src->getType(); 2789193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 2790193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 2791193326Sed assert(Size <= 8 && "does not support size > 8"); 2792193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 2793198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 2794193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 2795193326Sed } 2796193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 2797193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 2798198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(), 2799198092Srdivacky src, dst, ivarOffset); 2800193326Sed return; 2801193326Sed} 2802193326Sed 2803193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. 2804193326Sed/// objc_assign_strongCast (id src, id *dst) 2805193326Sed/// 2806193326Sedvoid CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 2807198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2808193326Sed const llvm::Type * SrcTy = src->getType(); 2809193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 2810193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 2811193326Sed assert(Size <= 8 && "does not support size > 8"); 2812193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 2813198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 2814193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 2815193326Sed } 2816193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 2817193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 2818193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(), 2819193326Sed src, dst, "weakassign"); 2820193326Sed return; 2821193326Sed} 2822193326Sed 2823198092Srdivackyvoid CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 2824198092Srdivacky llvm::Value *DestPtr, 2825198092Srdivacky llvm::Value *SrcPtr, 2826198092Srdivacky QualType Ty) { 2827198092Srdivacky // Get size info for this aggregate. 2828198092Srdivacky std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty); 2829198092Srdivacky unsigned long size = TypeInfo.first/8; 2830198092Srdivacky SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); 2831198092Srdivacky DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); 2832198092Srdivacky llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size); 2833198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(), 2834198092Srdivacky DestPtr, SrcPtr, N); 2835198092Srdivacky return; 2836198092Srdivacky} 2837198092Srdivacky 2838193326Sed/// EmitObjCValueForIvar - Code Gen for ivar reference. 2839193326Sed/// 2840193326SedLValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 2841193326Sed QualType ObjectTy, 2842193326Sed llvm::Value *BaseValue, 2843193326Sed const ObjCIvarDecl *Ivar, 2844193326Sed unsigned CVRQualifiers) { 2845198092Srdivacky const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); 2846193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 2847193326Sed EmitIvarOffset(CGF, ID, Ivar)); 2848193326Sed} 2849193326Sed 2850193326Sedllvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 2851193326Sed const ObjCInterfaceDecl *Interface, 2852193326Sed const ObjCIvarDecl *Ivar) { 2853193326Sed uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar); 2854193326Sed return llvm::ConstantInt::get( 2855198092Srdivacky CGM.getTypes().ConvertType(CGM.getContext().LongTy), 2856198092Srdivacky Offset); 2857193326Sed} 2858193326Sed 2859193326Sed/* *** Private Interface *** */ 2860193326Sed 2861193326Sed/// EmitImageInfo - Emit the image info marker used to encode some module 2862193326Sed/// level information. 2863193326Sed/// 2864193326Sed/// See: <rdr://4810609&4810587&4810587> 2865193326Sed/// struct IMAGE_INFO { 2866193326Sed/// unsigned version; 2867193326Sed/// unsigned flags; 2868193326Sed/// }; 2869193326Sedenum ImageInfoFlags { 2870193326Sed eImageInfo_FixAndContinue = (1 << 0), // FIXME: Not sure what 2871193326Sed // this implies. 2872198092Srdivacky eImageInfo_GarbageCollected = (1 << 1), 2873198092Srdivacky eImageInfo_GCOnly = (1 << 2), 2874193326Sed eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set. 2875193326Sed 2876193326Sed // A flag indicating that the module has no instances of an 2877193326Sed // @synthesize of a superclass variable. <rdar://problem/6803242> 2878193326Sed eImageInfo_CorrectedSynthesize = (1 << 4) 2879193326Sed}; 2880193326Sed 2881193326Sedvoid CGObjCMac::EmitImageInfo() { 2882193326Sed unsigned version = 0; // Version is unused? 2883193326Sed unsigned flags = 0; 2884193326Sed 2885193326Sed // FIXME: Fix and continue? 2886193326Sed if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) 2887193326Sed flags |= eImageInfo_GarbageCollected; 2888193326Sed if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) 2889193326Sed flags |= eImageInfo_GCOnly; 2890198092Srdivacky 2891193326Sed // We never allow @synthesize of a superclass property. 2892193326Sed flags |= eImageInfo_CorrectedSynthesize; 2893193326Sed 2894193326Sed // Emitted as int[2]; 2895193326Sed llvm::Constant *values[2] = { 2896198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), version), 2897198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), flags) 2898193326Sed }; 2899198092Srdivacky llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext), 2); 2900193326Sed 2901193326Sed const char *Section; 2902193326Sed if (ObjCABI == 1) 2903193326Sed Section = "__OBJC, __image_info,regular"; 2904193326Sed else 2905193326Sed Section = "__DATA, __objc_imageinfo, regular, no_dead_strip"; 2906198092Srdivacky llvm::GlobalVariable *GV = 2907193326Sed CreateMetadataVar("\01L_OBJC_IMAGE_INFO", 2908193326Sed llvm::ConstantArray::get(AT, values, 2), 2909193326Sed Section, 2910193326Sed 0, 2911193326Sed true); 2912193326Sed GV->setConstant(true); 2913193326Sed} 2914193326Sed 2915193326Sed 2916193326Sed// struct objc_module { 2917193326Sed// unsigned long version; 2918193326Sed// unsigned long size; 2919193326Sed// const char *name; 2920193326Sed// Symtab symtab; 2921193326Sed// }; 2922193326Sed 2923193326Sed// FIXME: Get from somewhere 2924193326Sedstatic const int ModuleVersion = 7; 2925193326Sed 2926193326Sedvoid CGObjCMac::EmitModuleInfo() { 2927193326Sed uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy); 2928198092Srdivacky 2929193326Sed std::vector<llvm::Constant*> Values(4); 2930193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion); 2931193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 2932193326Sed // This used to be the filename, now it is unused. <rdr://4327263> 2933193326Sed Values[2] = GetClassName(&CGM.getContext().Idents.get("")); 2934193326Sed Values[3] = EmitModuleSymbols(); 2935198092Srdivacky CreateMetadataVar("\01L_OBJC_MODULES", 2936193326Sed llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values), 2937193326Sed "__OBJC,__module_info,regular,no_dead_strip", 2938193326Sed 4, true); 2939193326Sed} 2940193326Sed 2941193326Sedllvm::Constant *CGObjCMac::EmitModuleSymbols() { 2942193326Sed unsigned NumClasses = DefinedClasses.size(); 2943193326Sed unsigned NumCategories = DefinedCategories.size(); 2944193326Sed 2945193326Sed // Return null if no symbols were defined. 2946193326Sed if (!NumClasses && !NumCategories) 2947193326Sed return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy); 2948193326Sed 2949193326Sed std::vector<llvm::Constant*> Values(5); 2950193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 2951193326Sed Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy); 2952193326Sed Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses); 2953193326Sed Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories); 2954193326Sed 2955193326Sed // The runtime expects exactly the list of defined classes followed 2956193326Sed // by the list of defined categories, in a single array. 2957193326Sed std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories); 2958193326Sed for (unsigned i=0; i<NumClasses; i++) 2959193326Sed Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i], 2960193326Sed ObjCTypes.Int8PtrTy); 2961193326Sed for (unsigned i=0; i<NumCategories; i++) 2962198092Srdivacky Symbols[NumClasses + i] = 2963193326Sed llvm::ConstantExpr::getBitCast(DefinedCategories[i], 2964193326Sed ObjCTypes.Int8PtrTy); 2965193326Sed 2966198092Srdivacky Values[4] = 2967193326Sed llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 2968193326Sed NumClasses + NumCategories), 2969193326Sed Symbols); 2970193326Sed 2971198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 2972193326Sed 2973193326Sed llvm::GlobalVariable *GV = 2974193326Sed CreateMetadataVar("\01L_OBJC_SYMBOLS", Init, 2975193326Sed "__OBJC,__symbols,regular,no_dead_strip", 2976193326Sed 4, true); 2977193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy); 2978193326Sed} 2979193326Sed 2980198092Srdivackyllvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder, 2981193326Sed const ObjCInterfaceDecl *ID) { 2982193326Sed LazySymbols.insert(ID->getIdentifier()); 2983193326Sed 2984193326Sed llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()]; 2985198092Srdivacky 2986193326Sed if (!Entry) { 2987198092Srdivacky llvm::Constant *Casted = 2988193326Sed llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()), 2989193326Sed ObjCTypes.ClassPtrTy); 2990198092Srdivacky Entry = 2991193326Sed CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted, 2992193326Sed "__OBJC,__cls_refs,literal_pointers,no_dead_strip", 2993193326Sed 4, true); 2994193326Sed } 2995193326Sed 2996193326Sed return Builder.CreateLoad(Entry, false, "tmp"); 2997193326Sed} 2998193326Sed 2999193326Sedllvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) { 3000193326Sed llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; 3001198092Srdivacky 3002193326Sed if (!Entry) { 3003198092Srdivacky llvm::Constant *Casted = 3004193326Sed llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), 3005193326Sed ObjCTypes.SelectorPtrTy); 3006198092Srdivacky Entry = 3007193326Sed CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted, 3008193326Sed "__OBJC,__message_refs,literal_pointers,no_dead_strip", 3009193326Sed 4, true); 3010193326Sed } 3011193326Sed 3012193326Sed return Builder.CreateLoad(Entry, false, "tmp"); 3013193326Sed} 3014193326Sed 3015193326Sedllvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) { 3016193326Sed llvm::GlobalVariable *&Entry = ClassNames[Ident]; 3017193326Sed 3018193326Sed if (!Entry) 3019198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", 3020198398Srdivacky llvm::ConstantArray::get(VMContext, 3021198398Srdivacky Ident->getNameStart()), 3022193326Sed "__TEXT,__cstring,cstring_literals", 3023193326Sed 1, true); 3024193326Sed 3025198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3026193326Sed} 3027193326Sed 3028193326Sed/// GetIvarLayoutName - Returns a unique constant for the given 3029193326Sed/// ivar layout bitmap. 3030193326Sedllvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, 3031198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 3032193326Sed return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 3033193326Sed} 3034193326Sed 3035198092Srdivackystatic Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) { 3036193326Sed if (FQT.isObjCGCStrong()) 3037198092Srdivacky return Qualifiers::Strong; 3038193326Sed 3039193326Sed if (FQT.isObjCGCWeak()) 3040198092Srdivacky return Qualifiers::Weak; 3041193326Sed 3042198092Srdivacky if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) 3043198092Srdivacky return Qualifiers::Strong; 3044193326Sed 3045198092Srdivacky if (const PointerType *PT = FQT->getAs<PointerType>()) 3046193326Sed return GetGCAttrTypeForType(Ctx, PT->getPointeeType()); 3047193326Sed 3048198092Srdivacky return Qualifiers::GCNone; 3049193326Sed} 3050193326Sed 3051193326Sedvoid CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT, 3052198092Srdivacky unsigned int BytePos, 3053193326Sed bool ForStrongLayout, 3054193326Sed bool &HasUnion) { 3055193326Sed const RecordDecl *RD = RT->getDecl(); 3056193326Sed // FIXME - Use iterator. 3057195341Sed llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end()); 3058193326Sed const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); 3059198092Srdivacky const llvm::StructLayout *RecLayout = 3060193326Sed CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty)); 3061198092Srdivacky 3062193326Sed BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos, 3063193326Sed ForStrongLayout, HasUnion); 3064193326Sed} 3065193326Sed 3066193326Sedvoid CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, 3067198092Srdivacky const llvm::StructLayout *Layout, 3068198092Srdivacky const RecordDecl *RD, 3069193326Sed const llvm::SmallVectorImpl<FieldDecl*> &RecFields, 3070198092Srdivacky unsigned int BytePos, bool ForStrongLayout, 3071198092Srdivacky bool &HasUnion) { 3072193326Sed bool IsUnion = (RD && RD->isUnion()); 3073193326Sed uint64_t MaxUnionIvarSize = 0; 3074193326Sed uint64_t MaxSkippedUnionIvarSize = 0; 3075193326Sed FieldDecl *MaxField = 0; 3076193326Sed FieldDecl *MaxSkippedField = 0; 3077193326Sed FieldDecl *LastFieldBitfield = 0; 3078193326Sed uint64_t MaxFieldOffset = 0; 3079193326Sed uint64_t MaxSkippedFieldOffset = 0; 3080193326Sed uint64_t LastBitfieldOffset = 0; 3081198092Srdivacky 3082193326Sed if (RecFields.empty()) 3083193326Sed return; 3084193326Sed unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0); 3085193326Sed unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth(); 3086193326Sed 3087193326Sed for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { 3088193326Sed FieldDecl *Field = RecFields[i]; 3089193326Sed uint64_t FieldOffset; 3090198092Srdivacky if (RD) { 3091198092Srdivacky if (Field->isBitField()) { 3092198092Srdivacky CodeGenTypes::BitFieldInfo Info = CGM.getTypes().getBitFieldInfo(Field); 3093198092Srdivacky 3094198092Srdivacky const llvm::Type *Ty = 3095198092Srdivacky CGM.getTypes().ConvertTypeForMemRecursive(Field->getType()); 3096198092Srdivacky uint64_t TypeSize = 3097198092Srdivacky CGM.getTypes().getTargetData().getTypeAllocSize(Ty); 3098198092Srdivacky FieldOffset = Info.FieldNo * TypeSize; 3099198092Srdivacky } else 3100198092Srdivacky FieldOffset = 3101198092Srdivacky Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field)); 3102198092Srdivacky } else 3103193326Sed FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)); 3104193326Sed 3105193326Sed // Skip over unnamed or bitfields 3106193326Sed if (!Field->getIdentifier() || Field->isBitField()) { 3107193326Sed LastFieldBitfield = Field; 3108193326Sed LastBitfieldOffset = FieldOffset; 3109193326Sed continue; 3110193326Sed } 3111193326Sed 3112193326Sed LastFieldBitfield = 0; 3113193326Sed QualType FQT = Field->getType(); 3114193326Sed if (FQT->isRecordType() || FQT->isUnionType()) { 3115193326Sed if (FQT->isUnionType()) 3116193326Sed HasUnion = true; 3117193326Sed 3118198092Srdivacky BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(), 3119193326Sed BytePos + FieldOffset, 3120193326Sed ForStrongLayout, HasUnion); 3121193326Sed continue; 3122193326Sed } 3123198092Srdivacky 3124193326Sed if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 3125198092Srdivacky const ConstantArrayType *CArray = 3126193326Sed dyn_cast_or_null<ConstantArrayType>(Array); 3127193326Sed uint64_t ElCount = CArray->getSize().getZExtValue(); 3128193326Sed assert(CArray && "only array with known element size is supported"); 3129193326Sed FQT = CArray->getElementType(); 3130193326Sed while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 3131193326Sed const ConstantArrayType *CArray = 3132193326Sed dyn_cast_or_null<ConstantArrayType>(Array); 3133193326Sed ElCount *= CArray->getSize().getZExtValue(); 3134193326Sed FQT = CArray->getElementType(); 3135193326Sed } 3136198092Srdivacky 3137198092Srdivacky assert(!FQT->isUnionType() && 3138193326Sed "layout for array of unions not supported"); 3139193326Sed if (FQT->isRecordType()) { 3140193326Sed int OldIndex = IvarsInfo.size() - 1; 3141193326Sed int OldSkIndex = SkipIvars.size() -1; 3142198092Srdivacky 3143198092Srdivacky const RecordType *RT = FQT->getAs<RecordType>(); 3144193326Sed BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset, 3145193326Sed ForStrongLayout, HasUnion); 3146198092Srdivacky 3147193326Sed // Replicate layout information for each array element. Note that 3148193326Sed // one element is already done. 3149193326Sed uint64_t ElIx = 1; 3150198092Srdivacky for (int FirstIndex = IvarsInfo.size() - 1, 3151198092Srdivacky FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) { 3152193326Sed uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits; 3153193326Sed for (int i = OldIndex+1; i <= FirstIndex; ++i) 3154193326Sed IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx, 3155193326Sed IvarsInfo[i].ivar_size)); 3156193326Sed for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i) 3157193326Sed SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx, 3158193326Sed SkipIvars[i].ivar_size)); 3159193326Sed } 3160193326Sed continue; 3161193326Sed } 3162193326Sed } 3163193326Sed // At this point, we are done with Record/Union and array there of. 3164193326Sed // For other arrays we are down to its element type. 3165198092Srdivacky Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT); 3166193326Sed 3167193326Sed unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType()); 3168198092Srdivacky if ((ForStrongLayout && GCAttr == Qualifiers::Strong) 3169198092Srdivacky || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) { 3170193326Sed if (IsUnion) { 3171193326Sed uint64_t UnionIvarSize = FieldSize / WordSizeInBits; 3172193326Sed if (UnionIvarSize > MaxUnionIvarSize) { 3173193326Sed MaxUnionIvarSize = UnionIvarSize; 3174193326Sed MaxField = Field; 3175193326Sed MaxFieldOffset = FieldOffset; 3176193326Sed } 3177193326Sed } else { 3178193326Sed IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset, 3179193326Sed FieldSize / WordSizeInBits)); 3180193326Sed } 3181198092Srdivacky } else if ((ForStrongLayout && 3182198092Srdivacky (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)) 3183198092Srdivacky || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) { 3184193326Sed if (IsUnion) { 3185193326Sed // FIXME: Why the asymmetry? We divide by word size in bits on other 3186193326Sed // side. 3187193326Sed uint64_t UnionIvarSize = FieldSize; 3188193326Sed if (UnionIvarSize > MaxSkippedUnionIvarSize) { 3189193326Sed MaxSkippedUnionIvarSize = UnionIvarSize; 3190193326Sed MaxSkippedField = Field; 3191193326Sed MaxSkippedFieldOffset = FieldOffset; 3192193326Sed } 3193193326Sed } else { 3194193326Sed // FIXME: Why the asymmetry, we divide by byte size in bits here? 3195193326Sed SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset, 3196193326Sed FieldSize / ByteSizeInBits)); 3197193326Sed } 3198193326Sed } 3199193326Sed } 3200193326Sed 3201193326Sed if (LastFieldBitfield) { 3202193326Sed // Last field was a bitfield. Must update skip info. 3203193326Sed Expr *BitWidth = LastFieldBitfield->getBitWidth(); 3204193326Sed uint64_t BitFieldSize = 3205193326Sed BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); 3206193326Sed GC_IVAR skivar; 3207193326Sed skivar.ivar_bytepos = BytePos + LastBitfieldOffset; 3208198092Srdivacky skivar.ivar_size = (BitFieldSize / ByteSizeInBits) 3209198092Srdivacky + ((BitFieldSize % ByteSizeInBits) != 0); 3210198092Srdivacky SkipIvars.push_back(skivar); 3211193326Sed } 3212198092Srdivacky 3213193326Sed if (MaxField) 3214198092Srdivacky IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset, 3215193326Sed MaxUnionIvarSize)); 3216193326Sed if (MaxSkippedField) 3217193326Sed SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset, 3218193326Sed MaxSkippedUnionIvarSize)); 3219193326Sed} 3220193326Sed 3221193326Sed/// BuildIvarLayout - Builds ivar layout bitmap for the class 3222193326Sed/// implementation for the __strong or __weak case. 3223198092Srdivacky/// The layout map displays which words in ivar list must be skipped 3224198092Srdivacky/// and which must be scanned by GC (see below). String is built of bytes. 3225198092Srdivacky/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count 3226193326Sed/// of words to skip and right nibble is count of words to scan. So, each 3227198092Srdivacky/// nibble represents up to 15 workds to skip or scan. Skipping the rest is 3228193326Sed/// represented by a 0x00 byte which also ends the string. 3229193326Sed/// 1. when ForStrongLayout is true, following ivars are scanned: 3230193326Sed/// - id, Class 3231193326Sed/// - object * 3232193326Sed/// - __strong anything 3233198092Srdivacky/// 3234193326Sed/// 2. When ForStrongLayout is false, following ivars are scanned: 3235193326Sed/// - __weak anything 3236193326Sed/// 3237193326Sedllvm::Constant *CGObjCCommonMac::BuildIvarLayout( 3238198092Srdivacky const ObjCImplementationDecl *OMD, 3239198092Srdivacky bool ForStrongLayout) { 3240193326Sed bool hasUnion = false; 3241198092Srdivacky 3242193326Sed unsigned int WordsToScan, WordsToSkip; 3243198092Srdivacky const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext); 3244193326Sed if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) 3245193326Sed return llvm::Constant::getNullValue(PtrTy); 3246198092Srdivacky 3247193326Sed llvm::SmallVector<FieldDecl*, 32> RecFields; 3248193326Sed const ObjCInterfaceDecl *OI = OMD->getClassInterface(); 3249193326Sed CGM.getContext().CollectObjCIvars(OI, RecFields); 3250198092Srdivacky 3251193326Sed // Add this implementations synthesized ivars. 3252193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; 3253193326Sed CGM.getContext().CollectSynthesizedIvars(OI, Ivars); 3254193326Sed for (unsigned k = 0, e = Ivars.size(); k != e; ++k) 3255193326Sed RecFields.push_back(cast<FieldDecl>(Ivars[k])); 3256198092Srdivacky 3257193326Sed if (RecFields.empty()) 3258193326Sed return llvm::Constant::getNullValue(PtrTy); 3259198092Srdivacky 3260198092Srdivacky SkipIvars.clear(); 3261193326Sed IvarsInfo.clear(); 3262198092Srdivacky 3263193326Sed BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion); 3264193326Sed if (IvarsInfo.empty()) 3265193326Sed return llvm::Constant::getNullValue(PtrTy); 3266198092Srdivacky 3267193326Sed // Sort on byte position in case we encounterred a union nested in 3268193326Sed // the ivar list. 3269193326Sed if (hasUnion && !IvarsInfo.empty()) 3270193326Sed std::sort(IvarsInfo.begin(), IvarsInfo.end()); 3271193326Sed if (hasUnion && !SkipIvars.empty()) 3272193326Sed std::sort(SkipIvars.begin(), SkipIvars.end()); 3273198092Srdivacky 3274193326Sed // Build the string of skip/scan nibbles 3275193326Sed llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars; 3276198092Srdivacky unsigned int WordSize = 3277193326Sed CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy); 3278193326Sed if (IvarsInfo[0].ivar_bytepos == 0) { 3279193326Sed WordsToSkip = 0; 3280193326Sed WordsToScan = IvarsInfo[0].ivar_size; 3281193326Sed } else { 3282193326Sed WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize; 3283193326Sed WordsToScan = IvarsInfo[0].ivar_size; 3284193326Sed } 3285193326Sed for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) { 3286198092Srdivacky unsigned int TailPrevGCObjC = 3287193326Sed IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize; 3288193326Sed if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) { 3289193326Sed // consecutive 'scanned' object pointers. 3290193326Sed WordsToScan += IvarsInfo[i].ivar_size; 3291193326Sed } else { 3292193326Sed // Skip over 'gc'able object pointer which lay over each other. 3293193326Sed if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos) 3294193326Sed continue; 3295193326Sed // Must skip over 1 or more words. We save current skip/scan values 3296193326Sed // and start a new pair. 3297193326Sed SKIP_SCAN SkScan; 3298193326Sed SkScan.skip = WordsToSkip; 3299193326Sed SkScan.scan = WordsToScan; 3300193326Sed SkipScanIvars.push_back(SkScan); 3301198092Srdivacky 3302193326Sed // Skip the hole. 3303193326Sed SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize; 3304193326Sed SkScan.scan = 0; 3305193326Sed SkipScanIvars.push_back(SkScan); 3306193326Sed WordsToSkip = 0; 3307193326Sed WordsToScan = IvarsInfo[i].ivar_size; 3308193326Sed } 3309193326Sed } 3310193326Sed if (WordsToScan > 0) { 3311193326Sed SKIP_SCAN SkScan; 3312193326Sed SkScan.skip = WordsToSkip; 3313193326Sed SkScan.scan = WordsToScan; 3314193326Sed SkipScanIvars.push_back(SkScan); 3315193326Sed } 3316198092Srdivacky 3317193326Sed bool BytesSkipped = false; 3318193326Sed if (!SkipIvars.empty()) { 3319193326Sed unsigned int LastIndex = SkipIvars.size()-1; 3320198092Srdivacky int LastByteSkipped = 3321198092Srdivacky SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size; 3322193326Sed LastIndex = IvarsInfo.size()-1; 3323198092Srdivacky int LastByteScanned = 3324198092Srdivacky IvarsInfo[LastIndex].ivar_bytepos + 3325198092Srdivacky IvarsInfo[LastIndex].ivar_size * WordSize; 3326193326Sed BytesSkipped = (LastByteSkipped > LastByteScanned); 3327193326Sed // Compute number of bytes to skip at the tail end of the last ivar scanned. 3328193326Sed if (BytesSkipped) { 3329193326Sed unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize; 3330193326Sed SKIP_SCAN SkScan; 3331193326Sed SkScan.skip = TotalWords - (LastByteScanned/WordSize); 3332193326Sed SkScan.scan = 0; 3333193326Sed SkipScanIvars.push_back(SkScan); 3334193326Sed } 3335193326Sed } 3336193326Sed // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced 3337193326Sed // as 0xMN. 3338193326Sed int SkipScan = SkipScanIvars.size()-1; 3339193326Sed for (int i = 0; i <= SkipScan; i++) { 3340193326Sed if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0 3341193326Sed && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) { 3342193326Sed // 0xM0 followed by 0x0N detected. 3343193326Sed SkipScanIvars[i].scan = SkipScanIvars[i+1].scan; 3344193326Sed for (int j = i+1; j < SkipScan; j++) 3345193326Sed SkipScanIvars[j] = SkipScanIvars[j+1]; 3346193326Sed --SkipScan; 3347193326Sed } 3348193326Sed } 3349198092Srdivacky 3350193326Sed // Generate the string. 3351193326Sed std::string BitMap; 3352193326Sed for (int i = 0; i <= SkipScan; i++) { 3353193326Sed unsigned char byte; 3354193326Sed unsigned int skip_small = SkipScanIvars[i].skip % 0xf; 3355193326Sed unsigned int scan_small = SkipScanIvars[i].scan % 0xf; 3356193326Sed unsigned int skip_big = SkipScanIvars[i].skip / 0xf; 3357193326Sed unsigned int scan_big = SkipScanIvars[i].scan / 0xf; 3358193326Sed 3359193326Sed if (skip_small > 0 || skip_big > 0) 3360193326Sed BytesSkipped = true; 3361193326Sed // first skip big. 3362193326Sed for (unsigned int ix = 0; ix < skip_big; ix++) 3363193326Sed BitMap += (unsigned char)(0xf0); 3364198092Srdivacky 3365193326Sed // next (skip small, scan) 3366193326Sed if (skip_small) { 3367193326Sed byte = skip_small << 4; 3368193326Sed if (scan_big > 0) { 3369193326Sed byte |= 0xf; 3370193326Sed --scan_big; 3371193326Sed } else if (scan_small) { 3372193326Sed byte |= scan_small; 3373193326Sed scan_small = 0; 3374193326Sed } 3375193326Sed BitMap += byte; 3376193326Sed } 3377193326Sed // next scan big 3378193326Sed for (unsigned int ix = 0; ix < scan_big; ix++) 3379193326Sed BitMap += (unsigned char)(0x0f); 3380193326Sed // last scan small 3381193326Sed if (scan_small) { 3382193326Sed byte = scan_small; 3383193326Sed BitMap += byte; 3384193326Sed } 3385193326Sed } 3386193326Sed // null terminate string. 3387193326Sed unsigned char zero = 0; 3388193326Sed BitMap += zero; 3389198092Srdivacky 3390193326Sed if (CGM.getLangOptions().ObjCGCBitmapPrint) { 3391198092Srdivacky printf("\n%s ivar layout for class '%s': ", 3392193326Sed ForStrongLayout ? "strong" : "weak", 3393193326Sed OMD->getClassInterface()->getNameAsCString()); 3394193326Sed const unsigned char *s = (unsigned char*)BitMap.c_str(); 3395193326Sed for (unsigned i = 0; i < BitMap.size(); i++) 3396193326Sed if (!(s[i] & 0xf0)) 3397193326Sed printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); 3398193326Sed else 3399193326Sed printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); 3400193326Sed printf("\n"); 3401193326Sed } 3402198092Srdivacky llvm::GlobalVariable * Entry = 3403198092Srdivacky CreateMetadataVar("\01L_OBJC_CLASS_NAME_", 3404198092Srdivacky llvm::ConstantArray::get(VMContext, BitMap.c_str()), 3405198092Srdivacky "__TEXT,__cstring,cstring_literals", 3406198092Srdivacky 1, true); 3407198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3408193326Sed} 3409193326Sed 3410193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) { 3411193326Sed llvm::GlobalVariable *&Entry = MethodVarNames[Sel]; 3412193326Sed 3413193326Sed // FIXME: Avoid std::string copying. 3414193326Sed if (!Entry) 3415198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_", 3416198092Srdivacky llvm::ConstantArray::get(VMContext, Sel.getAsString()), 3417193326Sed "__TEXT,__cstring,cstring_literals", 3418193326Sed 1, true); 3419193326Sed 3420198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3421193326Sed} 3422193326Sed 3423193326Sed// FIXME: Merge into a single cstring creation function. 3424193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) { 3425193326Sed return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID)); 3426193326Sed} 3427193326Sed 3428193326Sed// FIXME: Merge into a single cstring creation function. 3429193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) { 3430193326Sed return GetMethodVarName(&CGM.getContext().Idents.get(Name)); 3431193326Sed} 3432193326Sed 3433193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) { 3434193326Sed std::string TypeStr; 3435193326Sed CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field); 3436193326Sed 3437193326Sed llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; 3438193326Sed 3439193326Sed if (!Entry) 3440193326Sed Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", 3441198092Srdivacky llvm::ConstantArray::get(VMContext, TypeStr), 3442193326Sed "__TEXT,__cstring,cstring_literals", 3443193326Sed 1, true); 3444198092Srdivacky 3445198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3446193326Sed} 3447193326Sed 3448193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) { 3449193326Sed std::string TypeStr; 3450193326Sed CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D), 3451193326Sed TypeStr); 3452193326Sed 3453193326Sed llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; 3454193326Sed 3455193326Sed if (!Entry) 3456193326Sed Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", 3457198092Srdivacky llvm::ConstantArray::get(VMContext, TypeStr), 3458193326Sed "__TEXT,__cstring,cstring_literals", 3459193326Sed 1, true); 3460193326Sed 3461198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3462193326Sed} 3463193326Sed 3464193326Sed// FIXME: Merge into a single cstring creation function. 3465193326Sedllvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) { 3466193326Sed llvm::GlobalVariable *&Entry = PropertyNames[Ident]; 3467198092Srdivacky 3468193326Sed if (!Entry) 3469198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_", 3470198398Srdivacky llvm::ConstantArray::get(VMContext, 3471198398Srdivacky Ident->getNameStart()), 3472193326Sed "__TEXT,__cstring,cstring_literals", 3473193326Sed 1, true); 3474193326Sed 3475198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3476193326Sed} 3477193326Sed 3478193326Sed// FIXME: Merge into a single cstring creation function. 3479193326Sed// FIXME: This Decl should be more precise. 3480193326Sedllvm::Constant * 3481198092SrdivackyCGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD, 3482198092Srdivacky const Decl *Container) { 3483193326Sed std::string TypeStr; 3484193326Sed CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr); 3485193326Sed return GetPropertyName(&CGM.getContext().Idents.get(TypeStr)); 3486193326Sed} 3487193326Sed 3488198092Srdivackyvoid CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D, 3489193326Sed const ObjCContainerDecl *CD, 3490198398Srdivacky llvm::SmallVectorImpl<char> &Name) { 3491198398Srdivacky llvm::raw_svector_ostream OS(Name); 3492193326Sed assert (CD && "Missing container decl in GetNameForMethod"); 3493198398Srdivacky OS << '\01' << (D->isInstanceMethod() ? '-' : '+') 3494198398Srdivacky << '[' << CD->getName(); 3495198092Srdivacky if (const ObjCCategoryImplDecl *CID = 3496198398Srdivacky dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) 3497198398Srdivacky OS << '(' << CID->getNameAsString() << ')'; 3498198398Srdivacky OS << ' ' << D->getSelector().getAsString() << ']'; 3499193326Sed} 3500193326Sed 3501193326Sedvoid CGObjCMac::FinishModule() { 3502193326Sed EmitModuleInfo(); 3503193326Sed 3504193326Sed // Emit the dummy bodies for any protocols which were referenced but 3505193326Sed // never defined. 3506198092Srdivacky for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator 3507198092Srdivacky I = Protocols.begin(), e = Protocols.end(); I != e; ++I) { 3508198092Srdivacky if (I->second->hasInitializer()) 3509193326Sed continue; 3510193326Sed 3511193326Sed std::vector<llvm::Constant*> Values(5); 3512193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); 3513198092Srdivacky Values[1] = GetClassName(I->first); 3514193326Sed Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 3515193326Sed Values[3] = Values[4] = 3516193326Sed llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); 3517198092Srdivacky I->second->setLinkage(llvm::GlobalValue::InternalLinkage); 3518198092Srdivacky I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, 3519193326Sed Values)); 3520198092Srdivacky CGM.AddUsedGlobal(I->second); 3521193326Sed } 3522193326Sed 3523193326Sed // Add assembler directives to add lazy undefined symbol references 3524193326Sed // for classes which are referenced but not defined. This is 3525193326Sed // important for correct linker interaction. 3526198092Srdivacky // 3527198092Srdivacky // FIXME: It would be nice if we had an LLVM construct for this. 3528198092Srdivacky if (!LazySymbols.empty() || !DefinedSymbols.empty()) { 3529198092Srdivacky llvm::SmallString<256> Asm; 3530198092Srdivacky Asm += CGM.getModule().getModuleInlineAsm(); 3531198092Srdivacky if (!Asm.empty() && Asm.back() != '\n') 3532198092Srdivacky Asm += '\n'; 3533193326Sed 3534198092Srdivacky llvm::raw_svector_ostream OS(Asm); 3535198092Srdivacky for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(), 3536198092Srdivacky e = LazySymbols.end(); I != e; ++I) 3537198092Srdivacky OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n"; 3538198092Srdivacky for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(), 3539198092Srdivacky e = DefinedSymbols.end(); I != e; ++I) 3540198092Srdivacky OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n" 3541198092Srdivacky << "\t.globl .objc_class_name_" << (*I)->getName() << "\n"; 3542198092Srdivacky 3543198092Srdivacky CGM.getModule().setModuleInlineAsm(OS.str()); 3544193326Sed } 3545193326Sed} 3546193326Sed 3547198092SrdivackyCGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm) 3548193326Sed : CGObjCCommonMac(cgm), 3549198092Srdivacky ObjCTypes(cgm) { 3550193326Sed ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL; 3551193326Sed ObjCABI = 2; 3552193326Sed} 3553193326Sed 3554193326Sed/* *** */ 3555193326Sed 3556193326SedObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) 3557198092Srdivacky : VMContext(cgm.getLLVMContext()), CGM(cgm) { 3558193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 3559193326Sed ASTContext &Ctx = CGM.getContext(); 3560198092Srdivacky 3561193326Sed ShortTy = Types.ConvertType(Ctx.ShortTy); 3562193326Sed IntTy = Types.ConvertType(Ctx.IntTy); 3563193326Sed LongTy = Types.ConvertType(Ctx.LongTy); 3564193326Sed LongLongTy = Types.ConvertType(Ctx.LongLongTy); 3565198092Srdivacky Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); 3566198092Srdivacky 3567193326Sed ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType()); 3568193326Sed PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy); 3569193326Sed SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType()); 3570198092Srdivacky 3571193326Sed // FIXME: It would be nice to unify this with the opaque type, so that the IR 3572193326Sed // comes out a bit cleaner. 3573193326Sed const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType()); 3574193326Sed ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T); 3575198092Srdivacky 3576193326Sed // I'm not sure I like this. The implicit coordination is a bit 3577193326Sed // gross. We should solve this in a reasonable fashion because this 3578193326Sed // is a pretty common task (match some runtime data structure with 3579193326Sed // an LLVM data structure). 3580198092Srdivacky 3581193326Sed // FIXME: This is leaked. 3582193326Sed // FIXME: Merge with rewriter code? 3583198092Srdivacky 3584193326Sed // struct _objc_super { 3585193326Sed // id self; 3586193326Sed // Class cls; 3587193326Sed // } 3588193326Sed RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0, 3589193326Sed SourceLocation(), 3590198092Srdivacky &Ctx.Idents.get("_objc_super")); 3591195341Sed RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 3592198092Srdivacky Ctx.getObjCIdType(), 0, 0, false)); 3593198092Srdivacky RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 3594198092Srdivacky Ctx.getObjCClassType(), 0, 0, false)); 3595193326Sed RD->completeDefinition(Ctx); 3596198092Srdivacky 3597193326Sed SuperCTy = Ctx.getTagDeclType(RD); 3598193326Sed SuperPtrCTy = Ctx.getPointerType(SuperCTy); 3599198092Srdivacky 3600193326Sed SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy)); 3601198092Srdivacky SuperPtrTy = llvm::PointerType::getUnqual(SuperTy); 3602198092Srdivacky 3603193326Sed // struct _prop_t { 3604193326Sed // char *name; 3605198092Srdivacky // char *attributes; 3606193326Sed // } 3607198092Srdivacky PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL); 3608198092Srdivacky CGM.getModule().addTypeName("struct._prop_t", 3609193326Sed PropertyTy); 3610198092Srdivacky 3611193326Sed // struct _prop_list_t { 3612193326Sed // uint32_t entsize; // sizeof(struct _prop_t) 3613193326Sed // uint32_t count_of_properties; 3614193326Sed // struct _prop_t prop_list[count_of_properties]; 3615193326Sed // } 3616198092Srdivacky PropertyListTy = llvm::StructType::get(VMContext, IntTy, 3617193326Sed IntTy, 3618193326Sed llvm::ArrayType::get(PropertyTy, 0), 3619193326Sed NULL); 3620198092Srdivacky CGM.getModule().addTypeName("struct._prop_list_t", 3621193326Sed PropertyListTy); 3622193326Sed // struct _prop_list_t * 3623193326Sed PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy); 3624198092Srdivacky 3625193326Sed // struct _objc_method { 3626193326Sed // SEL _cmd; 3627193326Sed // char *method_type; 3628193326Sed // char *_imp; 3629193326Sed // } 3630198092Srdivacky MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy, 3631193326Sed Int8PtrTy, 3632193326Sed Int8PtrTy, 3633193326Sed NULL); 3634193326Sed CGM.getModule().addTypeName("struct._objc_method", MethodTy); 3635198092Srdivacky 3636193326Sed // struct _objc_cache * 3637198092Srdivacky CacheTy = llvm::OpaqueType::get(VMContext); 3638193326Sed CGM.getModule().addTypeName("struct._objc_cache", CacheTy); 3639193326Sed CachePtrTy = llvm::PointerType::getUnqual(CacheTy); 3640193326Sed} 3641193326Sed 3642198092SrdivackyObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) 3643198092Srdivacky : ObjCCommonTypesHelper(cgm) { 3644193326Sed // struct _objc_method_description { 3645193326Sed // SEL name; 3646193326Sed // char *types; 3647193326Sed // } 3648198092Srdivacky MethodDescriptionTy = 3649198092Srdivacky llvm::StructType::get(VMContext, SelectorPtrTy, 3650193326Sed Int8PtrTy, 3651193326Sed NULL); 3652198092Srdivacky CGM.getModule().addTypeName("struct._objc_method_description", 3653193326Sed MethodDescriptionTy); 3654193326Sed 3655193326Sed // struct _objc_method_description_list { 3656193326Sed // int count; 3657193326Sed // struct _objc_method_description[1]; 3658193326Sed // } 3659198092Srdivacky MethodDescriptionListTy = 3660198092Srdivacky llvm::StructType::get(VMContext, IntTy, 3661193326Sed llvm::ArrayType::get(MethodDescriptionTy, 0), 3662193326Sed NULL); 3663198092Srdivacky CGM.getModule().addTypeName("struct._objc_method_description_list", 3664193326Sed MethodDescriptionListTy); 3665198092Srdivacky 3666193326Sed // struct _objc_method_description_list * 3667198092Srdivacky MethodDescriptionListPtrTy = 3668193326Sed llvm::PointerType::getUnqual(MethodDescriptionListTy); 3669193326Sed 3670193326Sed // Protocol description structures 3671193326Sed 3672193326Sed // struct _objc_protocol_extension { 3673193326Sed // uint32_t size; // sizeof(struct _objc_protocol_extension) 3674193326Sed // struct _objc_method_description_list *optional_instance_methods; 3675193326Sed // struct _objc_method_description_list *optional_class_methods; 3676193326Sed // struct _objc_property_list *instance_properties; 3677193326Sed // } 3678198092Srdivacky ProtocolExtensionTy = 3679198092Srdivacky llvm::StructType::get(VMContext, IntTy, 3680193326Sed MethodDescriptionListPtrTy, 3681193326Sed MethodDescriptionListPtrTy, 3682193326Sed PropertyListPtrTy, 3683193326Sed NULL); 3684198092Srdivacky CGM.getModule().addTypeName("struct._objc_protocol_extension", 3685193326Sed ProtocolExtensionTy); 3686198092Srdivacky 3687193326Sed // struct _objc_protocol_extension * 3688193326Sed ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy); 3689193326Sed 3690193326Sed // Handle recursive construction of Protocol and ProtocolList types 3691193326Sed 3692198092Srdivacky llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext); 3693198092Srdivacky llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext); 3694193326Sed 3695198092Srdivacky const llvm::Type *T = 3696198092Srdivacky llvm::StructType::get(VMContext, 3697198092Srdivacky llvm::PointerType::getUnqual(ProtocolListTyHolder), 3698193326Sed LongTy, 3699193326Sed llvm::ArrayType::get(ProtocolTyHolder, 0), 3700193326Sed NULL); 3701193326Sed cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T); 3702193326Sed 3703193326Sed // struct _objc_protocol { 3704193326Sed // struct _objc_protocol_extension *isa; 3705193326Sed // char *protocol_name; 3706193326Sed // struct _objc_protocol **_objc_protocol_list; 3707193326Sed // struct _objc_method_description_list *instance_methods; 3708193326Sed // struct _objc_method_description_list *class_methods; 3709193326Sed // } 3710198092Srdivacky T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy, 3711193326Sed Int8PtrTy, 3712193326Sed llvm::PointerType::getUnqual(ProtocolListTyHolder), 3713193326Sed MethodDescriptionListPtrTy, 3714193326Sed MethodDescriptionListPtrTy, 3715193326Sed NULL); 3716193326Sed cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T); 3717193326Sed 3718193326Sed ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get()); 3719198092Srdivacky CGM.getModule().addTypeName("struct._objc_protocol_list", 3720193326Sed ProtocolListTy); 3721193326Sed // struct _objc_protocol_list * 3722193326Sed ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy); 3723193326Sed 3724193326Sed ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get()); 3725193326Sed CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy); 3726193326Sed ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy); 3727193326Sed 3728193326Sed // Class description structures 3729193326Sed 3730193326Sed // struct _objc_ivar { 3731193326Sed // char *ivar_name; 3732193326Sed // char *ivar_type; 3733193326Sed // int ivar_offset; 3734193326Sed // } 3735198092Srdivacky IvarTy = llvm::StructType::get(VMContext, Int8PtrTy, 3736198092Srdivacky Int8PtrTy, 3737198092Srdivacky IntTy, 3738193326Sed NULL); 3739193326Sed CGM.getModule().addTypeName("struct._objc_ivar", IvarTy); 3740193326Sed 3741193326Sed // struct _objc_ivar_list * 3742198092Srdivacky IvarListTy = llvm::OpaqueType::get(VMContext); 3743193326Sed CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy); 3744193326Sed IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy); 3745193326Sed 3746193326Sed // struct _objc_method_list * 3747198092Srdivacky MethodListTy = llvm::OpaqueType::get(VMContext); 3748193326Sed CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy); 3749193326Sed MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy); 3750193326Sed 3751193326Sed // struct _objc_class_extension * 3752198092Srdivacky ClassExtensionTy = 3753198092Srdivacky llvm::StructType::get(VMContext, IntTy, 3754193326Sed Int8PtrTy, 3755193326Sed PropertyListPtrTy, 3756193326Sed NULL); 3757193326Sed CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy); 3758193326Sed ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy); 3759193326Sed 3760198092Srdivacky llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext); 3761193326Sed 3762193326Sed // struct _objc_class { 3763193326Sed // Class isa; 3764193326Sed // Class super_class; 3765193326Sed // char *name; 3766193326Sed // long version; 3767193326Sed // long info; 3768193326Sed // long instance_size; 3769193326Sed // struct _objc_ivar_list *ivars; 3770193326Sed // struct _objc_method_list *methods; 3771193326Sed // struct _objc_cache *cache; 3772193326Sed // struct _objc_protocol_list *protocols; 3773193326Sed // char *ivar_layout; 3774193326Sed // struct _objc_class_ext *ext; 3775193326Sed // }; 3776198092Srdivacky T = llvm::StructType::get(VMContext, 3777193326Sed llvm::PointerType::getUnqual(ClassTyHolder), 3778198092Srdivacky llvm::PointerType::getUnqual(ClassTyHolder), 3779193326Sed Int8PtrTy, 3780193326Sed LongTy, 3781193326Sed LongTy, 3782193326Sed LongTy, 3783193326Sed IvarListPtrTy, 3784193326Sed MethodListPtrTy, 3785193326Sed CachePtrTy, 3786193326Sed ProtocolListPtrTy, 3787193326Sed Int8PtrTy, 3788193326Sed ClassExtensionPtrTy, 3789193326Sed NULL); 3790193326Sed cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T); 3791198092Srdivacky 3792193326Sed ClassTy = cast<llvm::StructType>(ClassTyHolder.get()); 3793193326Sed CGM.getModule().addTypeName("struct._objc_class", ClassTy); 3794193326Sed ClassPtrTy = llvm::PointerType::getUnqual(ClassTy); 3795193326Sed 3796193326Sed // struct _objc_category { 3797193326Sed // char *category_name; 3798193326Sed // char *class_name; 3799193326Sed // struct _objc_method_list *instance_method; 3800193326Sed // struct _objc_method_list *class_method; 3801193326Sed // uint32_t size; // sizeof(struct _objc_category) 3802193326Sed // struct _objc_property_list *instance_properties;// category's @property 3803193326Sed // } 3804198092Srdivacky CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy, 3805193326Sed Int8PtrTy, 3806193326Sed MethodListPtrTy, 3807193326Sed MethodListPtrTy, 3808193326Sed ProtocolListPtrTy, 3809193326Sed IntTy, 3810193326Sed PropertyListPtrTy, 3811193326Sed NULL); 3812193326Sed CGM.getModule().addTypeName("struct._objc_category", CategoryTy); 3813193326Sed 3814193326Sed // Global metadata structures 3815193326Sed 3816193326Sed // struct _objc_symtab { 3817193326Sed // long sel_ref_cnt; 3818193326Sed // SEL *refs; 3819193326Sed // short cls_def_cnt; 3820193326Sed // short cat_def_cnt; 3821193326Sed // char *defs[cls_def_cnt + cat_def_cnt]; 3822193326Sed // } 3823198092Srdivacky SymtabTy = llvm::StructType::get(VMContext, LongTy, 3824193326Sed SelectorPtrTy, 3825193326Sed ShortTy, 3826193326Sed ShortTy, 3827193326Sed llvm::ArrayType::get(Int8PtrTy, 0), 3828193326Sed NULL); 3829193326Sed CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy); 3830193326Sed SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy); 3831193326Sed 3832193326Sed // struct _objc_module { 3833193326Sed // long version; 3834193326Sed // long size; // sizeof(struct _objc_module) 3835193326Sed // char *name; 3836193326Sed // struct _objc_symtab* symtab; 3837193326Sed // } 3838198092Srdivacky ModuleTy = 3839198092Srdivacky llvm::StructType::get(VMContext, LongTy, 3840193326Sed LongTy, 3841193326Sed Int8PtrTy, 3842193326Sed SymtabPtrTy, 3843193326Sed NULL); 3844193326Sed CGM.getModule().addTypeName("struct._objc_module", ModuleTy); 3845193326Sed 3846198092Srdivacky 3847193326Sed // FIXME: This is the size of the setjmp buffer and should be target 3848193326Sed // specific. 18 is what's used on 32-bit X86. 3849193326Sed uint64_t SetJmpBufferSize = 18; 3850198092Srdivacky 3851193326Sed // Exceptions 3852198092Srdivacky const llvm::Type *StackPtrTy = llvm::ArrayType::get( 3853198092Srdivacky llvm::Type::getInt8PtrTy(VMContext), 4); 3854198092Srdivacky 3855198092Srdivacky ExceptionDataTy = 3856198092Srdivacky llvm::StructType::get(VMContext, llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext), 3857198092Srdivacky SetJmpBufferSize), 3858193326Sed StackPtrTy, NULL); 3859198092Srdivacky CGM.getModule().addTypeName("struct._objc_exception_data", 3860193326Sed ExceptionDataTy); 3861193326Sed 3862193326Sed} 3863193326Sed 3864198092SrdivackyObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm) 3865198092Srdivacky : ObjCCommonTypesHelper(cgm) { 3866193326Sed // struct _method_list_t { 3867193326Sed // uint32_t entsize; // sizeof(struct _objc_method) 3868193326Sed // uint32_t method_count; 3869193326Sed // struct _objc_method method_list[method_count]; 3870193326Sed // } 3871198092Srdivacky MethodListnfABITy = llvm::StructType::get(VMContext, IntTy, 3872193326Sed IntTy, 3873193326Sed llvm::ArrayType::get(MethodTy, 0), 3874193326Sed NULL); 3875193326Sed CGM.getModule().addTypeName("struct.__method_list_t", 3876193326Sed MethodListnfABITy); 3877193326Sed // struct method_list_t * 3878193326Sed MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy); 3879198092Srdivacky 3880193326Sed // struct _protocol_t { 3881193326Sed // id isa; // NULL 3882193326Sed // const char * const protocol_name; 3883193326Sed // const struct _protocol_list_t * protocol_list; // super protocols 3884193326Sed // const struct method_list_t * const instance_methods; 3885193326Sed // const struct method_list_t * const class_methods; 3886193326Sed // const struct method_list_t *optionalInstanceMethods; 3887193326Sed // const struct method_list_t *optionalClassMethods; 3888193326Sed // const struct _prop_list_t * properties; 3889193326Sed // const uint32_t size; // sizeof(struct _protocol_t) 3890193326Sed // const uint32_t flags; // = 0 3891193326Sed // } 3892198092Srdivacky 3893193326Sed // Holder for struct _protocol_list_t * 3894198092Srdivacky llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext); 3895198092Srdivacky 3896198092Srdivacky ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy, 3897193326Sed Int8PtrTy, 3898193326Sed llvm::PointerType::getUnqual( 3899193326Sed ProtocolListTyHolder), 3900193326Sed MethodListnfABIPtrTy, 3901193326Sed MethodListnfABIPtrTy, 3902193326Sed MethodListnfABIPtrTy, 3903193326Sed MethodListnfABIPtrTy, 3904193326Sed PropertyListPtrTy, 3905193326Sed IntTy, 3906193326Sed IntTy, 3907193326Sed NULL); 3908193326Sed CGM.getModule().addTypeName("struct._protocol_t", 3909193326Sed ProtocolnfABITy); 3910193326Sed 3911193326Sed // struct _protocol_t* 3912193326Sed ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy); 3913198092Srdivacky 3914193326Sed // struct _protocol_list_t { 3915193326Sed // long protocol_count; // Note, this is 32/64 bit 3916193326Sed // struct _protocol_t *[protocol_count]; 3917193326Sed // } 3918198092Srdivacky ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy, 3919193326Sed llvm::ArrayType::get( 3920193326Sed ProtocolnfABIPtrTy, 0), 3921193326Sed NULL); 3922193326Sed CGM.getModule().addTypeName("struct._objc_protocol_list", 3923193326Sed ProtocolListnfABITy); 3924193326Sed cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo( 3925198092Srdivacky ProtocolListnfABITy); 3926198092Srdivacky 3927193326Sed // struct _objc_protocol_list* 3928193326Sed ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy); 3929198092Srdivacky 3930193326Sed // struct _ivar_t { 3931193326Sed // unsigned long int *offset; // pointer to ivar offset location 3932193326Sed // char *name; 3933193326Sed // char *type; 3934193326Sed // uint32_t alignment; 3935193326Sed // uint32_t size; 3936193326Sed // } 3937198092Srdivacky IvarnfABITy = llvm::StructType::get(VMContext, 3938198092Srdivacky llvm::PointerType::getUnqual(LongTy), 3939193326Sed Int8PtrTy, 3940193326Sed Int8PtrTy, 3941193326Sed IntTy, 3942193326Sed IntTy, 3943193326Sed NULL); 3944193326Sed CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy); 3945198092Srdivacky 3946193326Sed // struct _ivar_list_t { 3947193326Sed // uint32 entsize; // sizeof(struct _ivar_t) 3948193326Sed // uint32 count; 3949193326Sed // struct _iver_t list[count]; 3950193326Sed // } 3951198092Srdivacky IvarListnfABITy = llvm::StructType::get(VMContext, IntTy, 3952193326Sed IntTy, 3953193326Sed llvm::ArrayType::get( 3954198092Srdivacky IvarnfABITy, 0), 3955193326Sed NULL); 3956193326Sed CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy); 3957198092Srdivacky 3958193326Sed IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy); 3959198092Srdivacky 3960193326Sed // struct _class_ro_t { 3961193326Sed // uint32_t const flags; 3962193326Sed // uint32_t const instanceStart; 3963193326Sed // uint32_t const instanceSize; 3964193326Sed // uint32_t const reserved; // only when building for 64bit targets 3965193326Sed // const uint8_t * const ivarLayout; 3966193326Sed // const char *const name; 3967193326Sed // const struct _method_list_t * const baseMethods; 3968193326Sed // const struct _objc_protocol_list *const baseProtocols; 3969193326Sed // const struct _ivar_list_t *const ivars; 3970193326Sed // const uint8_t * const weakIvarLayout; 3971193326Sed // const struct _prop_list_t * const properties; 3972193326Sed // } 3973198092Srdivacky 3974193326Sed // FIXME. Add 'reserved' field in 64bit abi mode! 3975198092Srdivacky ClassRonfABITy = llvm::StructType::get(VMContext, IntTy, 3976193326Sed IntTy, 3977193326Sed IntTy, 3978193326Sed Int8PtrTy, 3979193326Sed Int8PtrTy, 3980193326Sed MethodListnfABIPtrTy, 3981193326Sed ProtocolListnfABIPtrTy, 3982193326Sed IvarListnfABIPtrTy, 3983193326Sed Int8PtrTy, 3984193326Sed PropertyListPtrTy, 3985193326Sed NULL); 3986193326Sed CGM.getModule().addTypeName("struct._class_ro_t", 3987193326Sed ClassRonfABITy); 3988198092Srdivacky 3989193326Sed // ImpnfABITy - LLVM for id (*)(id, SEL, ...) 3990193326Sed std::vector<const llvm::Type*> Params; 3991193326Sed Params.push_back(ObjectPtrTy); 3992193326Sed Params.push_back(SelectorPtrTy); 3993193326Sed ImpnfABITy = llvm::PointerType::getUnqual( 3994198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Params, false)); 3995198092Srdivacky 3996193326Sed // struct _class_t { 3997193326Sed // struct _class_t *isa; 3998193326Sed // struct _class_t * const superclass; 3999193326Sed // void *cache; 4000193326Sed // IMP *vtable; 4001193326Sed // struct class_ro_t *ro; 4002193326Sed // } 4003198092Srdivacky 4004198092Srdivacky llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext); 4005198092Srdivacky ClassnfABITy = 4006198092Srdivacky llvm::StructType::get(VMContext, 4007198092Srdivacky llvm::PointerType::getUnqual(ClassTyHolder), 4008198092Srdivacky llvm::PointerType::getUnqual(ClassTyHolder), 4009198092Srdivacky CachePtrTy, 4010198092Srdivacky llvm::PointerType::getUnqual(ImpnfABITy), 4011198092Srdivacky llvm::PointerType::getUnqual(ClassRonfABITy), 4012198092Srdivacky NULL); 4013193326Sed CGM.getModule().addTypeName("struct._class_t", ClassnfABITy); 4014193326Sed 4015193326Sed cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo( 4016198092Srdivacky ClassnfABITy); 4017198092Srdivacky 4018193326Sed // LLVM for struct _class_t * 4019193326Sed ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy); 4020198092Srdivacky 4021193326Sed // struct _category_t { 4022193326Sed // const char * const name; 4023193326Sed // struct _class_t *const cls; 4024193326Sed // const struct _method_list_t * const instance_methods; 4025193326Sed // const struct _method_list_t * const class_methods; 4026193326Sed // const struct _protocol_list_t * const protocols; 4027193326Sed // const struct _prop_list_t * const properties; 4028193326Sed // } 4029198092Srdivacky CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy, 4030193326Sed ClassnfABIPtrTy, 4031193326Sed MethodListnfABIPtrTy, 4032193326Sed MethodListnfABIPtrTy, 4033193326Sed ProtocolListnfABIPtrTy, 4034193326Sed PropertyListPtrTy, 4035193326Sed NULL); 4036193326Sed CGM.getModule().addTypeName("struct._category_t", CategorynfABITy); 4037198092Srdivacky 4038193326Sed // New types for nonfragile abi messaging. 4039193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 4040193326Sed ASTContext &Ctx = CGM.getContext(); 4041198092Srdivacky 4042193326Sed // MessageRefTy - LLVM for: 4043193326Sed // struct _message_ref_t { 4044193326Sed // IMP messenger; 4045193326Sed // SEL name; 4046193326Sed // }; 4047198092Srdivacky 4048193326Sed // First the clang type for struct _message_ref_t 4049193326Sed RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0, 4050193326Sed SourceLocation(), 4051193326Sed &Ctx.Idents.get("_message_ref_t")); 4052195341Sed RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 4053198092Srdivacky Ctx.VoidPtrTy, 0, 0, false)); 4054195341Sed RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 4055198092Srdivacky Ctx.getObjCSelType(), 0, 0, false)); 4056193326Sed RD->completeDefinition(Ctx); 4057198092Srdivacky 4058193326Sed MessageRefCTy = Ctx.getTagDeclType(RD); 4059193326Sed MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy); 4060193326Sed MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy)); 4061198092Srdivacky 4062193326Sed // MessageRefPtrTy - LLVM for struct _message_ref_t* 4063193326Sed MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy); 4064198092Srdivacky 4065193326Sed // SuperMessageRefTy - LLVM for: 4066193326Sed // struct _super_message_ref_t { 4067193326Sed // SUPER_IMP messenger; 4068193326Sed // SEL name; 4069193326Sed // }; 4070198092Srdivacky SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy, 4071193326Sed SelectorPtrTy, 4072193326Sed NULL); 4073193326Sed CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy); 4074198092Srdivacky 4075193326Sed // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* 4076198092Srdivacky SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); 4077193326Sed 4078198092Srdivacky 4079193326Sed // struct objc_typeinfo { 4080193326Sed // const void** vtable; // objc_ehtype_vtable + 2 4081193326Sed // const char* name; // c++ typeinfo string 4082193326Sed // Class cls; 4083193326Sed // }; 4084198092Srdivacky EHTypeTy = llvm::StructType::get(VMContext, 4085198092Srdivacky llvm::PointerType::getUnqual(Int8PtrTy), 4086193326Sed Int8PtrTy, 4087193326Sed ClassnfABIPtrTy, 4088193326Sed NULL); 4089193326Sed CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy); 4090193326Sed EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy); 4091193326Sed} 4092193326Sed 4093198092Srdivackyllvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() { 4094193326Sed FinishNonFragileABIModule(); 4095198092Srdivacky 4096193326Sed return NULL; 4097193326Sed} 4098193326Sed 4099198092Srdivackyvoid CGObjCNonFragileABIMac::AddModuleClassList(const 4100198092Srdivacky std::vector<llvm::GlobalValue*> 4101198092Srdivacky &Container, 4102193326Sed const char *SymbolName, 4103193326Sed const char *SectionName) { 4104193326Sed unsigned NumClasses = Container.size(); 4105198092Srdivacky 4106193326Sed if (!NumClasses) 4107193326Sed return; 4108198092Srdivacky 4109193326Sed std::vector<llvm::Constant*> Symbols(NumClasses); 4110193326Sed for (unsigned i=0; i<NumClasses; i++) 4111193326Sed Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i], 4112193326Sed ObjCTypes.Int8PtrTy); 4113198092Srdivacky llvm::Constant* Init = 4114193326Sed llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 4115193326Sed NumClasses), 4116193326Sed Symbols); 4117198092Srdivacky 4118193326Sed llvm::GlobalVariable *GV = 4119198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 4120193326Sed llvm::GlobalValue::InternalLinkage, 4121193326Sed Init, 4122198092Srdivacky SymbolName); 4123193326Sed GV->setAlignment(8); 4124193326Sed GV->setSection(SectionName); 4125198092Srdivacky CGM.AddUsedGlobal(GV); 4126193326Sed} 4127198092Srdivacky 4128193326Sedvoid CGObjCNonFragileABIMac::FinishNonFragileABIModule() { 4129193326Sed // nonfragile abi has no module definition. 4130198092Srdivacky 4131193326Sed // Build list of all implemented class addresses in array 4132193326Sed // L_OBJC_LABEL_CLASS_$. 4133198092Srdivacky AddModuleClassList(DefinedClasses, 4134193326Sed "\01L_OBJC_LABEL_CLASS_$", 4135193326Sed "__DATA, __objc_classlist, regular, no_dead_strip"); 4136199482Srdivacky 4137199482Srdivacky bool hasWeakImport = false; 4138199482Srdivacky for (unsigned i = 0; i < DefinedClasses.size(); i++) { 4139199482Srdivacky llvm::GlobalValue *IMPLGV = DefinedClasses[i]; 4140199482Srdivacky if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) 4141199482Srdivacky continue; 4142199482Srdivacky IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage); 4143199482Srdivacky hasWeakImport = true; 4144199482Srdivacky } 4145199482Srdivacky 4146199482Srdivacky if (hasWeakImport) { 4147199482Srdivacky for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) { 4148199482Srdivacky llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i]; 4149199482Srdivacky if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) 4150199482Srdivacky continue; 4151199482Srdivacky IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage); 4152199482Srdivacky } 4153199482Srdivacky } 4154199482Srdivacky 4155198092Srdivacky AddModuleClassList(DefinedNonLazyClasses, 4156193326Sed "\01L_OBJC_LABEL_NONLAZY_CLASS_$", 4157193326Sed "__DATA, __objc_nlclslist, regular, no_dead_strip"); 4158198092Srdivacky 4159193326Sed // Build list of all implemented category addresses in array 4160193326Sed // L_OBJC_LABEL_CATEGORY_$. 4161198092Srdivacky AddModuleClassList(DefinedCategories, 4162193326Sed "\01L_OBJC_LABEL_CATEGORY_$", 4163193326Sed "__DATA, __objc_catlist, regular, no_dead_strip"); 4164198092Srdivacky AddModuleClassList(DefinedNonLazyCategories, 4165193326Sed "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$", 4166193326Sed "__DATA, __objc_nlcatlist, regular, no_dead_strip"); 4167198092Srdivacky 4168193326Sed // static int L_OBJC_IMAGE_INFO[2] = { 0, flags }; 4169193326Sed // FIXME. flags can be 0 | 1 | 2 | 6. For now just use 0 4170193326Sed std::vector<llvm::Constant*> Values(2); 4171193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, 0); 4172193326Sed unsigned int flags = 0; 4173193326Sed // FIXME: Fix and continue? 4174193326Sed if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) 4175193326Sed flags |= eImageInfo_GarbageCollected; 4176193326Sed if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) 4177193326Sed flags |= eImageInfo_GCOnly; 4178193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags); 4179193326Sed llvm::Constant* Init = llvm::ConstantArray::get( 4180198092Srdivacky llvm::ArrayType::get(ObjCTypes.IntTy, 2), 4181198092Srdivacky Values); 4182193326Sed llvm::GlobalVariable *IMGV = 4183198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 4184193326Sed llvm::GlobalValue::InternalLinkage, 4185193326Sed Init, 4186198092Srdivacky "\01L_OBJC_IMAGE_INFO"); 4187193326Sed IMGV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip"); 4188193326Sed IMGV->setConstant(true); 4189198092Srdivacky CGM.AddUsedGlobal(IMGV); 4190193326Sed} 4191193326Sed 4192193326Sed/// LegacyDispatchedSelector - Returns true if SEL is not in the list of 4193193326Sed/// NonLegacyDispatchMethods; false otherwise. What this means is that 4194198092Srdivacky/// except for the 19 selectors in the list, we generate 32bit-style 4195193326Sed/// message dispatch call for all the rest. 4196193326Sed/// 4197193326Sedbool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) { 4198193326Sed if (NonLegacyDispatchMethods.empty()) { 4199193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("alloc")); 4200193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("class")); 4201193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("self")); 4202193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("isFlipped")); 4203193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("length")); 4204193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("count")); 4205193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("retain")); 4206193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("release")); 4207193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("autorelease")); 4208193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("hash")); 4209198092Srdivacky 4210193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("allocWithZone")); 4211193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("isKindOfClass")); 4212193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("respondsToSelector")); 4213193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("objectForKey")); 4214193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("objectAtIndex")); 4215193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("isEqualToString")); 4216193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("isEqual")); 4217193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("addObject")); 4218198092Srdivacky // "countByEnumeratingWithState:objects:count" 4219193326Sed IdentifierInfo *KeyIdents[] = { 4220198092Srdivacky &CGM.getContext().Idents.get("countByEnumeratingWithState"), 4221198092Srdivacky &CGM.getContext().Idents.get("objects"), 4222198092Srdivacky &CGM.getContext().Idents.get("count") 4223193326Sed }; 4224193326Sed NonLegacyDispatchMethods.insert( 4225193326Sed CGM.getContext().Selectors.getSelector(3, KeyIdents)); 4226193326Sed } 4227193326Sed return (NonLegacyDispatchMethods.count(Sel) == 0); 4228193326Sed} 4229193326Sed 4230193326Sed// Metadata flags 4231193326Sedenum MetaDataDlags { 4232193326Sed CLS = 0x0, 4233193326Sed CLS_META = 0x1, 4234193326Sed CLS_ROOT = 0x2, 4235193326Sed OBJC2_CLS_HIDDEN = 0x10, 4236193326Sed CLS_EXCEPTION = 0x20 4237193326Sed}; 4238193326Sed/// BuildClassRoTInitializer - generate meta-data for: 4239193326Sed/// struct _class_ro_t { 4240193326Sed/// uint32_t const flags; 4241193326Sed/// uint32_t const instanceStart; 4242193326Sed/// uint32_t const instanceSize; 4243193326Sed/// uint32_t const reserved; // only when building for 64bit targets 4244193326Sed/// const uint8_t * const ivarLayout; 4245193326Sed/// const char *const name; 4246193326Sed/// const struct _method_list_t * const baseMethods; 4247193326Sed/// const struct _protocol_list_t *const baseProtocols; 4248193326Sed/// const struct _ivar_list_t *const ivars; 4249193326Sed/// const uint8_t * const weakIvarLayout; 4250193326Sed/// const struct _prop_list_t * const properties; 4251193326Sed/// } 4252193326Sed/// 4253193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( 4254198092Srdivacky unsigned flags, 4255198092Srdivacky unsigned InstanceStart, 4256198092Srdivacky unsigned InstanceSize, 4257198092Srdivacky const ObjCImplementationDecl *ID) { 4258193326Sed std::string ClassName = ID->getNameAsString(); 4259193326Sed std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets! 4260193326Sed Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags); 4261193326Sed Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart); 4262193326Sed Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize); 4263193326Sed // FIXME. For 64bit targets add 0 here. 4264198092Srdivacky Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) 4265198092Srdivacky : BuildIvarLayout(ID, true); 4266193326Sed Values[ 4] = GetClassName(ID->getIdentifier()); 4267193326Sed // const struct _method_list_t * const baseMethods; 4268193326Sed std::vector<llvm::Constant*> Methods; 4269193326Sed std::string MethodListName("\01l_OBJC_$_"); 4270193326Sed if (flags & CLS_META) { 4271193326Sed MethodListName += "CLASS_METHODS_" + ID->getNameAsString(); 4272198092Srdivacky for (ObjCImplementationDecl::classmeth_iterator 4273195341Sed i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { 4274193326Sed // Class methods should always be defined. 4275193326Sed Methods.push_back(GetMethodConstant(*i)); 4276193326Sed } 4277193326Sed } else { 4278193326Sed MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString(); 4279198092Srdivacky for (ObjCImplementationDecl::instmeth_iterator 4280195341Sed i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { 4281193326Sed // Instance methods should always be defined. 4282193326Sed Methods.push_back(GetMethodConstant(*i)); 4283193326Sed } 4284198092Srdivacky for (ObjCImplementationDecl::propimpl_iterator 4285195341Sed i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { 4286193326Sed ObjCPropertyImplDecl *PID = *i; 4287198092Srdivacky 4288193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){ 4289193326Sed ObjCPropertyDecl *PD = PID->getPropertyDecl(); 4290198092Srdivacky 4291193326Sed if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) 4292193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 4293193326Sed Methods.push_back(C); 4294193326Sed if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) 4295193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 4296193326Sed Methods.push_back(C); 4297193326Sed } 4298193326Sed } 4299193326Sed } 4300198092Srdivacky Values[ 5] = EmitMethodList(MethodListName, 4301198092Srdivacky "__DATA, __objc_const", Methods); 4302198092Srdivacky 4303193326Sed const ObjCInterfaceDecl *OID = ID->getClassInterface(); 4304193326Sed assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer"); 4305198092Srdivacky Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_" 4306198398Srdivacky + OID->getName(), 4307193326Sed OID->protocol_begin(), 4308193326Sed OID->protocol_end()); 4309198092Srdivacky 4310193326Sed if (flags & CLS_META) 4311193326Sed Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); 4312193326Sed else 4313193326Sed Values[ 7] = EmitIvarList(ID); 4314198092Srdivacky Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) 4315198092Srdivacky : BuildIvarLayout(ID, false); 4316193326Sed if (flags & CLS_META) 4317193326Sed Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 4318193326Sed else 4319198398Srdivacky Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), 4320198398Srdivacky ID, ID->getClassInterface(), ObjCTypes); 4321193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy, 4322193326Sed Values); 4323193326Sed llvm::GlobalVariable *CLASS_RO_GV = 4324198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false, 4325198092Srdivacky llvm::GlobalValue::InternalLinkage, 4326198092Srdivacky Init, 4327198092Srdivacky (flags & CLS_META) ? 4328198092Srdivacky std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName : 4329198092Srdivacky std::string("\01l_OBJC_CLASS_RO_$_")+ClassName); 4330193326Sed CLASS_RO_GV->setAlignment( 4331193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassRonfABITy)); 4332193326Sed CLASS_RO_GV->setSection("__DATA, __objc_const"); 4333193326Sed return CLASS_RO_GV; 4334193326Sed 4335193326Sed} 4336193326Sed 4337193326Sed/// BuildClassMetaData - This routine defines that to-level meta-data 4338193326Sed/// for the given ClassName for: 4339193326Sed/// struct _class_t { 4340193326Sed/// struct _class_t *isa; 4341193326Sed/// struct _class_t * const superclass; 4342193326Sed/// void *cache; 4343193326Sed/// IMP *vtable; 4344193326Sed/// struct class_ro_t *ro; 4345193326Sed/// } 4346193326Sed/// 4347193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( 4348198092Srdivacky std::string &ClassName, 4349198092Srdivacky llvm::Constant *IsAGV, 4350198092Srdivacky llvm::Constant *SuperClassGV, 4351198092Srdivacky llvm::Constant *ClassRoGV, 4352198092Srdivacky bool HiddenVisibility) { 4353193326Sed std::vector<llvm::Constant*> Values(5); 4354193326Sed Values[0] = IsAGV; 4355198092Srdivacky Values[1] = SuperClassGV; 4356198092Srdivacky if (!Values[1]) 4357198092Srdivacky Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy); 4358193326Sed Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar 4359193326Sed Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar 4360193326Sed Values[4] = ClassRoGV; // &CLASS_RO_GV 4361198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy, 4362193326Sed Values); 4363193326Sed llvm::GlobalVariable *GV = GetClassGlobal(ClassName); 4364193326Sed GV->setInitializer(Init); 4365193326Sed GV->setSection("__DATA, __objc_data"); 4366193326Sed GV->setAlignment( 4367193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassnfABITy)); 4368193326Sed if (HiddenVisibility) 4369193326Sed GV->setVisibility(llvm::GlobalValue::HiddenVisibility); 4370193326Sed return GV; 4371193326Sed} 4372193326Sed 4373198092Srdivackybool 4374193326SedCGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const { 4375195341Sed return OD->getClassMethod(GetNullarySelector("load")) != 0; 4376193326Sed} 4377193326Sed 4378193326Sedvoid CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, 4379193326Sed uint32_t &InstanceStart, 4380193326Sed uint32_t &InstanceSize) { 4381198092Srdivacky const ASTRecordLayout &RL = 4382193326Sed CGM.getContext().getASTObjCImplementationLayout(OID); 4383198092Srdivacky 4384193326Sed // InstanceSize is really instance end. 4385198092Srdivacky InstanceSize = llvm::RoundUpToAlignment(RL.getDataSize(), 8) / 8; 4386193326Sed 4387193326Sed // If there are no fields, the start is the same as the end. 4388193326Sed if (!RL.getFieldCount()) 4389193326Sed InstanceStart = InstanceSize; 4390193326Sed else 4391193326Sed InstanceStart = RL.getFieldOffset(0) / 8; 4392193326Sed} 4393193326Sed 4394193326Sedvoid CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { 4395193326Sed std::string ClassName = ID->getNameAsString(); 4396193326Sed if (!ObjCEmptyCacheVar) { 4397193326Sed ObjCEmptyCacheVar = new llvm::GlobalVariable( 4398198092Srdivacky CGM.getModule(), 4399198092Srdivacky ObjCTypes.CacheTy, 4400198092Srdivacky false, 4401198092Srdivacky llvm::GlobalValue::ExternalLinkage, 4402198092Srdivacky 0, 4403198092Srdivacky "_objc_empty_cache"); 4404198092Srdivacky 4405193326Sed ObjCEmptyVtableVar = new llvm::GlobalVariable( 4406198092Srdivacky CGM.getModule(), 4407198092Srdivacky ObjCTypes.ImpnfABITy, 4408198092Srdivacky false, 4409198092Srdivacky llvm::GlobalValue::ExternalLinkage, 4410198092Srdivacky 0, 4411198092Srdivacky "_objc_empty_vtable"); 4412193326Sed } 4413198092Srdivacky assert(ID->getClassInterface() && 4414193326Sed "CGObjCNonFragileABIMac::GenerateClass - class is 0"); 4415193326Sed // FIXME: Is this correct (that meta class size is never computed)? 4416198092Srdivacky uint32_t InstanceStart = 4417193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy); 4418193326Sed uint32_t InstanceSize = InstanceStart; 4419193326Sed uint32_t flags = CLS_META; 4420193326Sed std::string ObjCMetaClassName(getMetaclassSymbolPrefix()); 4421193326Sed std::string ObjCClassName(getClassSymbolPrefix()); 4422198092Srdivacky 4423193326Sed llvm::GlobalVariable *SuperClassGV, *IsAGV; 4424198092Srdivacky 4425198092Srdivacky bool classIsHidden = 4426193326Sed CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden; 4427193326Sed if (classIsHidden) 4428193326Sed flags |= OBJC2_CLS_HIDDEN; 4429193326Sed if (!ID->getClassInterface()->getSuperClass()) { 4430193326Sed // class is root 4431193326Sed flags |= CLS_ROOT; 4432193326Sed SuperClassGV = GetClassGlobal(ObjCClassName + ClassName); 4433193326Sed IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName); 4434193326Sed } else { 4435193326Sed // Has a root. Current class is not a root. 4436193326Sed const ObjCInterfaceDecl *Root = ID->getClassInterface(); 4437193326Sed while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) 4438193326Sed Root = Super; 4439193326Sed IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString()); 4440193326Sed // work on super class metadata symbol. 4441198092Srdivacky std::string SuperClassName = 4442193326Sed ObjCMetaClassName + ID->getClassInterface()->getSuperClass()->getNameAsString(); 4443193326Sed SuperClassGV = GetClassGlobal(SuperClassName); 4444199482Srdivacky if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>()) 4445199482Srdivacky SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 4446193326Sed } 4447193326Sed llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags, 4448193326Sed InstanceStart, 4449193326Sed InstanceSize,ID); 4450193326Sed std::string TClassName = ObjCMetaClassName + ClassName; 4451198092Srdivacky llvm::GlobalVariable *MetaTClass = 4452193326Sed BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV, 4453193326Sed classIsHidden); 4454199482Srdivacky DefinedMetaClasses.push_back(MetaTClass); 4455193326Sed 4456193326Sed // Metadata for the class 4457193326Sed flags = CLS; 4458193326Sed if (classIsHidden) 4459193326Sed flags |= OBJC2_CLS_HIDDEN; 4460193326Sed 4461194613Sed if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface())) 4462193326Sed flags |= CLS_EXCEPTION; 4463193326Sed 4464193326Sed if (!ID->getClassInterface()->getSuperClass()) { 4465193326Sed flags |= CLS_ROOT; 4466193326Sed SuperClassGV = 0; 4467193326Sed } else { 4468193326Sed // Has a root. Current class is not a root. 4469193326Sed std::string RootClassName = 4470193326Sed ID->getClassInterface()->getSuperClass()->getNameAsString(); 4471193326Sed SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName); 4472199482Srdivacky if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>()) 4473199482Srdivacky SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 4474193326Sed } 4475193326Sed GetClassSizeInfo(ID, InstanceStart, InstanceSize); 4476193326Sed CLASS_RO_GV = BuildClassRoTInitializer(flags, 4477193326Sed InstanceStart, 4478198092Srdivacky InstanceSize, 4479193326Sed ID); 4480198092Srdivacky 4481193326Sed TClassName = ObjCClassName + ClassName; 4482198092Srdivacky llvm::GlobalVariable *ClassMD = 4483193326Sed BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV, 4484193326Sed classIsHidden); 4485193326Sed DefinedClasses.push_back(ClassMD); 4486193326Sed 4487193326Sed // Determine if this class is also "non-lazy". 4488193326Sed if (ImplementationIsNonLazy(ID)) 4489193326Sed DefinedNonLazyClasses.push_back(ClassMD); 4490193326Sed 4491193326Sed // Force the definition of the EHType if necessary. 4492193326Sed if (flags & CLS_EXCEPTION) 4493193326Sed GetInterfaceEHType(ID->getClassInterface(), true); 4494193326Sed} 4495193326Sed 4496193326Sed/// GenerateProtocolRef - This routine is called to generate code for 4497193326Sed/// a protocol reference expression; as in: 4498193326Sed/// @code 4499193326Sed/// @protocol(Proto1); 4500193326Sed/// @endcode 4501193326Sed/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1 4502193326Sed/// which will hold address of the protocol meta-data. 4503193326Sed/// 4504193326Sedllvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder, 4505198092Srdivacky const ObjCProtocolDecl *PD) { 4506198092Srdivacky 4507193326Sed // This routine is called for @protocol only. So, we must build definition 4508193326Sed // of protocol's meta-data (not a reference to it!) 4509193326Sed // 4510198092Srdivacky llvm::Constant *Init = 4511198092Srdivacky llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD), 4512198092Srdivacky ObjCTypes.ExternalProtocolPtrTy); 4513198092Srdivacky 4514193326Sed std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_"); 4515193326Sed ProtocolName += PD->getNameAsCString(); 4516198092Srdivacky 4517193326Sed llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName); 4518193326Sed if (PTGV) 4519193326Sed return Builder.CreateLoad(PTGV, false, "tmp"); 4520193326Sed PTGV = new llvm::GlobalVariable( 4521198092Srdivacky CGM.getModule(), 4522198092Srdivacky Init->getType(), false, 4523198092Srdivacky llvm::GlobalValue::WeakAnyLinkage, 4524198092Srdivacky Init, 4525198092Srdivacky ProtocolName); 4526193326Sed PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip"); 4527193326Sed PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 4528198092Srdivacky CGM.AddUsedGlobal(PTGV); 4529193326Sed return Builder.CreateLoad(PTGV, false, "tmp"); 4530193326Sed} 4531193326Sed 4532193326Sed/// GenerateCategory - Build metadata for a category implementation. 4533193326Sed/// struct _category_t { 4534193326Sed/// const char * const name; 4535193326Sed/// struct _class_t *const cls; 4536193326Sed/// const struct _method_list_t * const instance_methods; 4537193326Sed/// const struct _method_list_t * const class_methods; 4538193326Sed/// const struct _protocol_list_t * const protocols; 4539193326Sed/// const struct _prop_list_t * const properties; 4540193326Sed/// } 4541193326Sed/// 4542193326Sedvoid CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 4543193326Sed const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); 4544193326Sed const char *Prefix = "\01l_OBJC_$_CATEGORY_"; 4545198092Srdivacky std::string ExtCatName(Prefix + Interface->getNameAsString()+ 4546198092Srdivacky "_$_" + OCD->getNameAsString()); 4547198092Srdivacky std::string ExtClassName(getClassSymbolPrefix() + 4548193326Sed Interface->getNameAsString()); 4549198092Srdivacky 4550193326Sed std::vector<llvm::Constant*> Values(6); 4551193326Sed Values[0] = GetClassName(OCD->getIdentifier()); 4552193326Sed // meta-class entry symbol 4553193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName); 4554199482Srdivacky if (Interface->hasAttr<WeakImportAttr>()) 4555199482Srdivacky ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 4556199482Srdivacky 4557193326Sed Values[1] = ClassGV; 4558193326Sed std::vector<llvm::Constant*> Methods; 4559193326Sed std::string MethodListName(Prefix); 4560198092Srdivacky MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() + 4561193326Sed "_$_" + OCD->getNameAsString(); 4562198092Srdivacky 4563198092Srdivacky for (ObjCCategoryImplDecl::instmeth_iterator 4564195341Sed i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { 4565193326Sed // Instance methods should always be defined. 4566193326Sed Methods.push_back(GetMethodConstant(*i)); 4567193326Sed } 4568198092Srdivacky 4569198092Srdivacky Values[2] = EmitMethodList(MethodListName, 4570198092Srdivacky "__DATA, __objc_const", 4571193326Sed Methods); 4572193326Sed 4573193326Sed MethodListName = Prefix; 4574193326Sed MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" + 4575193326Sed OCD->getNameAsString(); 4576193326Sed Methods.clear(); 4577198092Srdivacky for (ObjCCategoryImplDecl::classmeth_iterator 4578195341Sed i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { 4579193326Sed // Class methods should always be defined. 4580193326Sed Methods.push_back(GetMethodConstant(*i)); 4581193326Sed } 4582198092Srdivacky 4583198092Srdivacky Values[3] = EmitMethodList(MethodListName, 4584198092Srdivacky "__DATA, __objc_const", 4585193326Sed Methods); 4586198092Srdivacky const ObjCCategoryDecl *Category = 4587193326Sed Interface->FindCategoryDeclaration(OCD->getIdentifier()); 4588193326Sed if (Category) { 4589198398Srdivacky llvm::SmallString<256> ExtName; 4590198398Srdivacky llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_" 4591198398Srdivacky << OCD->getName(); 4592193326Sed Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_" 4593198398Srdivacky + Interface->getName() + "_$_" 4594198398Srdivacky + Category->getName(), 4595193326Sed Category->protocol_begin(), 4596193326Sed Category->protocol_end()); 4597198398Srdivacky Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), 4598198398Srdivacky OCD, Category, ObjCTypes); 4599198092Srdivacky } else { 4600193326Sed Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); 4601193326Sed Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 4602193326Sed } 4603198092Srdivacky 4604198092Srdivacky llvm::Constant *Init = 4605198092Srdivacky llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy, 4606193326Sed Values); 4607193326Sed llvm::GlobalVariable *GCATV 4608198092Srdivacky = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy, 4609193326Sed false, 4610193326Sed llvm::GlobalValue::InternalLinkage, 4611193326Sed Init, 4612198092Srdivacky ExtCatName); 4613193326Sed GCATV->setAlignment( 4614193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.CategorynfABITy)); 4615193326Sed GCATV->setSection("__DATA, __objc_const"); 4616198092Srdivacky CGM.AddUsedGlobal(GCATV); 4617193326Sed DefinedCategories.push_back(GCATV); 4618193326Sed 4619193326Sed // Determine if this category is also "non-lazy". 4620193326Sed if (ImplementationIsNonLazy(OCD)) 4621193326Sed DefinedNonLazyCategories.push_back(GCATV); 4622193326Sed} 4623193326Sed 4624193326Sed/// GetMethodConstant - Return a struct objc_method constant for the 4625193326Sed/// given method if it has been defined. The result is null if the 4626193326Sed/// method has not been defined. The return value has type MethodPtrTy. 4627193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant( 4628198092Srdivacky const ObjCMethodDecl *MD) { 4629193326Sed // FIXME: Use DenseMap::lookup 4630193326Sed llvm::Function *Fn = MethodDefinitions[MD]; 4631193326Sed if (!Fn) 4632193326Sed return 0; 4633198092Srdivacky 4634193326Sed std::vector<llvm::Constant*> Method(3); 4635198092Srdivacky Method[0] = 4636198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 4637198092Srdivacky ObjCTypes.SelectorPtrTy); 4638193326Sed Method[1] = GetMethodVarType(MD); 4639193326Sed Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy); 4640193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method); 4641193326Sed} 4642193326Sed 4643193326Sed/// EmitMethodList - Build meta-data for method declarations 4644193326Sed/// struct _method_list_t { 4645193326Sed/// uint32_t entsize; // sizeof(struct _objc_method) 4646193326Sed/// uint32_t method_count; 4647193326Sed/// struct _objc_method method_list[method_count]; 4648193326Sed/// } 4649193326Sed/// 4650198398Srdivackyllvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name, 4651198398Srdivacky const char *Section, 4652198398Srdivacky const ConstantVector &Methods) { 4653193326Sed // Return null for empty list. 4654193326Sed if (Methods.empty()) 4655193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy); 4656198092Srdivacky 4657193326Sed std::vector<llvm::Constant*> Values(3); 4658193326Sed // sizeof(struct _objc_method) 4659193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy); 4660193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 4661193326Sed // method_count 4662193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 4663193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy, 4664193326Sed Methods.size()); 4665193326Sed Values[2] = llvm::ConstantArray::get(AT, Methods); 4666198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 4667198092Srdivacky 4668193326Sed llvm::GlobalVariable *GV = 4669198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 4670193326Sed llvm::GlobalValue::InternalLinkage, 4671193326Sed Init, 4672198092Srdivacky Name); 4673193326Sed GV->setAlignment( 4674193326Sed CGM.getTargetData().getPrefTypeAlignment(Init->getType())); 4675193326Sed GV->setSection(Section); 4676198092Srdivacky CGM.AddUsedGlobal(GV); 4677193326Sed return llvm::ConstantExpr::getBitCast(GV, 4678193326Sed ObjCTypes.MethodListnfABIPtrTy); 4679193326Sed} 4680193326Sed 4681193326Sed/// ObjCIvarOffsetVariable - Returns the ivar offset variable for 4682193326Sed/// the given ivar. 4683193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable( 4684198092Srdivacky const ObjCInterfaceDecl *ID, 4685198092Srdivacky const ObjCIvarDecl *Ivar) { 4686193326Sed // FIXME: We shouldn't need to do this lookup. 4687193326Sed unsigned Index; 4688198092Srdivacky const ObjCInterfaceDecl *Container = 4689193326Sed FindIvarInterface(CGM.getContext(), ID, Ivar, Index); 4690193326Sed assert(Container && "Unable to find ivar container!"); 4691193326Sed std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() + 4692193326Sed '.' + Ivar->getNameAsString(); 4693198092Srdivacky llvm::GlobalVariable *IvarOffsetGV = 4694193326Sed CGM.getModule().getGlobalVariable(Name); 4695193326Sed if (!IvarOffsetGV) 4696198092Srdivacky IvarOffsetGV = 4697198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy, 4698193326Sed false, 4699193326Sed llvm::GlobalValue::ExternalLinkage, 4700193326Sed 0, 4701198092Srdivacky Name); 4702193326Sed return IvarOffsetGV; 4703193326Sed} 4704193326Sed 4705193326Sedllvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar( 4706198092Srdivacky const ObjCInterfaceDecl *ID, 4707198092Srdivacky const ObjCIvarDecl *Ivar, 4708198092Srdivacky unsigned long int Offset) { 4709193326Sed llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar); 4710198092Srdivacky IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy, 4711193326Sed Offset)); 4712193326Sed IvarOffsetGV->setAlignment( 4713193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy)); 4714193326Sed 4715193326Sed // FIXME: This matches gcc, but shouldn't the visibility be set on the use as 4716193326Sed // well (i.e., in ObjCIvarOffsetVariable). 4717193326Sed if (Ivar->getAccessControl() == ObjCIvarDecl::Private || 4718193326Sed Ivar->getAccessControl() == ObjCIvarDecl::Package || 4719193326Sed CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden) 4720193326Sed IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 4721193326Sed else 4722193326Sed IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); 4723193326Sed IvarOffsetGV->setSection("__DATA, __objc_const"); 4724193326Sed return IvarOffsetGV; 4725193326Sed} 4726193326Sed 4727193326Sed/// EmitIvarList - Emit the ivar list for the given 4728193326Sed/// implementation. The return value has type 4729193326Sed/// IvarListnfABIPtrTy. 4730193326Sed/// struct _ivar_t { 4731193326Sed/// unsigned long int *offset; // pointer to ivar offset location 4732193326Sed/// char *name; 4733193326Sed/// char *type; 4734193326Sed/// uint32_t alignment; 4735193326Sed/// uint32_t size; 4736193326Sed/// } 4737193326Sed/// struct _ivar_list_t { 4738193326Sed/// uint32 entsize; // sizeof(struct _ivar_t) 4739193326Sed/// uint32 count; 4740193326Sed/// struct _iver_t list[count]; 4741193326Sed/// } 4742193326Sed/// 4743193326Sed 4744193326Sedllvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( 4745198092Srdivacky const ObjCImplementationDecl *ID) { 4746198092Srdivacky 4747193326Sed std::vector<llvm::Constant*> Ivars, Ivar(5); 4748198092Srdivacky 4749193326Sed const ObjCInterfaceDecl *OID = ID->getClassInterface(); 4750193326Sed assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface"); 4751198092Srdivacky 4752193326Sed // FIXME. Consolidate this with similar code in GenerateClass. 4753198092Srdivacky 4754193326Sed // Collect declared and synthesized ivars in a small vector. 4755193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; 4756193576Sed CGM.getContext().ShallowCollectObjCIvars(OID, OIvars); 4757198092Srdivacky 4758193326Sed for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { 4759193326Sed ObjCIvarDecl *IVD = OIvars[i]; 4760193576Sed // Ignore unnamed bit-fields. 4761193576Sed if (!IVD->getDeclName()) 4762193576Sed continue; 4763198092Srdivacky Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD, 4764193326Sed ComputeIvarBaseOffset(CGM, ID, IVD)); 4765193326Sed Ivar[1] = GetMethodVarName(IVD->getIdentifier()); 4766193326Sed Ivar[2] = GetMethodVarType(IVD); 4767193326Sed const llvm::Type *FieldTy = 4768193326Sed CGM.getTypes().ConvertTypeForMem(IVD->getType()); 4769193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy); 4770193326Sed unsigned Align = CGM.getContext().getPreferredTypeAlign( 4771198092Srdivacky IVD->getType().getTypePtr()) >> 3; 4772193326Sed Align = llvm::Log2_32(Align); 4773193326Sed Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align); 4774193326Sed // NOTE. Size of a bitfield does not match gcc's, because of the 4775193326Sed // way bitfields are treated special in each. But I am told that 4776193326Sed // 'size' for bitfield ivars is ignored by the runtime so it does 4777193326Sed // not matter. If it matters, there is enough info to get the 4778193326Sed // bitfield right! 4779193326Sed Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 4780193326Sed Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar)); 4781193326Sed } 4782193326Sed // Return null for empty list. 4783193326Sed if (Ivars.empty()) 4784193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); 4785193326Sed std::vector<llvm::Constant*> Values(3); 4786193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy); 4787193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 4788193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size()); 4789193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy, 4790193326Sed Ivars.size()); 4791193326Sed Values[2] = llvm::ConstantArray::get(AT, Ivars); 4792198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 4793193326Sed const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_"; 4794193326Sed llvm::GlobalVariable *GV = 4795198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 4796193326Sed llvm::GlobalValue::InternalLinkage, 4797193326Sed Init, 4798198398Srdivacky Prefix + OID->getName()); 4799193326Sed GV->setAlignment( 4800193326Sed CGM.getTargetData().getPrefTypeAlignment(Init->getType())); 4801193326Sed GV->setSection("__DATA, __objc_const"); 4802198092Srdivacky 4803198092Srdivacky CGM.AddUsedGlobal(GV); 4804198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy); 4805193326Sed} 4806193326Sed 4807193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( 4808198092Srdivacky const ObjCProtocolDecl *PD) { 4809193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 4810198092Srdivacky 4811193326Sed if (!Entry) { 4812193326Sed // We use the initializer as a marker of whether this is a forward 4813193326Sed // reference or not. At module finalization we add the empty 4814193326Sed // contents for protocols which were referenced but never defined. 4815198092Srdivacky Entry = 4816198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false, 4817198092Srdivacky llvm::GlobalValue::ExternalLinkage, 4818198092Srdivacky 0, 4819198398Srdivacky "\01l_OBJC_PROTOCOL_$_" + PD->getName()); 4820193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 4821193326Sed } 4822198092Srdivacky 4823193326Sed return Entry; 4824193326Sed} 4825193326Sed 4826193326Sed/// GetOrEmitProtocol - Generate the protocol meta-data: 4827193326Sed/// @code 4828193326Sed/// struct _protocol_t { 4829193326Sed/// id isa; // NULL 4830193326Sed/// const char * const protocol_name; 4831193326Sed/// const struct _protocol_list_t * protocol_list; // super protocols 4832193326Sed/// const struct method_list_t * const instance_methods; 4833193326Sed/// const struct method_list_t * const class_methods; 4834193326Sed/// const struct method_list_t *optionalInstanceMethods; 4835193326Sed/// const struct method_list_t *optionalClassMethods; 4836193326Sed/// const struct _prop_list_t * properties; 4837193326Sed/// const uint32_t size; // sizeof(struct _protocol_t) 4838193326Sed/// const uint32_t flags; // = 0 4839193326Sed/// } 4840193326Sed/// @endcode 4841193326Sed/// 4842193326Sed 4843193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( 4844198092Srdivacky const ObjCProtocolDecl *PD) { 4845193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 4846198092Srdivacky 4847193326Sed // Early exit if a defining object has already been generated. 4848193326Sed if (Entry && Entry->hasInitializer()) 4849193326Sed return Entry; 4850193326Sed 4851193326Sed // Construct method lists. 4852193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 4853193326Sed std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; 4854198092Srdivacky for (ObjCProtocolDecl::instmeth_iterator 4855195341Sed i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { 4856193326Sed ObjCMethodDecl *MD = *i; 4857193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 4858193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 4859193326Sed OptInstanceMethods.push_back(C); 4860193326Sed } else { 4861193326Sed InstanceMethods.push_back(C); 4862198092Srdivacky } 4863193326Sed } 4864198092Srdivacky 4865198092Srdivacky for (ObjCProtocolDecl::classmeth_iterator 4866195341Sed i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { 4867193326Sed ObjCMethodDecl *MD = *i; 4868193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 4869193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 4870193326Sed OptClassMethods.push_back(C); 4871193326Sed } else { 4872193326Sed ClassMethods.push_back(C); 4873198092Srdivacky } 4874193326Sed } 4875198092Srdivacky 4876193326Sed std::vector<llvm::Constant*> Values(10); 4877193326Sed // isa is NULL 4878193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy); 4879193326Sed Values[1] = GetClassName(PD->getIdentifier()); 4880198398Srdivacky Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(), 4881198398Srdivacky PD->protocol_begin(), 4882198398Srdivacky PD->protocol_end()); 4883198092Srdivacky 4884193326Sed Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_" 4885198398Srdivacky + PD->getName(), 4886193326Sed "__DATA, __objc_const", 4887193326Sed InstanceMethods); 4888198092Srdivacky Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_" 4889198398Srdivacky + PD->getName(), 4890193326Sed "__DATA, __objc_const", 4891193326Sed ClassMethods); 4892193326Sed Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_" 4893198398Srdivacky + PD->getName(), 4894193326Sed "__DATA, __objc_const", 4895193326Sed OptInstanceMethods); 4896198092Srdivacky Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_" 4897198398Srdivacky + PD->getName(), 4898193326Sed "__DATA, __objc_const", 4899193326Sed OptClassMethods); 4900198398Srdivacky Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(), 4901193326Sed 0, PD, ObjCTypes); 4902198092Srdivacky uint32_t Size = 4903193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); 4904193326Sed Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 4905193326Sed Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy); 4906193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy, 4907193326Sed Values); 4908198092Srdivacky 4909193326Sed if (Entry) { 4910193326Sed // Already created, fix the linkage and update the initializer. 4911193326Sed Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 4912193326Sed Entry->setInitializer(Init); 4913193326Sed } else { 4914198092Srdivacky Entry = 4915198398Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, 4916198398Srdivacky false, llvm::GlobalValue::WeakAnyLinkage, Init, 4917198398Srdivacky "\01l_OBJC_PROTOCOL_$_" + PD->getName()); 4918193326Sed Entry->setAlignment( 4919193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy)); 4920193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 4921193326Sed } 4922193326Sed Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); 4923198092Srdivacky CGM.AddUsedGlobal(Entry); 4924198092Srdivacky 4925193326Sed // Use this protocol meta-data to build protocol list table in section 4926193326Sed // __DATA, __objc_protolist 4927198398Srdivacky llvm::GlobalVariable *PTGV = 4928198398Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, 4929198398Srdivacky false, llvm::GlobalValue::WeakAnyLinkage, Entry, 4930198398Srdivacky "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName()); 4931193326Sed PTGV->setAlignment( 4932193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); 4933193326Sed PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip"); 4934193326Sed PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 4935198092Srdivacky CGM.AddUsedGlobal(PTGV); 4936193326Sed return Entry; 4937193326Sed} 4938193326Sed 4939193326Sed/// EmitProtocolList - Generate protocol list meta-data: 4940193326Sed/// @code 4941193326Sed/// struct _protocol_list_t { 4942193326Sed/// long protocol_count; // Note, this is 32/64 bit 4943193326Sed/// struct _protocol_t[protocol_count]; 4944193326Sed/// } 4945193326Sed/// @endcode 4946193326Sed/// 4947193326Sedllvm::Constant * 4948198398SrdivackyCGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name, 4949198398Srdivacky ObjCProtocolDecl::protocol_iterator begin, 4950198398Srdivacky ObjCProtocolDecl::protocol_iterator end) { 4951193326Sed std::vector<llvm::Constant*> ProtocolRefs; 4952198092Srdivacky 4953193326Sed // Just return null for empty protocol lists 4954198092Srdivacky if (begin == end) 4955193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); 4956198092Srdivacky 4957193326Sed // FIXME: We shouldn't need to do this lookup here, should we? 4958198398Srdivacky llvm::SmallString<256> TmpName; 4959198398Srdivacky Name.toVector(TmpName); 4960198398Srdivacky llvm::GlobalVariable *GV = 4961198398Srdivacky CGM.getModule().getGlobalVariable(TmpName.str(), true); 4962193326Sed if (GV) 4963198398Srdivacky return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy); 4964198092Srdivacky 4965193326Sed for (; begin != end; ++begin) 4966193326Sed ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented??? 4967193326Sed 4968193326Sed // This list is null terminated. 4969193326Sed ProtocolRefs.push_back(llvm::Constant::getNullValue( 4970198092Srdivacky ObjCTypes.ProtocolnfABIPtrTy)); 4971198092Srdivacky 4972193326Sed std::vector<llvm::Constant*> Values(2); 4973198092Srdivacky Values[0] = 4974198092Srdivacky llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1); 4975198092Srdivacky Values[1] = 4976198092Srdivacky llvm::ConstantArray::get( 4977198092Srdivacky llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy, 4978198092Srdivacky ProtocolRefs.size()), 4979198092Srdivacky ProtocolRefs); 4980198092Srdivacky 4981198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 4982198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 4983193326Sed llvm::GlobalValue::InternalLinkage, 4984193326Sed Init, 4985198092Srdivacky Name); 4986193326Sed GV->setSection("__DATA, __objc_const"); 4987193326Sed GV->setAlignment( 4988193326Sed CGM.getTargetData().getPrefTypeAlignment(Init->getType())); 4989198092Srdivacky CGM.AddUsedGlobal(GV); 4990198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, 4991193326Sed ObjCTypes.ProtocolListnfABIPtrTy); 4992193326Sed} 4993193326Sed 4994193326Sed/// GetMethodDescriptionConstant - This routine build following meta-data: 4995193326Sed/// struct _objc_method { 4996193326Sed/// SEL _cmd; 4997193326Sed/// char *method_type; 4998193326Sed/// char *_imp; 4999193326Sed/// } 5000193326Sed 5001193326Sedllvm::Constant * 5002193326SedCGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { 5003193326Sed std::vector<llvm::Constant*> Desc(3); 5004198092Srdivacky Desc[0] = 5005198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 5006198092Srdivacky ObjCTypes.SelectorPtrTy); 5007193326Sed Desc[1] = GetMethodVarType(MD); 5008193326Sed // Protocol methods have no implementation. So, this entry is always NULL. 5009193326Sed Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 5010193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc); 5011193326Sed} 5012193326Sed 5013193326Sed/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference. 5014193326Sed/// This code gen. amounts to generating code for: 5015193326Sed/// @code 5016193326Sed/// (type *)((char *)base + _OBJC_IVAR_$_.ivar; 5017193326Sed/// @encode 5018198092Srdivacky/// 5019193326SedLValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( 5020198092Srdivacky CodeGen::CodeGenFunction &CGF, 5021198092Srdivacky QualType ObjectTy, 5022198092Srdivacky llvm::Value *BaseValue, 5023198092Srdivacky const ObjCIvarDecl *Ivar, 5024198092Srdivacky unsigned CVRQualifiers) { 5025198092Srdivacky const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); 5026193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 5027193326Sed EmitIvarOffset(CGF, ID, Ivar)); 5028193326Sed} 5029193326Sed 5030193326Sedllvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset( 5031198092Srdivacky CodeGen::CodeGenFunction &CGF, 5032198092Srdivacky const ObjCInterfaceDecl *Interface, 5033198092Srdivacky const ObjCIvarDecl *Ivar) { 5034198092Srdivacky return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar), 5035193326Sed false, "ivar"); 5036193326Sed} 5037193326Sed 5038193326SedCodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( 5039198092Srdivacky CodeGen::CodeGenFunction &CGF, 5040198092Srdivacky QualType ResultType, 5041198092Srdivacky Selector Sel, 5042198092Srdivacky llvm::Value *Receiver, 5043198092Srdivacky QualType Arg0Ty, 5044198092Srdivacky bool IsSuper, 5045198092Srdivacky const CallArgList &CallArgs) { 5046193326Sed // FIXME. Even though IsSuper is passes. This function doese not handle calls 5047193326Sed // to 'super' receivers. 5048193326Sed CodeGenTypes &Types = CGM.getTypes(); 5049193326Sed llvm::Value *Arg0 = Receiver; 5050193326Sed if (!IsSuper) 5051193326Sed Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp"); 5052198092Srdivacky 5053193326Sed // Find the message function name. 5054193326Sed // FIXME. This is too much work to get the ABI-specific result type needed to 5055193326Sed // find the message name. 5056198092Srdivacky const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, 5057198092Srdivacky llvm::SmallVector<QualType, 16>()); 5058193326Sed llvm::Constant *Fn = 0; 5059193326Sed std::string Name("\01l_"); 5060193326Sed if (CGM.ReturnTypeUsesSret(FnInfo)) { 5061193326Sed#if 0 5062193326Sed // unlike what is documented. gcc never generates this API!! 5063193326Sed if (Receiver->getType() == ObjCTypes.ObjectPtrTy) { 5064193326Sed Fn = ObjCTypes.getMessageSendIdStretFixupFn(); 5065193326Sed // FIXME. Is there a better way of getting these names. 5066193326Sed // They are available in RuntimeFunctions vector pair. 5067193326Sed Name += "objc_msgSendId_stret_fixup"; 5068198092Srdivacky } else 5069193326Sed#endif 5070198092Srdivacky if (IsSuper) { 5071193326Sed Fn = ObjCTypes.getMessageSendSuper2StretFixupFn(); 5072193326Sed Name += "objc_msgSendSuper2_stret_fixup"; 5073198092Srdivacky } else { 5074198092Srdivacky Fn = ObjCTypes.getMessageSendStretFixupFn(); 5075198092Srdivacky Name += "objc_msgSend_stret_fixup"; 5076198092Srdivacky } 5077198092Srdivacky } else if (!IsSuper && ResultType->isFloatingType()) { 5078195099Sed if (ResultType->isSpecificBuiltinType(BuiltinType::LongDouble)) { 5079195099Sed Fn = ObjCTypes.getMessageSendFpretFixupFn(); 5080195099Sed Name += "objc_msgSend_fpret_fixup"; 5081198092Srdivacky } else { 5082195099Sed Fn = ObjCTypes.getMessageSendFixupFn(); 5083195099Sed Name += "objc_msgSend_fixup"; 5084193326Sed } 5085198092Srdivacky } else { 5086193326Sed#if 0 5087193326Sed// unlike what is documented. gcc never generates this API!! 5088193326Sed if (Receiver->getType() == ObjCTypes.ObjectPtrTy) { 5089193326Sed Fn = ObjCTypes.getMessageSendIdFixupFn(); 5090193326Sed Name += "objc_msgSendId_fixup"; 5091198092Srdivacky } else 5092193326Sed#endif 5093198092Srdivacky if (IsSuper) { 5094193326Sed Fn = ObjCTypes.getMessageSendSuper2FixupFn(); 5095193326Sed Name += "objc_msgSendSuper2_fixup"; 5096198092Srdivacky } else { 5097198092Srdivacky Fn = ObjCTypes.getMessageSendFixupFn(); 5098198092Srdivacky Name += "objc_msgSend_fixup"; 5099198092Srdivacky } 5100193326Sed } 5101193326Sed assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend"); 5102193326Sed Name += '_'; 5103193326Sed std::string SelName(Sel.getAsString()); 5104193326Sed // Replace all ':' in selector name with '_' ouch! 5105198092Srdivacky for (unsigned i = 0; i < SelName.size(); i++) 5106193326Sed if (SelName[i] == ':') 5107193326Sed SelName[i] = '_'; 5108193326Sed Name += SelName; 5109193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 5110193326Sed if (!GV) { 5111193326Sed // Build message ref table entry. 5112193326Sed std::vector<llvm::Constant*> Values(2); 5113193326Sed Values[0] = Fn; 5114193326Sed Values[1] = GetMethodVarName(Sel); 5115198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 5116198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 5117193326Sed llvm::GlobalValue::WeakAnyLinkage, 5118193326Sed Init, 5119198092Srdivacky Name); 5120193326Sed GV->setVisibility(llvm::GlobalValue::HiddenVisibility); 5121193326Sed GV->setAlignment(16); 5122193326Sed GV->setSection("__DATA, __objc_msgrefs, coalesced"); 5123193326Sed } 5124193326Sed llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy); 5125198092Srdivacky 5126193326Sed CallArgList ActualArgs; 5127193326Sed ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty)); 5128198092Srdivacky ActualArgs.push_back(std::make_pair(RValue::get(Arg1), 5129193326Sed ObjCTypes.MessageRefCPtrTy)); 5130193326Sed ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); 5131193326Sed const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs); 5132193326Sed llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0); 5133193326Sed Callee = CGF.Builder.CreateLoad(Callee); 5134193326Sed const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true); 5135193326Sed Callee = CGF.Builder.CreateBitCast(Callee, 5136193326Sed llvm::PointerType::getUnqual(FTy)); 5137193326Sed return CGF.EmitCall(FnInfo1, Callee, ActualArgs); 5138193326Sed} 5139193326Sed 5140193326Sed/// Generate code for a message send expression in the nonfragile abi. 5141198092SrdivackyCodeGen::RValue 5142198092SrdivackyCGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 5143198092Srdivacky QualType ResultType, 5144198092Srdivacky Selector Sel, 5145198092Srdivacky llvm::Value *Receiver, 5146198092Srdivacky bool IsClassMessage, 5147198092Srdivacky const CallArgList &CallArgs, 5148198092Srdivacky const ObjCMethodDecl *Method) { 5149193326Sed return LegacyDispatchedSelector(Sel) 5150198092Srdivacky ? EmitLegacyMessageSend(CGF, ResultType, EmitSelector(CGF.Builder, Sel), 5151198092Srdivacky Receiver, CGF.getContext().getObjCIdType(), 5152198092Srdivacky false, CallArgs, Method, ObjCTypes) 5153198092Srdivacky : EmitMessageSend(CGF, ResultType, Sel, 5154198092Srdivacky Receiver, CGF.getContext().getObjCIdType(), 5155198092Srdivacky false, CallArgs); 5156193326Sed} 5157193326Sed 5158193326Sedllvm::GlobalVariable * 5159193326SedCGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) { 5160193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 5161193326Sed 5162193326Sed if (!GV) { 5163198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy, 5164198092Srdivacky false, llvm::GlobalValue::ExternalLinkage, 5165198092Srdivacky 0, Name); 5166193326Sed } 5167193326Sed 5168193326Sed return GV; 5169193326Sed} 5170193326Sed 5171198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder, 5172198092Srdivacky const ObjCInterfaceDecl *ID) { 5173193326Sed llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()]; 5174198092Srdivacky 5175193326Sed if (!Entry) { 5176193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5177193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 5178198092Srdivacky Entry = 5179198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, 5180198092Srdivacky false, llvm::GlobalValue::InternalLinkage, 5181198092Srdivacky ClassGV, 5182198092Srdivacky "\01L_OBJC_CLASSLIST_REFERENCES_$_"); 5183193326Sed Entry->setAlignment( 5184198092Srdivacky CGM.getTargetData().getPrefTypeAlignment( 5185198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 5186193326Sed Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip"); 5187198092Srdivacky CGM.AddUsedGlobal(Entry); 5188193326Sed } 5189198092Srdivacky 5190193326Sed return Builder.CreateLoad(Entry, false, "tmp"); 5191193326Sed} 5192193326Sed 5193193326Sedllvm::Value * 5194198092SrdivackyCGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder, 5195193326Sed const ObjCInterfaceDecl *ID) { 5196193326Sed llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()]; 5197198092Srdivacky 5198193326Sed if (!Entry) { 5199193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5200193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 5201198092Srdivacky Entry = 5202198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, 5203198092Srdivacky false, llvm::GlobalValue::InternalLinkage, 5204198092Srdivacky ClassGV, 5205198092Srdivacky "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); 5206193326Sed Entry->setAlignment( 5207198092Srdivacky CGM.getTargetData().getPrefTypeAlignment( 5208198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 5209193326Sed Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); 5210198092Srdivacky CGM.AddUsedGlobal(Entry); 5211193326Sed } 5212198092Srdivacky 5213193326Sed return Builder.CreateLoad(Entry, false, "tmp"); 5214193326Sed} 5215193326Sed 5216193326Sed/// EmitMetaClassRef - Return a Value * of the address of _class_t 5217193326Sed/// meta-data 5218193326Sed/// 5219198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder, 5220198092Srdivacky const ObjCInterfaceDecl *ID) { 5221193326Sed llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; 5222193326Sed if (Entry) 5223193326Sed return Builder.CreateLoad(Entry, false, "tmp"); 5224198092Srdivacky 5225193326Sed std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString()); 5226193326Sed llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName); 5227198092Srdivacky Entry = 5228198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false, 5229193326Sed llvm::GlobalValue::InternalLinkage, 5230198092Srdivacky MetaClassGV, 5231198092Srdivacky "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); 5232193326Sed Entry->setAlignment( 5233198092Srdivacky CGM.getTargetData().getPrefTypeAlignment( 5234198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 5235198092Srdivacky 5236193326Sed Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); 5237198092Srdivacky CGM.AddUsedGlobal(Entry); 5238198092Srdivacky 5239193326Sed return Builder.CreateLoad(Entry, false, "tmp"); 5240193326Sed} 5241193326Sed 5242193326Sed/// GetClass - Return a reference to the class for the given interface 5243193326Sed/// decl. 5244193326Sedllvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder, 5245193326Sed const ObjCInterfaceDecl *ID) { 5246199482Srdivacky if (ID->hasAttr<WeakImportAttr>()) { 5247199482Srdivacky std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5248199482Srdivacky llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 5249199482Srdivacky ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5250199482Srdivacky } 5251199482Srdivacky 5252193326Sed return EmitClassRef(Builder, ID); 5253193326Sed} 5254193326Sed 5255193326Sed/// Generates a message send where the super is the receiver. This is 5256193326Sed/// a message send to self with special delivery semantics indicating 5257193326Sed/// which class's method should be called. 5258193326SedCodeGen::RValue 5259193326SedCGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 5260198092Srdivacky QualType ResultType, 5261198092Srdivacky Selector Sel, 5262198092Srdivacky const ObjCInterfaceDecl *Class, 5263198092Srdivacky bool isCategoryImpl, 5264198092Srdivacky llvm::Value *Receiver, 5265198092Srdivacky bool IsClassMessage, 5266198092Srdivacky const CodeGen::CallArgList &CallArgs, 5267198092Srdivacky const ObjCMethodDecl *Method) { 5268193326Sed // ... 5269193326Sed // Create and init a super structure; this is a (receiver, class) 5270193326Sed // pair we will pass to objc_msgSendSuper. 5271193326Sed llvm::Value *ObjCSuper = 5272193326Sed CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); 5273198092Srdivacky 5274193326Sed llvm::Value *ReceiverAsObject = 5275193326Sed CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); 5276193326Sed CGF.Builder.CreateStore(ReceiverAsObject, 5277193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 5278198092Srdivacky 5279193326Sed // If this is a class message the metaclass is passed as the target. 5280193326Sed llvm::Value *Target; 5281193326Sed if (IsClassMessage) { 5282193326Sed if (isCategoryImpl) { 5283193326Sed // Message sent to "super' in a class method defined in 5284193326Sed // a category implementation. 5285193326Sed Target = EmitClassRef(CGF.Builder, Class); 5286193326Sed Target = CGF.Builder.CreateStructGEP(Target, 0); 5287193326Sed Target = CGF.Builder.CreateLoad(Target); 5288198092Srdivacky } else 5289193326Sed Target = EmitMetaClassRef(CGF.Builder, Class); 5290198092Srdivacky } else 5291193326Sed Target = EmitSuperClassRef(CGF.Builder, Class); 5292198092Srdivacky 5293193326Sed // FIXME: We shouldn't need to do this cast, rectify the ASTContext and 5294193326Sed // ObjCTypes types. 5295193326Sed const llvm::Type *ClassTy = 5296193326Sed CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); 5297193326Sed Target = CGF.Builder.CreateBitCast(Target, ClassTy); 5298193326Sed CGF.Builder.CreateStore(Target, 5299193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 5300198092Srdivacky 5301193326Sed return (LegacyDispatchedSelector(Sel)) 5302198092Srdivacky ? EmitLegacyMessageSend(CGF, ResultType,EmitSelector(CGF.Builder, Sel), 5303198092Srdivacky ObjCSuper, ObjCTypes.SuperPtrCTy, 5304198092Srdivacky true, CallArgs, Method, ObjCTypes) 5305198092Srdivacky : EmitMessageSend(CGF, ResultType, Sel, 5306198092Srdivacky ObjCSuper, ObjCTypes.SuperPtrCTy, 5307198092Srdivacky true, CallArgs); 5308193326Sed} 5309193326Sed 5310198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder, 5311193326Sed Selector Sel) { 5312193326Sed llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; 5313198092Srdivacky 5314193326Sed if (!Entry) { 5315198092Srdivacky llvm::Constant *Casted = 5316198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), 5317198092Srdivacky ObjCTypes.SelectorPtrTy); 5318198092Srdivacky Entry = 5319198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false, 5320198092Srdivacky llvm::GlobalValue::InternalLinkage, 5321198092Srdivacky Casted, "\01L_OBJC_SELECTOR_REFERENCES_"); 5322193326Sed Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip"); 5323198092Srdivacky CGM.AddUsedGlobal(Entry); 5324193326Sed } 5325198092Srdivacky 5326193326Sed return Builder.CreateLoad(Entry, false, "tmp"); 5327193326Sed} 5328193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. 5329198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t) 5330193326Sed/// 5331193326Sedvoid CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 5332198092Srdivacky llvm::Value *src, 5333198092Srdivacky llvm::Value *dst, 5334198092Srdivacky llvm::Value *ivarOffset) { 5335193326Sed const llvm::Type * SrcTy = src->getType(); 5336193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5337193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5338193326Sed assert(Size <= 8 && "does not support size > 8"); 5339193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5340193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5341193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5342193326Sed } 5343193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5344193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5345198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(), 5346198092Srdivacky src, dst, ivarOffset); 5347193326Sed return; 5348193326Sed} 5349193326Sed 5350193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. 5351193326Sed/// objc_assign_strongCast (id src, id *dst) 5352193326Sed/// 5353193326Sedvoid CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( 5354198092Srdivacky CodeGen::CodeGenFunction &CGF, 5355198092Srdivacky llvm::Value *src, llvm::Value *dst) { 5356193326Sed const llvm::Type * SrcTy = src->getType(); 5357193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5358193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5359193326Sed assert(Size <= 8 && "does not support size > 8"); 5360193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5361198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5362193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5363193326Sed } 5364193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5365193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5366193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(), 5367193326Sed src, dst, "weakassign"); 5368193326Sed return; 5369193326Sed} 5370193326Sed 5371198092Srdivackyvoid CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( 5372198092Srdivacky CodeGen::CodeGenFunction &CGF, 5373198092Srdivacky llvm::Value *DestPtr, 5374198092Srdivacky llvm::Value *SrcPtr, 5375198092Srdivacky QualType Ty) { 5376198092Srdivacky // Get size info for this aggregate. 5377198092Srdivacky std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty); 5378198092Srdivacky unsigned long size = TypeInfo.first/8; 5379198092Srdivacky SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); 5380198092Srdivacky DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); 5381198092Srdivacky llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size); 5382198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(), 5383198092Srdivacky DestPtr, SrcPtr, N); 5384198092Srdivacky return; 5385198092Srdivacky} 5386198092Srdivacky 5387193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak 5388193326Sed/// object: objc_read_weak (id *src) 5389193326Sed/// 5390193326Sedllvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( 5391198092Srdivacky CodeGen::CodeGenFunction &CGF, 5392198092Srdivacky llvm::Value *AddrWeakObj) { 5393193326Sed const llvm::Type* DestTy = 5394198092Srdivacky cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); 5395198092Srdivacky AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy); 5396193326Sed llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(), 5397193326Sed AddrWeakObj, "weakread"); 5398193326Sed read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); 5399193326Sed return read_weak; 5400193326Sed} 5401193326Sed 5402193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. 5403193326Sed/// objc_assign_weak (id src, id *dst) 5404193326Sed/// 5405193326Sedvoid CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 5406198092Srdivacky llvm::Value *src, llvm::Value *dst) { 5407193326Sed const llvm::Type * SrcTy = src->getType(); 5408193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5409193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5410193326Sed assert(Size <= 8 && "does not support size > 8"); 5411193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5412193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5413193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5414193326Sed } 5415193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5416193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5417193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(), 5418193326Sed src, dst, "weakassign"); 5419193326Sed return; 5420193326Sed} 5421193326Sed 5422193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. 5423193326Sed/// objc_assign_global (id src, id *dst) 5424193326Sed/// 5425193326Sedvoid CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 5426198092Srdivacky llvm::Value *src, llvm::Value *dst) { 5427193326Sed const llvm::Type * SrcTy = src->getType(); 5428193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5429193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5430193326Sed assert(Size <= 8 && "does not support size > 8"); 5431193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5432193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5433193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5434193326Sed } 5435193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5436193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5437193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(), 5438193326Sed src, dst, "globalassign"); 5439193326Sed return; 5440193326Sed} 5441193326Sed 5442198092Srdivackyvoid 5443193326SedCGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 5444193326Sed const Stmt &S) { 5445193326Sed bool isTry = isa<ObjCAtTryStmt>(S); 5446193326Sed llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); 5447193326Sed llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest(); 5448193326Sed llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); 5449193326Sed llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally"); 5450193326Sed llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); 5451193326Sed llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); 5452193326Sed 5453193326Sed // For @synchronized, call objc_sync_enter(sync.expr). The 5454193326Sed // evaluation of the expression must occur before we enter the 5455193326Sed // @synchronized. We can safely avoid a temp here because jumps into 5456193326Sed // @synchronized are illegal & this will dominate uses. 5457193326Sed llvm::Value *SyncArg = 0; 5458193326Sed if (!isTry) { 5459198092Srdivacky SyncArg = 5460193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 5461193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); 5462193326Sed CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg); 5463193326Sed } 5464193326Sed 5465193326Sed // Push an EH context entry, used for handling rethrows and jumps 5466193326Sed // through finally. 5467193326Sed CGF.PushCleanupBlock(FinallyBlock); 5468193326Sed 5469193326Sed CGF.setInvokeDest(TryHandler); 5470193326Sed 5471193326Sed CGF.EmitBlock(TryBlock); 5472198092Srdivacky CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() 5473198092Srdivacky : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); 5474193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 5475198092Srdivacky 5476193326Sed // Emit the exception handler. 5477193326Sed 5478193326Sed CGF.EmitBlock(TryHandler); 5479193326Sed 5480198092Srdivacky llvm::Value *llvm_eh_exception = 5481193326Sed CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 5482198092Srdivacky llvm::Value *llvm_eh_selector = 5483198092Srdivacky CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 5484198092Srdivacky llvm::Value *llvm_eh_typeid_for = 5485198092Srdivacky CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); 5486193326Sed llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 5487193326Sed llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow"); 5488193326Sed 5489193326Sed llvm::SmallVector<llvm::Value*, 8> SelectorArgs; 5490193326Sed SelectorArgs.push_back(Exc); 5491193326Sed SelectorArgs.push_back(ObjCTypes.getEHPersonalityPtr()); 5492193326Sed 5493193326Sed // Construct the lists of (type, catch body) to handle. 5494193326Sed llvm::SmallVector<std::pair<const ParmVarDecl*, const Stmt*>, 8> Handlers; 5495193326Sed bool HasCatchAll = false; 5496193326Sed if (isTry) { 5497193326Sed if (const ObjCAtCatchStmt* CatchStmt = 5498193326Sed cast<ObjCAtTryStmt>(S).getCatchStmts()) { 5499193326Sed for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) { 5500193326Sed const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); 5501193326Sed Handlers.push_back(std::make_pair(CatchDecl, CatchStmt->getCatchBody())); 5502193326Sed 5503193326Sed // catch(...) always matches. 5504193326Sed if (!CatchDecl) { 5505193326Sed // Use i8* null here to signal this is a catch all, not a cleanup. 5506193326Sed llvm::Value *Null = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 5507193326Sed SelectorArgs.push_back(Null); 5508193326Sed HasCatchAll = true; 5509193326Sed break; 5510193326Sed } 5511193326Sed 5512198092Srdivacky if (CatchDecl->getType()->isObjCIdType() || 5513193326Sed CatchDecl->getType()->isObjCQualifiedIdType()) { 5514198092Srdivacky llvm::Value *IDEHType = 5515193326Sed CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id"); 5516193326Sed if (!IDEHType) 5517198092Srdivacky IDEHType = 5518198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, 5519198092Srdivacky false, 5520193326Sed llvm::GlobalValue::ExternalLinkage, 5521198092Srdivacky 0, "OBJC_EHTYPE_id"); 5522193326Sed SelectorArgs.push_back(IDEHType); 5523198092Srdivacky } else { 5524198092Srdivacky // All other types should be Objective-C interface pointer types. 5525198092Srdivacky const ObjCObjectPointerType *PT = 5526198092Srdivacky CatchDecl->getType()->getAs<ObjCObjectPointerType>(); 5527198092Srdivacky assert(PT && "Invalid @catch type."); 5528198092Srdivacky const ObjCInterfaceType *IT = PT->getInterfaceType(); 5529198092Srdivacky assert(IT && "Invalid @catch type."); 5530198092Srdivacky llvm::Value *EHType = GetInterfaceEHType(IT->getDecl(), false); 5531198092Srdivacky SelectorArgs.push_back(EHType); 5532198092Srdivacky } 5533193326Sed } 5534193326Sed } 5535193326Sed } 5536193326Sed 5537193326Sed // We use a cleanup unless there was already a catch all. 5538193326Sed if (!HasCatchAll) { 5539198092Srdivacky // Even though this is a cleanup, treat it as a catch all to avoid the C++ 5540198092Srdivacky // personality behavior of terminating the process if only cleanups are 5541198092Srdivacky // found in the exception handling stack. 5542198092Srdivacky SelectorArgs.push_back(llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy)); 5543193326Sed Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0)); 5544193326Sed } 5545198092Srdivacky 5546198092Srdivacky llvm::Value *Selector = 5547198092Srdivacky CGF.Builder.CreateCall(llvm_eh_selector, 5548193326Sed SelectorArgs.begin(), SelectorArgs.end(), 5549193326Sed "selector"); 5550193326Sed for (unsigned i = 0, e = Handlers.size(); i != e; ++i) { 5551193326Sed const ParmVarDecl *CatchParam = Handlers[i].first; 5552193326Sed const Stmt *CatchBody = Handlers[i].second; 5553193326Sed 5554193326Sed llvm::BasicBlock *Next = 0; 5555193326Sed 5556193326Sed // The last handler always matches. 5557193326Sed if (i + 1 != e) { 5558193326Sed assert(CatchParam && "Only last handler can be a catch all."); 5559193326Sed 5560193326Sed llvm::BasicBlock *Match = CGF.createBasicBlock("match"); 5561193326Sed Next = CGF.createBasicBlock("catch.next"); 5562198092Srdivacky llvm::Value *Id = 5563198092Srdivacky CGF.Builder.CreateCall(llvm_eh_typeid_for, 5564193326Sed CGF.Builder.CreateBitCast(SelectorArgs[i+2], 5565193326Sed ObjCTypes.Int8PtrTy)); 5566193326Sed CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(Selector, Id), 5567193326Sed Match, Next); 5568193326Sed 5569193326Sed CGF.EmitBlock(Match); 5570193326Sed } 5571198092Srdivacky 5572193326Sed if (CatchBody) { 5573193326Sed llvm::BasicBlock *MatchEnd = CGF.createBasicBlock("match.end"); 5574193326Sed llvm::BasicBlock *MatchHandler = CGF.createBasicBlock("match.handler"); 5575193326Sed 5576193326Sed // Cleanups must call objc_end_catch. 5577198092Srdivacky // 5578193326Sed // FIXME: It seems incorrect for objc_begin_catch to be inside this 5579193326Sed // context, but this matches gcc. 5580193326Sed CGF.PushCleanupBlock(MatchEnd); 5581193326Sed CGF.setInvokeDest(MatchHandler); 5582198092Srdivacky 5583198092Srdivacky llvm::Value *ExcObject = 5584193326Sed CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), Exc); 5585193326Sed 5586193326Sed // Bind the catch parameter if it exists. 5587193326Sed if (CatchParam) { 5588198092Srdivacky ExcObject = 5589198092Srdivacky CGF.Builder.CreateBitCast(ExcObject, 5590193326Sed CGF.ConvertType(CatchParam->getType())); 5591193326Sed // CatchParam is a ParmVarDecl because of the grammar 5592193326Sed // construction used to handle this, but for codegen purposes 5593193326Sed // we treat this as a local decl. 5594193326Sed CGF.EmitLocalBlockVarDecl(*CatchParam); 5595193326Sed CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(CatchParam)); 5596193326Sed } 5597193326Sed 5598193326Sed CGF.ObjCEHValueStack.push_back(ExcObject); 5599193326Sed CGF.EmitStmt(CatchBody); 5600193326Sed CGF.ObjCEHValueStack.pop_back(); 5601193326Sed 5602193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 5603193326Sed 5604193326Sed CGF.EmitBlock(MatchHandler); 5605193326Sed 5606193326Sed llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 5607193326Sed // We are required to emit this call to satisfy LLVM, even 5608193326Sed // though we don't use the result. 5609193326Sed llvm::SmallVector<llvm::Value*, 8> Args; 5610193326Sed Args.push_back(Exc); 5611193326Sed Args.push_back(ObjCTypes.getEHPersonalityPtr()); 5612198092Srdivacky Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 5613193326Sed 0)); 5614198092Srdivacky CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end()); 5615193326Sed CGF.Builder.CreateStore(Exc, RethrowPtr); 5616193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 5617193326Sed 5618193326Sed CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); 5619198092Srdivacky 5620193326Sed CGF.EmitBlock(MatchEnd); 5621193326Sed 5622193326Sed // Unfortunately, we also have to generate another EH frame here 5623193326Sed // in case this throws. 5624198092Srdivacky llvm::BasicBlock *MatchEndHandler = 5625193326Sed CGF.createBasicBlock("match.end.handler"); 5626193326Sed llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); 5627198092Srdivacky CGF.Builder.CreateInvoke(ObjCTypes.getObjCEndCatchFn(), 5628193326Sed Cont, MatchEndHandler, 5629193326Sed Args.begin(), Args.begin()); 5630193326Sed 5631193326Sed CGF.EmitBlock(Cont); 5632193326Sed if (Info.SwitchBlock) 5633193326Sed CGF.EmitBlock(Info.SwitchBlock); 5634193326Sed if (Info.EndBlock) 5635193326Sed CGF.EmitBlock(Info.EndBlock); 5636193326Sed 5637193326Sed CGF.EmitBlock(MatchEndHandler); 5638193326Sed Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 5639193326Sed // We are required to emit this call to satisfy LLVM, even 5640193326Sed // though we don't use the result. 5641193326Sed Args.clear(); 5642193326Sed Args.push_back(Exc); 5643193326Sed Args.push_back(ObjCTypes.getEHPersonalityPtr()); 5644198092Srdivacky Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 5645193326Sed 0)); 5646198092Srdivacky CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end()); 5647193326Sed CGF.Builder.CreateStore(Exc, RethrowPtr); 5648193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 5649193326Sed 5650193326Sed if (Next) 5651193326Sed CGF.EmitBlock(Next); 5652193326Sed } else { 5653193326Sed assert(!Next && "catchup should be last handler."); 5654193326Sed 5655193326Sed CGF.Builder.CreateStore(Exc, RethrowPtr); 5656193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 5657193326Sed } 5658193326Sed } 5659193326Sed 5660193326Sed // Pop the cleanup entry, the @finally is outside this cleanup 5661193326Sed // scope. 5662193326Sed CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); 5663193326Sed CGF.setInvokeDest(PrevLandingPad); 5664193326Sed 5665193326Sed CGF.EmitBlock(FinallyBlock); 5666193326Sed 5667193326Sed if (isTry) { 5668198092Srdivacky if (const ObjCAtFinallyStmt* FinallyStmt = 5669193326Sed cast<ObjCAtTryStmt>(S).getFinallyStmt()) 5670193326Sed CGF.EmitStmt(FinallyStmt->getFinallyBody()); 5671193326Sed } else { 5672193326Sed // Emit 'objc_sync_exit(expr)' as finally's sole statement for 5673193326Sed // @synchronized. 5674193326Sed CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg); 5675193326Sed } 5676193326Sed 5677193326Sed if (Info.SwitchBlock) 5678193326Sed CGF.EmitBlock(Info.SwitchBlock); 5679193326Sed if (Info.EndBlock) 5680193326Sed CGF.EmitBlock(Info.EndBlock); 5681193326Sed 5682193326Sed // Branch around the rethrow code. 5683193326Sed CGF.EmitBranch(FinallyEnd); 5684193326Sed 5685193326Sed CGF.EmitBlock(FinallyRethrow); 5686198092Srdivacky CGF.Builder.CreateCall(ObjCTypes.getUnwindResumeOrRethrowFn(), 5687193326Sed CGF.Builder.CreateLoad(RethrowPtr)); 5688193326Sed CGF.Builder.CreateUnreachable(); 5689198092Srdivacky 5690193326Sed CGF.EmitBlock(FinallyEnd); 5691193326Sed} 5692193326Sed 5693193326Sed/// EmitThrowStmt - Generate code for a throw statement. 5694193326Sedvoid CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 5695193326Sed const ObjCAtThrowStmt &S) { 5696198092Srdivacky llvm::Value *Exception; 5697193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 5698193326Sed Exception = CGF.EmitScalarExpr(ThrowExpr); 5699193326Sed } else { 5700198092Srdivacky assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && 5701193326Sed "Unexpected rethrow outside @catch block."); 5702193326Sed Exception = CGF.ObjCEHValueStack.back(); 5703193326Sed } 5704193326Sed 5705198092Srdivacky llvm::Value *ExceptionAsObject = 5706193326Sed CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp"); 5707193326Sed llvm::BasicBlock *InvokeDest = CGF.getInvokeDest(); 5708193326Sed if (InvokeDest) { 5709193326Sed llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); 5710193326Sed CGF.Builder.CreateInvoke(ObjCTypes.getExceptionThrowFn(), 5711193326Sed Cont, InvokeDest, 5712193326Sed &ExceptionAsObject, &ExceptionAsObject + 1); 5713193326Sed CGF.EmitBlock(Cont); 5714193326Sed } else 5715198092Srdivacky CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject); 5716193326Sed CGF.Builder.CreateUnreachable(); 5717193326Sed 5718193326Sed // Clear the insertion point to indicate we are in unreachable code. 5719193326Sed CGF.Builder.ClearInsertionPoint(); 5720193326Sed} 5721193326Sed 5722193326Sedllvm::Value * 5723198092SrdivackyCGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, 5724193326Sed bool ForDefinition) { 5725193326Sed llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()]; 5726193326Sed 5727193326Sed // If we don't need a definition, return the entry if found or check 5728193326Sed // if we use an external reference. 5729193326Sed if (!ForDefinition) { 5730193326Sed if (Entry) 5731193326Sed return Entry; 5732193326Sed 5733193326Sed // If this type (or a super class) has the __objc_exception__ 5734193326Sed // attribute, emit an external reference. 5735194613Sed if (hasObjCExceptionAttribute(CGM.getContext(), ID)) 5736198092Srdivacky return Entry = 5737198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, 5738193326Sed llvm::GlobalValue::ExternalLinkage, 5739198092Srdivacky 0, 5740198398Srdivacky ("OBJC_EHTYPE_$_" + 5741198092Srdivacky ID->getIdentifier()->getName())); 5742193326Sed } 5743198092Srdivacky 5744193326Sed // Otherwise we need to either make a new entry or fill in the 5745193326Sed // initializer. 5746193326Sed assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition"); 5747193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5748193326Sed std::string VTableName = "objc_ehtype_vtable"; 5749198092Srdivacky llvm::GlobalVariable *VTableGV = 5750193326Sed CGM.getModule().getGlobalVariable(VTableName); 5751193326Sed if (!VTableGV) 5752198092Srdivacky VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, 5753198092Srdivacky false, 5754193326Sed llvm::GlobalValue::ExternalLinkage, 5755198092Srdivacky 0, VTableName); 5756193326Sed 5757198092Srdivacky llvm::Value *VTableIdx = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2); 5758193326Sed 5759193326Sed std::vector<llvm::Constant*> Values(3); 5760193326Sed Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1); 5761193326Sed Values[1] = GetClassName(ID->getIdentifier()); 5762193326Sed Values[2] = GetClassGlobal(ClassName); 5763198092Srdivacky llvm::Constant *Init = 5764198092Srdivacky llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values); 5765193326Sed 5766193326Sed if (Entry) { 5767193326Sed Entry->setInitializer(Init); 5768193326Sed } else { 5769198092Srdivacky Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, 5770193326Sed llvm::GlobalValue::WeakAnyLinkage, 5771198092Srdivacky Init, 5772198398Srdivacky ("OBJC_EHTYPE_$_" + 5773198092Srdivacky ID->getIdentifier()->getName())); 5774193326Sed } 5775193326Sed 5776193326Sed if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden) 5777193326Sed Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); 5778193326Sed Entry->setAlignment(8); 5779193326Sed 5780193326Sed if (ForDefinition) { 5781193326Sed Entry->setSection("__DATA,__objc_const"); 5782193326Sed Entry->setLinkage(llvm::GlobalValue::ExternalLinkage); 5783193326Sed } else { 5784193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 5785193326Sed } 5786193326Sed 5787193326Sed return Entry; 5788193326Sed} 5789198092Srdivacky 5790193326Sed/* *** */ 5791193326Sed 5792193326SedCodeGen::CGObjCRuntime * 5793193326SedCodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) { 5794193326Sed return new CGObjCMac(CGM); 5795193326Sed} 5796193326Sed 5797193326SedCodeGen::CGObjCRuntime * 5798193326SedCodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) { 5799193326Sed return new CGObjCNonFragileABIMac(CGM); 5800193326Sed} 5801