CGObjCMac.cpp revision 203955
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" 24203955Srdivacky#include "clang/CodeGen/CodeGenOptions.h" 25193326Sed 26193326Sed#include "llvm/Intrinsics.h" 27198092Srdivacky#include "llvm/LLVMContext.h" 28193326Sed#include "llvm/Module.h" 29193326Sed#include "llvm/ADT/DenseSet.h" 30198092Srdivacky#include "llvm/ADT/SetVector.h" 31198092Srdivacky#include "llvm/ADT/SmallString.h" 32200583Srdivacky#include "llvm/ADT/SmallPtrSet.h" 33198092Srdivacky#include "llvm/Support/raw_ostream.h" 34193326Sed#include "llvm/Target/TargetData.h" 35198092Srdivacky#include <cstdio> 36193326Sed 37193326Sedusing namespace clang; 38193326Sedusing namespace CodeGen; 39193326Sed 40193326Sed// Common CGObjCRuntime functions, these don't belong here, but they 41193326Sed// don't belong in CGObjCRuntime either so we will live with it for 42193326Sed// now. 43193326Sed 44198092Srdivacky/// FindIvarInterface - Find the interface containing the ivar. 45193326Sed/// 46193326Sed/// FIXME: We shouldn't need to do this, the containing context should 47193326Sed/// be fixed. 48193326Sedstatic const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, 49193326Sed const ObjCInterfaceDecl *OID, 50193326Sed const ObjCIvarDecl *OIVD, 51193326Sed unsigned &Index) { 52193326Sed // FIXME: The index here is closely tied to how 53193326Sed // ASTContext::getObjCLayout is implemented. This should be fixed to 54193326Sed // get the information from the layout directly. 55193326Sed Index = 0; 56193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; 57193576Sed Context.ShallowCollectObjCIvars(OID, Ivars); 58193326Sed for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { 59193326Sed if (OIVD == Ivars[k]) 60193326Sed return OID; 61193326Sed ++Index; 62193326Sed } 63198092Srdivacky 64193326Sed // Otherwise check in the super class. 65193326Sed if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 66193326Sed return FindIvarInterface(Context, Super, OIVD, Index); 67198092Srdivacky 68193326Sed return 0; 69193326Sed} 70193326Sed 71193326Sedstatic uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, 72193326Sed const ObjCInterfaceDecl *OID, 73193326Sed const ObjCImplementationDecl *ID, 74193326Sed const ObjCIvarDecl *Ivar) { 75193326Sed unsigned Index; 76198092Srdivacky const ObjCInterfaceDecl *Container = 77193326Sed FindIvarInterface(CGM.getContext(), OID, Ivar, Index); 78193326Sed assert(Container && "Unable to find ivar container"); 79193326Sed 80193326Sed // If we know have an implementation (and the ivar is in it) then 81193326Sed // look up in the implementation layout. 82198092Srdivacky const ASTRecordLayout *RL; 83193326Sed if (ID && ID->getClassInterface() == Container) 84193326Sed RL = &CGM.getContext().getASTObjCImplementationLayout(ID); 85193326Sed else 86193326Sed RL = &CGM.getContext().getASTObjCInterfaceLayout(Container); 87193326Sed return RL->getFieldOffset(Index); 88193326Sed} 89193326Sed 90193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, 91193326Sed const ObjCInterfaceDecl *OID, 92193326Sed const ObjCIvarDecl *Ivar) { 93193326Sed return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8; 94193326Sed} 95193326Sed 96193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, 97193326Sed const ObjCImplementationDecl *OID, 98193326Sed const ObjCIvarDecl *Ivar) { 99193326Sed return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8; 100193326Sed} 101193326Sed 102193326SedLValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, 103193326Sed const ObjCInterfaceDecl *OID, 104193326Sed llvm::Value *BaseValue, 105193326Sed const ObjCIvarDecl *Ivar, 106193326Sed unsigned CVRQualifiers, 107193326Sed llvm::Value *Offset) { 108193326Sed // Compute (type*) ( (char *) BaseValue + Offset) 109198092Srdivacky const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 110193326Sed QualType IvarTy = Ivar->getType(); 111193326Sed const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); 112193326Sed llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr); 113193326Sed V = CGF.Builder.CreateGEP(V, Offset, "add.ptr"); 114193326Sed V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); 115198092Srdivacky 116198092Srdivacky Qualifiers Quals = CGF.MakeQualifiers(IvarTy); 117198092Srdivacky Quals.addCVRQualifiers(CVRQualifiers); 118198092Srdivacky 119193326Sed if (Ivar->isBitField()) { 120193326Sed // We need to compute the bit offset for the bit-field, the offset 121193326Sed // is to the byte. Note, there is a subtle invariant here: we can 122193326Sed // only call this routine on non-sythesized ivars but we may be 123193326Sed // called for synthesized ivars. However, a synthesized ivar can 124193326Sed // never be a bit-field so this is safe. 125193326Sed uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar) % 8; 126193326Sed 127193326Sed uint64_t BitFieldSize = 128193326Sed Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); 129193326Sed return LValue::MakeBitfield(V, BitOffset, BitFieldSize, 130193326Sed IvarTy->isSignedIntegerType(), 131198092Srdivacky Quals.getCVRQualifiers()); 132193326Sed } 133193326Sed 134198092Srdivacky 135198092Srdivacky LValue LV = LValue::MakeAddr(V, Quals); 136193326Sed return LV; 137193326Sed} 138193326Sed 139193326Sed/// 140193326Sed 141193326Sednamespace { 142193326Sed 143198092Srdivackytypedef std::vector<llvm::Constant*> ConstantVector; 144193326Sed 145198092Srdivacky// FIXME: We should find a nicer way to make the labels for metadata, string 146198092Srdivacky// concatenation is lame. 147193326Sed 148193326Sedclass ObjCCommonTypesHelper { 149198092Srdivackyprotected: 150198092Srdivacky llvm::LLVMContext &VMContext; 151198092Srdivacky 152193326Sedprivate: 153193326Sed llvm::Constant *getMessageSendFn() const { 154193326Sed // id objc_msgSend (id, SEL, ...) 155193326Sed std::vector<const llvm::Type*> Params; 156193326Sed Params.push_back(ObjectPtrTy); 157193326Sed Params.push_back(SelectorPtrTy); 158193326Sed return 159198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 160198092Srdivacky Params, true), 161198092Srdivacky "objc_msgSend"); 162193326Sed } 163198092Srdivacky 164193326Sed llvm::Constant *getMessageSendStretFn() const { 165193326Sed // id objc_msgSend_stret (id, SEL, ...) 166193326Sed std::vector<const llvm::Type*> Params; 167193326Sed Params.push_back(ObjectPtrTy); 168193326Sed Params.push_back(SelectorPtrTy); 169193326Sed return 170198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 171198092Srdivacky Params, true), 172198092Srdivacky "objc_msgSend_stret"); 173198092Srdivacky 174193326Sed } 175198092Srdivacky 176193326Sed llvm::Constant *getMessageSendFpretFn() const { 177193326Sed // FIXME: This should be long double on x86_64? 178193326Sed // [double | long double] objc_msgSend_fpret(id self, SEL op, ...) 179193326Sed std::vector<const llvm::Type*> Params; 180193326Sed Params.push_back(ObjectPtrTy); 181193326Sed Params.push_back(SelectorPtrTy); 182193326Sed return 183198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get( 184198092Srdivacky llvm::Type::getDoubleTy(VMContext), 185198092Srdivacky Params, 186198092Srdivacky true), 187198092Srdivacky "objc_msgSend_fpret"); 188198092Srdivacky 189193326Sed } 190198092Srdivacky 191193326Sed llvm::Constant *getMessageSendSuperFn() const { 192193326Sed // id objc_msgSendSuper(struct objc_super *super, SEL op, ...) 193193326Sed const char *SuperName = "objc_msgSendSuper"; 194193326Sed std::vector<const llvm::Type*> Params; 195193326Sed Params.push_back(SuperPtrTy); 196193326Sed Params.push_back(SelectorPtrTy); 197193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 198193326Sed Params, true), 199193326Sed SuperName); 200193326Sed } 201198092Srdivacky 202193326Sed llvm::Constant *getMessageSendSuperFn2() const { 203193326Sed // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...) 204193326Sed const char *SuperName = "objc_msgSendSuper2"; 205193326Sed std::vector<const llvm::Type*> Params; 206193326Sed Params.push_back(SuperPtrTy); 207193326Sed Params.push_back(SelectorPtrTy); 208193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 209193326Sed Params, true), 210193326Sed SuperName); 211193326Sed } 212198092Srdivacky 213193326Sed llvm::Constant *getMessageSendSuperStretFn() const { 214193326Sed // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super, 215193326Sed // SEL op, ...) 216193326Sed std::vector<const llvm::Type*> Params; 217193326Sed Params.push_back(Int8PtrTy); 218193326Sed Params.push_back(SuperPtrTy); 219193326Sed Params.push_back(SelectorPtrTy); 220198092Srdivacky return CGM.CreateRuntimeFunction( 221198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 222198092Srdivacky Params, true), 223198092Srdivacky "objc_msgSendSuper_stret"); 224193326Sed } 225198092Srdivacky 226193326Sed llvm::Constant *getMessageSendSuperStretFn2() const { 227193326Sed // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super, 228193326Sed // SEL op, ...) 229193326Sed std::vector<const llvm::Type*> Params; 230193326Sed Params.push_back(Int8PtrTy); 231193326Sed Params.push_back(SuperPtrTy); 232193326Sed Params.push_back(SelectorPtrTy); 233198092Srdivacky return CGM.CreateRuntimeFunction( 234198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 235198092Srdivacky Params, true), 236198092Srdivacky "objc_msgSendSuper2_stret"); 237193326Sed } 238198092Srdivacky 239193326Sed llvm::Constant *getMessageSendSuperFpretFn() const { 240193326Sed // There is no objc_msgSendSuper_fpret? How can that work? 241193326Sed return getMessageSendSuperFn(); 242193326Sed } 243198092Srdivacky 244193326Sed llvm::Constant *getMessageSendSuperFpretFn2() const { 245193326Sed // There is no objc_msgSendSuper_fpret? How can that work? 246193326Sed return getMessageSendSuperFn2(); 247193326Sed } 248198092Srdivacky 249193326Sedprotected: 250193326Sed CodeGen::CodeGenModule &CGM; 251198092Srdivacky 252193326Sedpublic: 253193326Sed const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy; 254193326Sed const llvm::Type *Int8PtrTy; 255198092Srdivacky 256193326Sed /// ObjectPtrTy - LLVM type for object handles (typeof(id)) 257193326Sed const llvm::Type *ObjectPtrTy; 258198092Srdivacky 259193326Sed /// PtrObjectPtrTy - LLVM type for id * 260193326Sed const llvm::Type *PtrObjectPtrTy; 261198092Srdivacky 262193326Sed /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL)) 263193326Sed const llvm::Type *SelectorPtrTy; 264193326Sed /// ProtocolPtrTy - LLVM type for external protocol handles 265193326Sed /// (typeof(Protocol)) 266193326Sed const llvm::Type *ExternalProtocolPtrTy; 267198092Srdivacky 268193326Sed // SuperCTy - clang type for struct objc_super. 269193326Sed QualType SuperCTy; 270193326Sed // SuperPtrCTy - clang type for struct objc_super *. 271193326Sed QualType SuperPtrCTy; 272198092Srdivacky 273193326Sed /// SuperTy - LLVM type for struct objc_super. 274193326Sed const llvm::StructType *SuperTy; 275193326Sed /// SuperPtrTy - LLVM type for struct objc_super *. 276193326Sed const llvm::Type *SuperPtrTy; 277198092Srdivacky 278193326Sed /// PropertyTy - LLVM type for struct objc_property (struct _prop_t 279193326Sed /// in GCC parlance). 280193326Sed const llvm::StructType *PropertyTy; 281198092Srdivacky 282193326Sed /// PropertyListTy - LLVM type for struct objc_property_list 283193326Sed /// (_prop_list_t in GCC parlance). 284193326Sed const llvm::StructType *PropertyListTy; 285193326Sed /// PropertyListPtrTy - LLVM type for struct objc_property_list*. 286193326Sed const llvm::Type *PropertyListPtrTy; 287198092Srdivacky 288193326Sed // MethodTy - LLVM type for struct objc_method. 289193326Sed const llvm::StructType *MethodTy; 290198092Srdivacky 291193326Sed /// CacheTy - LLVM type for struct objc_cache. 292193326Sed const llvm::Type *CacheTy; 293193326Sed /// CachePtrTy - LLVM type for struct objc_cache *. 294193326Sed const llvm::Type *CachePtrTy; 295198092Srdivacky 296193326Sed llvm::Constant *getGetPropertyFn() { 297193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 298193326Sed ASTContext &Ctx = CGM.getContext(); 299193326Sed // id objc_getProperty (id, SEL, ptrdiff_t, bool) 300193326Sed llvm::SmallVector<QualType,16> Params; 301193326Sed QualType IdType = Ctx.getObjCIdType(); 302193326Sed QualType SelType = Ctx.getObjCSelType(); 303193326Sed Params.push_back(IdType); 304193326Sed Params.push_back(SelType); 305193326Sed Params.push_back(Ctx.LongTy); 306193326Sed Params.push_back(Ctx.BoolTy); 307193326Sed const llvm::FunctionType *FTy = 308203955Srdivacky Types.GetFunctionType(Types.getFunctionInfo(IdType, Params, 309203955Srdivacky CC_Default, false), false); 310193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_getProperty"); 311193326Sed } 312198092Srdivacky 313193326Sed llvm::Constant *getSetPropertyFn() { 314193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 315193326Sed ASTContext &Ctx = CGM.getContext(); 316193326Sed // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) 317193326Sed llvm::SmallVector<QualType,16> Params; 318193326Sed QualType IdType = Ctx.getObjCIdType(); 319193326Sed QualType SelType = Ctx.getObjCSelType(); 320193326Sed Params.push_back(IdType); 321193326Sed Params.push_back(SelType); 322193326Sed Params.push_back(Ctx.LongTy); 323193326Sed Params.push_back(IdType); 324193326Sed Params.push_back(Ctx.BoolTy); 325193326Sed Params.push_back(Ctx.BoolTy); 326193326Sed const llvm::FunctionType *FTy = 327203955Srdivacky Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params, 328203955Srdivacky CC_Default, false), false); 329193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_setProperty"); 330193326Sed } 331198092Srdivacky 332193326Sed llvm::Constant *getEnumerationMutationFn() { 333198092Srdivacky CodeGen::CodeGenTypes &Types = CGM.getTypes(); 334198092Srdivacky ASTContext &Ctx = CGM.getContext(); 335193326Sed // void objc_enumerationMutation (id) 336198092Srdivacky llvm::SmallVector<QualType,16> Params; 337198092Srdivacky Params.push_back(Ctx.getObjCIdType()); 338198092Srdivacky const llvm::FunctionType *FTy = 339203955Srdivacky Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params, 340203955Srdivacky CC_Default, false), false); 341193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); 342193326Sed } 343198092Srdivacky 344193326Sed /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function. 345193326Sed llvm::Constant *getGcReadWeakFn() { 346193326Sed // id objc_read_weak (id *) 347193326Sed std::vector<const llvm::Type*> Args; 348193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 349198092Srdivacky llvm::FunctionType *FTy = 350198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 351193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); 352198092Srdivacky } 353198092Srdivacky 354193326Sed /// GcAssignWeakFn -- LLVM objc_assign_weak function. 355193326Sed llvm::Constant *getGcAssignWeakFn() { 356193326Sed // id objc_assign_weak (id, id *) 357193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 358193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 359193326Sed llvm::FunctionType *FTy = 360193326Sed llvm::FunctionType::get(ObjectPtrTy, Args, false); 361193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); 362193326Sed } 363198092Srdivacky 364193326Sed /// GcAssignGlobalFn -- LLVM objc_assign_global function. 365193326Sed llvm::Constant *getGcAssignGlobalFn() { 366193326Sed // id objc_assign_global(id, id *) 367193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 368193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 369198092Srdivacky llvm::FunctionType *FTy = 370198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 371193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); 372193326Sed } 373198092Srdivacky 374193326Sed /// GcAssignIvarFn -- LLVM objc_assign_ivar function. 375193326Sed llvm::Constant *getGcAssignIvarFn() { 376198092Srdivacky // id objc_assign_ivar(id, id *, ptrdiff_t) 377193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 378193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 379198092Srdivacky Args.push_back(LongTy); 380198092Srdivacky llvm::FunctionType *FTy = 381198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 382193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); 383193326Sed } 384198092Srdivacky 385198092Srdivacky /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function. 386198092Srdivacky llvm::Constant *GcMemmoveCollectableFn() { 387198092Srdivacky // void *objc_memmove_collectable(void *dst, const void *src, size_t size) 388198092Srdivacky std::vector<const llvm::Type*> Args(1, Int8PtrTy); 389198092Srdivacky Args.push_back(Int8PtrTy); 390198092Srdivacky Args.push_back(LongTy); 391198092Srdivacky llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false); 392198092Srdivacky return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); 393198092Srdivacky } 394198092Srdivacky 395193326Sed /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function. 396193326Sed llvm::Constant *getGcAssignStrongCastFn() { 397193326Sed // id objc_assign_global(id, id *) 398193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 399193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 400198092Srdivacky llvm::FunctionType *FTy = 401198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 402193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); 403193326Sed } 404193326Sed 405193326Sed /// ExceptionThrowFn - LLVM objc_exception_throw function. 406193326Sed llvm::Constant *getExceptionThrowFn() { 407193326Sed // void objc_exception_throw(id) 408193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 409193326Sed llvm::FunctionType *FTy = 410198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 411193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); 412193326Sed } 413198092Srdivacky 414193326Sed /// SyncEnterFn - LLVM object_sync_enter function. 415193326Sed llvm::Constant *getSyncEnterFn() { 416193326Sed // void objc_sync_enter (id) 417193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 418193326Sed llvm::FunctionType *FTy = 419198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 420193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); 421193326Sed } 422198092Srdivacky 423193326Sed /// SyncExitFn - LLVM object_sync_exit function. 424193326Sed llvm::Constant *getSyncExitFn() { 425193326Sed // void objc_sync_exit (id) 426193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 427193326Sed llvm::FunctionType *FTy = 428198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 429193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); 430193326Sed } 431198092Srdivacky 432193326Sed llvm::Constant *getSendFn(bool IsSuper) const { 433193326Sed return IsSuper ? getMessageSendSuperFn() : getMessageSendFn(); 434193326Sed } 435198092Srdivacky 436193326Sed llvm::Constant *getSendFn2(bool IsSuper) const { 437193326Sed return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn(); 438193326Sed } 439198092Srdivacky 440193326Sed llvm::Constant *getSendStretFn(bool IsSuper) const { 441193326Sed return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn(); 442193326Sed } 443198092Srdivacky 444193326Sed llvm::Constant *getSendStretFn2(bool IsSuper) const { 445193326Sed return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn(); 446193326Sed } 447198092Srdivacky 448193326Sed llvm::Constant *getSendFpretFn(bool IsSuper) const { 449193326Sed return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn(); 450193326Sed } 451198092Srdivacky 452193326Sed llvm::Constant *getSendFpretFn2(bool IsSuper) const { 453193326Sed return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn(); 454193326Sed } 455198092Srdivacky 456193326Sed ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm); 457193326Sed ~ObjCCommonTypesHelper(){} 458193326Sed}; 459193326Sed 460193326Sed/// ObjCTypesHelper - Helper class that encapsulates lazy 461193326Sed/// construction of varies types used during ObjC generation. 462193326Sedclass ObjCTypesHelper : public ObjCCommonTypesHelper { 463193326Sedpublic: 464193326Sed /// SymtabTy - LLVM type for struct objc_symtab. 465193326Sed const llvm::StructType *SymtabTy; 466193326Sed /// SymtabPtrTy - LLVM type for struct objc_symtab *. 467193326Sed const llvm::Type *SymtabPtrTy; 468193326Sed /// ModuleTy - LLVM type for struct objc_module. 469193326Sed const llvm::StructType *ModuleTy; 470193326Sed 471193326Sed /// ProtocolTy - LLVM type for struct objc_protocol. 472193326Sed const llvm::StructType *ProtocolTy; 473193326Sed /// ProtocolPtrTy - LLVM type for struct objc_protocol *. 474193326Sed const llvm::Type *ProtocolPtrTy; 475193326Sed /// ProtocolExtensionTy - LLVM type for struct 476193326Sed /// objc_protocol_extension. 477193326Sed const llvm::StructType *ProtocolExtensionTy; 478193326Sed /// ProtocolExtensionTy - LLVM type for struct 479193326Sed /// objc_protocol_extension *. 480193326Sed const llvm::Type *ProtocolExtensionPtrTy; 481193326Sed /// MethodDescriptionTy - LLVM type for struct 482193326Sed /// objc_method_description. 483193326Sed const llvm::StructType *MethodDescriptionTy; 484193326Sed /// MethodDescriptionListTy - LLVM type for struct 485193326Sed /// objc_method_description_list. 486193326Sed const llvm::StructType *MethodDescriptionListTy; 487193326Sed /// MethodDescriptionListPtrTy - LLVM type for struct 488193326Sed /// objc_method_description_list *. 489193326Sed const llvm::Type *MethodDescriptionListPtrTy; 490193326Sed /// ProtocolListTy - LLVM type for struct objc_property_list. 491193326Sed const llvm::Type *ProtocolListTy; 492193326Sed /// ProtocolListPtrTy - LLVM type for struct objc_property_list*. 493193326Sed const llvm::Type *ProtocolListPtrTy; 494193326Sed /// CategoryTy - LLVM type for struct objc_category. 495193326Sed const llvm::StructType *CategoryTy; 496193326Sed /// ClassTy - LLVM type for struct objc_class. 497193326Sed const llvm::StructType *ClassTy; 498193326Sed /// ClassPtrTy - LLVM type for struct objc_class *. 499193326Sed const llvm::Type *ClassPtrTy; 500193326Sed /// ClassExtensionTy - LLVM type for struct objc_class_ext. 501193326Sed const llvm::StructType *ClassExtensionTy; 502193326Sed /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *. 503193326Sed const llvm::Type *ClassExtensionPtrTy; 504193326Sed // IvarTy - LLVM type for struct objc_ivar. 505193326Sed const llvm::StructType *IvarTy; 506193326Sed /// IvarListTy - LLVM type for struct objc_ivar_list. 507193326Sed const llvm::Type *IvarListTy; 508193326Sed /// IvarListPtrTy - LLVM type for struct objc_ivar_list *. 509193326Sed const llvm::Type *IvarListPtrTy; 510193326Sed /// MethodListTy - LLVM type for struct objc_method_list. 511193326Sed const llvm::Type *MethodListTy; 512193326Sed /// MethodListPtrTy - LLVM type for struct objc_method_list *. 513193326Sed const llvm::Type *MethodListPtrTy; 514198092Srdivacky 515193326Sed /// ExceptionDataTy - LLVM type for struct _objc_exception_data. 516193326Sed const llvm::Type *ExceptionDataTy; 517198092Srdivacky 518193326Sed /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function. 519193326Sed llvm::Constant *getExceptionTryEnterFn() { 520193326Sed std::vector<const llvm::Type*> Params; 521193326Sed Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); 522198092Srdivacky return CGM.CreateRuntimeFunction( 523198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 524198092Srdivacky Params, false), 525198092Srdivacky "objc_exception_try_enter"); 526193326Sed } 527193326Sed 528193326Sed /// ExceptionTryExitFn - LLVM objc_exception_try_exit function. 529193326Sed llvm::Constant *getExceptionTryExitFn() { 530193326Sed std::vector<const llvm::Type*> Params; 531193326Sed Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); 532198092Srdivacky return CGM.CreateRuntimeFunction( 533198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 534198092Srdivacky Params, false), 535198092Srdivacky "objc_exception_try_exit"); 536193326Sed } 537193326Sed 538193326Sed /// ExceptionExtractFn - LLVM objc_exception_extract function. 539193326Sed llvm::Constant *getExceptionExtractFn() { 540193326Sed std::vector<const llvm::Type*> Params; 541193326Sed Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); 542193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 543193326Sed Params, false), 544193326Sed "objc_exception_extract"); 545198092Srdivacky 546193326Sed } 547198092Srdivacky 548193326Sed /// ExceptionMatchFn - LLVM objc_exception_match function. 549193326Sed llvm::Constant *getExceptionMatchFn() { 550193326Sed std::vector<const llvm::Type*> Params; 551193326Sed Params.push_back(ClassPtrTy); 552193326Sed Params.push_back(ObjectPtrTy); 553198092Srdivacky return CGM.CreateRuntimeFunction( 554198092Srdivacky llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), 555198092Srdivacky Params, false), 556198092Srdivacky "objc_exception_match"); 557198092Srdivacky 558193326Sed } 559198092Srdivacky 560193326Sed /// SetJmpFn - LLVM _setjmp function. 561193326Sed llvm::Constant *getSetJmpFn() { 562193326Sed std::vector<const llvm::Type*> Params; 563198092Srdivacky Params.push_back(llvm::Type::getInt32PtrTy(VMContext)); 564193326Sed return 565198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), 566193326Sed Params, false), 567193326Sed "_setjmp"); 568198092Srdivacky 569193326Sed } 570198092Srdivacky 571193326Sedpublic: 572193326Sed ObjCTypesHelper(CodeGen::CodeGenModule &cgm); 573193326Sed ~ObjCTypesHelper() {} 574193326Sed}; 575193326Sed 576193326Sed/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's 577193326Sed/// modern abi 578193326Sedclass ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper { 579193326Sedpublic: 580198092Srdivacky 581193326Sed // MethodListnfABITy - LLVM for struct _method_list_t 582193326Sed const llvm::StructType *MethodListnfABITy; 583198092Srdivacky 584193326Sed // MethodListnfABIPtrTy - LLVM for struct _method_list_t* 585193326Sed const llvm::Type *MethodListnfABIPtrTy; 586198092Srdivacky 587193326Sed // ProtocolnfABITy = LLVM for struct _protocol_t 588193326Sed const llvm::StructType *ProtocolnfABITy; 589198092Srdivacky 590193326Sed // ProtocolnfABIPtrTy = LLVM for struct _protocol_t* 591193326Sed const llvm::Type *ProtocolnfABIPtrTy; 592193326Sed 593193326Sed // ProtocolListnfABITy - LLVM for struct _objc_protocol_list 594193326Sed const llvm::StructType *ProtocolListnfABITy; 595198092Srdivacky 596193326Sed // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list* 597193326Sed const llvm::Type *ProtocolListnfABIPtrTy; 598198092Srdivacky 599193326Sed // ClassnfABITy - LLVM for struct _class_t 600193326Sed const llvm::StructType *ClassnfABITy; 601198092Srdivacky 602193326Sed // ClassnfABIPtrTy - LLVM for struct _class_t* 603193326Sed const llvm::Type *ClassnfABIPtrTy; 604198092Srdivacky 605193326Sed // IvarnfABITy - LLVM for struct _ivar_t 606193326Sed const llvm::StructType *IvarnfABITy; 607198092Srdivacky 608193326Sed // IvarListnfABITy - LLVM for struct _ivar_list_t 609193326Sed const llvm::StructType *IvarListnfABITy; 610198092Srdivacky 611193326Sed // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t* 612193326Sed const llvm::Type *IvarListnfABIPtrTy; 613198092Srdivacky 614193326Sed // ClassRonfABITy - LLVM for struct _class_ro_t 615193326Sed const llvm::StructType *ClassRonfABITy; 616198092Srdivacky 617193326Sed // ImpnfABITy - LLVM for id (*)(id, SEL, ...) 618193326Sed const llvm::Type *ImpnfABITy; 619198092Srdivacky 620193326Sed // CategorynfABITy - LLVM for struct _category_t 621193326Sed const llvm::StructType *CategorynfABITy; 622198092Srdivacky 623193326Sed // New types for nonfragile abi messaging. 624198092Srdivacky 625193326Sed // MessageRefTy - LLVM for: 626193326Sed // struct _message_ref_t { 627193326Sed // IMP messenger; 628193326Sed // SEL name; 629193326Sed // }; 630193326Sed const llvm::StructType *MessageRefTy; 631193326Sed // MessageRefCTy - clang type for struct _message_ref_t 632193326Sed QualType MessageRefCTy; 633198092Srdivacky 634193326Sed // MessageRefPtrTy - LLVM for struct _message_ref_t* 635193326Sed const llvm::Type *MessageRefPtrTy; 636193326Sed // MessageRefCPtrTy - clang type for struct _message_ref_t* 637193326Sed QualType MessageRefCPtrTy; 638198092Srdivacky 639193326Sed // MessengerTy - Type of the messenger (shown as IMP above) 640193326Sed const llvm::FunctionType *MessengerTy; 641198092Srdivacky 642193326Sed // SuperMessageRefTy - LLVM for: 643193326Sed // struct _super_message_ref_t { 644193326Sed // SUPER_IMP messenger; 645193326Sed // SEL name; 646193326Sed // }; 647193326Sed const llvm::StructType *SuperMessageRefTy; 648198092Srdivacky 649193326Sed // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* 650193326Sed const llvm::Type *SuperMessageRefPtrTy; 651193326Sed 652193326Sed llvm::Constant *getMessageSendFixupFn() { 653193326Sed // id objc_msgSend_fixup(id, struct message_ref_t*, ...) 654193326Sed std::vector<const llvm::Type*> Params; 655193326Sed Params.push_back(ObjectPtrTy); 656193326Sed Params.push_back(MessageRefPtrTy); 657193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 658193326Sed Params, true), 659193326Sed "objc_msgSend_fixup"); 660193326Sed } 661198092Srdivacky 662193326Sed llvm::Constant *getMessageSendFpretFixupFn() { 663193326Sed // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...) 664193326Sed std::vector<const llvm::Type*> Params; 665193326Sed Params.push_back(ObjectPtrTy); 666193326Sed Params.push_back(MessageRefPtrTy); 667193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 668193326Sed Params, true), 669193326Sed "objc_msgSend_fpret_fixup"); 670193326Sed } 671198092Srdivacky 672193326Sed llvm::Constant *getMessageSendStretFixupFn() { 673193326Sed // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...) 674193326Sed std::vector<const llvm::Type*> Params; 675193326Sed Params.push_back(ObjectPtrTy); 676193326Sed Params.push_back(MessageRefPtrTy); 677193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 678193326Sed Params, true), 679193326Sed "objc_msgSend_stret_fixup"); 680193326Sed } 681198092Srdivacky 682193326Sed llvm::Constant *getMessageSendIdFixupFn() { 683193326Sed // id objc_msgSendId_fixup(id, struct message_ref_t*, ...) 684193326Sed std::vector<const llvm::Type*> Params; 685193326Sed Params.push_back(ObjectPtrTy); 686193326Sed Params.push_back(MessageRefPtrTy); 687193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 688193326Sed Params, true), 689193326Sed "objc_msgSendId_fixup"); 690193326Sed } 691198092Srdivacky 692193326Sed llvm::Constant *getMessageSendIdStretFixupFn() { 693193326Sed // id objc_msgSendId_stret_fixup(id, struct message_ref_t*, ...) 694193326Sed std::vector<const llvm::Type*> Params; 695193326Sed Params.push_back(ObjectPtrTy); 696193326Sed Params.push_back(MessageRefPtrTy); 697193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 698193326Sed Params, true), 699193326Sed "objc_msgSendId_stret_fixup"); 700193326Sed } 701193326Sed llvm::Constant *getMessageSendSuper2FixupFn() { 702198092Srdivacky // id objc_msgSendSuper2_fixup (struct objc_super *, 703193326Sed // struct _super_message_ref_t*, ...) 704193326Sed std::vector<const llvm::Type*> Params; 705193326Sed Params.push_back(SuperPtrTy); 706193326Sed Params.push_back(SuperMessageRefPtrTy); 707193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 708193326Sed Params, true), 709193326Sed "objc_msgSendSuper2_fixup"); 710193326Sed } 711198092Srdivacky 712193326Sed llvm::Constant *getMessageSendSuper2StretFixupFn() { 713198092Srdivacky // id objc_msgSendSuper2_stret_fixup(struct objc_super *, 714193326Sed // struct _super_message_ref_t*, ...) 715193326Sed std::vector<const llvm::Type*> Params; 716193326Sed Params.push_back(SuperPtrTy); 717193326Sed Params.push_back(SuperMessageRefPtrTy); 718193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 719193326Sed Params, true), 720193326Sed "objc_msgSendSuper2_stret_fixup"); 721193326Sed } 722198092Srdivacky 723198092Srdivacky 724198092Srdivacky 725193326Sed /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C 726193326Sed /// exception personality function. 727193326Sed llvm::Value *getEHPersonalityPtr() { 728198092Srdivacky llvm::Constant *Personality = 729198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), 730193326Sed true), 731198092Srdivacky "__objc_personality_v0"); 732193326Sed return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy); 733193326Sed } 734193326Sed 735193326Sed llvm::Constant *getUnwindResumeOrRethrowFn() { 736193326Sed std::vector<const llvm::Type*> Params; 737193326Sed Params.push_back(Int8PtrTy); 738198092Srdivacky return CGM.CreateRuntimeFunction( 739198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 740198092Srdivacky Params, false), 741203955Srdivacky (CGM.getLangOptions().SjLjExceptions ? "_Unwind_SjLj_Resume" : 742203955Srdivacky "_Unwind_Resume_or_Rethrow")); 743193326Sed } 744198092Srdivacky 745193326Sed llvm::Constant *getObjCEndCatchFn() { 746198092Srdivacky return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 747195341Sed false), 748193326Sed "objc_end_catch"); 749198092Srdivacky 750193326Sed } 751198092Srdivacky 752193326Sed llvm::Constant *getObjCBeginCatchFn() { 753193326Sed std::vector<const llvm::Type*> Params; 754193326Sed Params.push_back(Int8PtrTy); 755193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy, 756193326Sed Params, false), 757193326Sed "objc_begin_catch"); 758193326Sed } 759193326Sed 760193326Sed const llvm::StructType *EHTypeTy; 761193326Sed const llvm::Type *EHTypePtrTy; 762193326Sed 763193326Sed ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm); 764193326Sed ~ObjCNonFragileABITypesHelper(){} 765193326Sed}; 766198092Srdivacky 767193326Sedclass CGObjCCommonMac : public CodeGen::CGObjCRuntime { 768193326Sedpublic: 769193326Sed // FIXME - accessibility 770193326Sed class GC_IVAR { 771193326Sed public: 772193326Sed unsigned ivar_bytepos; 773193326Sed unsigned ivar_size; 774193326Sed GC_IVAR(unsigned bytepos = 0, unsigned size = 0) 775198092Srdivacky : ivar_bytepos(bytepos), ivar_size(size) {} 776193326Sed 777193326Sed // Allow sorting based on byte pos. 778193326Sed bool operator<(const GC_IVAR &b) const { 779193326Sed return ivar_bytepos < b.ivar_bytepos; 780193326Sed } 781193326Sed }; 782198092Srdivacky 783193326Sed class SKIP_SCAN { 784193326Sed public: 785193326Sed unsigned skip; 786193326Sed unsigned scan; 787198092Srdivacky SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0) 788193326Sed : skip(_skip), scan(_scan) {} 789193326Sed }; 790198092Srdivacky 791193326Sedprotected: 792193326Sed CodeGen::CodeGenModule &CGM; 793198092Srdivacky llvm::LLVMContext &VMContext; 794193326Sed // FIXME! May not be needing this after all. 795193326Sed unsigned ObjCABI; 796198092Srdivacky 797193326Sed // gc ivar layout bitmap calculation helper caches. 798193326Sed llvm::SmallVector<GC_IVAR, 16> SkipIvars; 799193326Sed llvm::SmallVector<GC_IVAR, 16> IvarsInfo; 800198092Srdivacky 801193326Sed /// LazySymbols - Symbols to generate a lazy reference for. See 802193326Sed /// DefinedSymbols and FinishModule(). 803198092Srdivacky llvm::SetVector<IdentifierInfo*> LazySymbols; 804198092Srdivacky 805193326Sed /// DefinedSymbols - External symbols which are defined by this 806193326Sed /// module. The symbols in this list and LazySymbols are used to add 807193326Sed /// special linker symbols which ensure that Objective-C modules are 808193326Sed /// linked properly. 809198092Srdivacky llvm::SetVector<IdentifierInfo*> DefinedSymbols; 810198092Srdivacky 811193326Sed /// ClassNames - uniqued class names. 812193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames; 813198092Srdivacky 814193326Sed /// MethodVarNames - uniqued method variable names. 815193326Sed llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames; 816198092Srdivacky 817193326Sed /// MethodVarTypes - uniqued method type signatures. We have to use 818193326Sed /// a StringMap here because have no other unique reference. 819193326Sed llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes; 820198092Srdivacky 821193326Sed /// MethodDefinitions - map of methods which have been defined in 822193326Sed /// this translation unit. 823193326Sed llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions; 824198092Srdivacky 825193326Sed /// PropertyNames - uniqued method variable names. 826193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames; 827198092Srdivacky 828193326Sed /// ClassReferences - uniqued class references. 829193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences; 830198092Srdivacky 831193326Sed /// SelectorReferences - uniqued selector references. 832193326Sed llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences; 833198092Srdivacky 834193326Sed /// Protocols - Protocols for which an objc_protocol structure has 835193326Sed /// been emitted. Forward declarations are handled by creating an 836193326Sed /// empty structure whose initializer is filled in when/if defined. 837193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols; 838198092Srdivacky 839193326Sed /// DefinedProtocols - Protocols which have actually been 840193326Sed /// defined. We should not need this, see FIXME in GenerateProtocol. 841193326Sed llvm::DenseSet<IdentifierInfo*> DefinedProtocols; 842198092Srdivacky 843193326Sed /// DefinedClasses - List of defined classes. 844193326Sed std::vector<llvm::GlobalValue*> DefinedClasses; 845193326Sed 846193326Sed /// DefinedNonLazyClasses - List of defined "non-lazy" classes. 847193326Sed std::vector<llvm::GlobalValue*> DefinedNonLazyClasses; 848198092Srdivacky 849193326Sed /// DefinedCategories - List of defined categories. 850193326Sed std::vector<llvm::GlobalValue*> DefinedCategories; 851198092Srdivacky 852193326Sed /// DefinedNonLazyCategories - List of defined "non-lazy" categories. 853193326Sed std::vector<llvm::GlobalValue*> DefinedNonLazyCategories; 854193326Sed 855193326Sed /// GetNameForMethod - Return a name for the given method. 856193326Sed /// \param[out] NameOut - The return value. 857193326Sed void GetNameForMethod(const ObjCMethodDecl *OMD, 858193326Sed const ObjCContainerDecl *CD, 859198398Srdivacky llvm::SmallVectorImpl<char> &NameOut); 860198092Srdivacky 861193326Sed /// GetMethodVarName - Return a unique constant for the given 862193326Sed /// selector's name. The return value has type char *. 863193326Sed llvm::Constant *GetMethodVarName(Selector Sel); 864193326Sed llvm::Constant *GetMethodVarName(IdentifierInfo *Ident); 865193326Sed llvm::Constant *GetMethodVarName(const std::string &Name); 866198092Srdivacky 867193326Sed /// GetMethodVarType - Return a unique constant for the given 868193326Sed /// selector's name. The return value has type char *. 869198092Srdivacky 870193326Sed // FIXME: This is a horrible name. 871193326Sed llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D); 872193326Sed llvm::Constant *GetMethodVarType(const FieldDecl *D); 873198092Srdivacky 874193326Sed /// GetPropertyName - Return a unique constant for the given 875193326Sed /// name. The return value has type char *. 876193326Sed llvm::Constant *GetPropertyName(IdentifierInfo *Ident); 877198092Srdivacky 878193326Sed // FIXME: This can be dropped once string functions are unified. 879193326Sed llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD, 880193326Sed const Decl *Container); 881198092Srdivacky 882193326Sed /// GetClassName - Return a unique constant for the given selector's 883193326Sed /// name. The return value has type char *. 884193326Sed llvm::Constant *GetClassName(IdentifierInfo *Ident); 885198092Srdivacky 886193326Sed /// BuildIvarLayout - Builds ivar layout bitmap for the class 887193326Sed /// implementation for the __strong or __weak case. 888193326Sed /// 889193326Sed llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI, 890193326Sed bool ForStrongLayout); 891198092Srdivacky 892193326Sed void BuildAggrIvarRecordLayout(const RecordType *RT, 893198092Srdivacky unsigned int BytePos, bool ForStrongLayout, 894198092Srdivacky bool &HasUnion); 895193326Sed void BuildAggrIvarLayout(const ObjCImplementationDecl *OI, 896193326Sed const llvm::StructLayout *Layout, 897193326Sed const RecordDecl *RD, 898193326Sed const llvm::SmallVectorImpl<FieldDecl*> &RecFields, 899193326Sed unsigned int BytePos, bool ForStrongLayout, 900193326Sed bool &HasUnion); 901193326Sed 902193326Sed /// GetIvarLayoutName - Returns a unique constant for the given 903193326Sed /// ivar layout bitmap. 904193326Sed llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident, 905193326Sed const ObjCCommonTypesHelper &ObjCTypes); 906198092Srdivacky 907193326Sed /// EmitPropertyList - Emit the given property list. The return 908193326Sed /// value has type PropertyListPtrTy. 909198398Srdivacky llvm::Constant *EmitPropertyList(llvm::Twine Name, 910198092Srdivacky const Decl *Container, 911193326Sed const ObjCContainerDecl *OCD, 912193326Sed const ObjCCommonTypesHelper &ObjCTypes); 913198092Srdivacky 914200583Srdivacky /// PushProtocolProperties - Push protocol's property on the input stack. 915200583Srdivacky void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet, 916200583Srdivacky std::vector<llvm::Constant*> &Properties, 917200583Srdivacky const Decl *Container, 918200583Srdivacky const ObjCProtocolDecl *PROTO, 919200583Srdivacky const ObjCCommonTypesHelper &ObjCTypes); 920200583Srdivacky 921193326Sed /// GetProtocolRef - Return a reference to the internal protocol 922193326Sed /// description, creating an empty one if it has not been 923193326Sed /// defined. The return value has type ProtocolPtrTy. 924193326Sed llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD); 925193326Sed 926193326Sed /// CreateMetadataVar - Create a global variable with internal 927193326Sed /// linkage for use by the Objective-C runtime. 928193326Sed /// 929193326Sed /// This is a convenience wrapper which not only creates the 930193326Sed /// variable, but also sets the section and alignment and adds the 931198092Srdivacky /// global to the "llvm.used" list. 932193326Sed /// 933193326Sed /// \param Name - The variable name. 934193326Sed /// \param Init - The variable initializer; this is also used to 935193326Sed /// define the type of the variable. 936193326Sed /// \param Section - The section the variable should go into, or 0. 937193326Sed /// \param Align - The alignment for the variable, or 0. 938193326Sed /// \param AddToUsed - Whether the variable should be added to 939193326Sed /// "llvm.used". 940198398Srdivacky llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name, 941193326Sed llvm::Constant *Init, 942193326Sed const char *Section, 943193326Sed unsigned Align, 944193326Sed bool AddToUsed); 945193326Sed 946193326Sed CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, 947193326Sed QualType ResultType, 948193326Sed llvm::Value *Sel, 949193326Sed llvm::Value *Arg0, 950193326Sed QualType Arg0Ty, 951193326Sed bool IsSuper, 952193326Sed const CallArgList &CallArgs, 953198092Srdivacky const ObjCMethodDecl *OMD, 954193326Sed const ObjCCommonTypesHelper &ObjCTypes); 955193326Sed 956198092Srdivackypublic: 957198092Srdivacky CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : 958198092Srdivacky CGM(cgm), VMContext(cgm.getLLVMContext()) { } 959195099Sed 960202879Srdivacky virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL); 961198092Srdivacky 962193326Sed virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, 963193326Sed const ObjCContainerDecl *CD=0); 964198092Srdivacky 965193326Sed virtual void GenerateProtocol(const ObjCProtocolDecl *PD); 966198092Srdivacky 967193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 968193326Sed /// declaration, emitting it if necessary. The return value has type 969193326Sed /// ProtocolPtrTy. 970193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0; 971198092Srdivacky 972193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 973193326Sed /// object for the given declaration, emitting it if needed. These 974193326Sed /// forward references will be filled in with empty bodies if no 975193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 976193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0; 977193326Sed}; 978198092Srdivacky 979193326Sedclass CGObjCMac : public CGObjCCommonMac { 980193326Sedprivate: 981193326Sed ObjCTypesHelper ObjCTypes; 982193326Sed /// EmitImageInfo - Emit the image info marker used to encode some module 983193326Sed /// level information. 984193326Sed void EmitImageInfo(); 985193326Sed 986193326Sed /// EmitModuleInfo - Another marker encoding module level 987198092Srdivacky /// information. 988193326Sed void EmitModuleInfo(); 989193326Sed 990193326Sed /// EmitModuleSymols - Emit module symbols, the list of defined 991193326Sed /// classes and categories. The result has type SymtabPtrTy. 992193326Sed llvm::Constant *EmitModuleSymbols(); 993193326Sed 994193326Sed /// FinishModule - Write out global data structures at the end of 995193326Sed /// processing a translation unit. 996193326Sed void FinishModule(); 997193326Sed 998193326Sed /// EmitClassExtension - Generate the class extension structure used 999193326Sed /// to store the weak ivar layout and properties. The return value 1000193326Sed /// has type ClassExtensionPtrTy. 1001193326Sed llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID); 1002193326Sed 1003193326Sed /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1004193326Sed /// for the given class. 1005198092Srdivacky llvm::Value *EmitClassRef(CGBuilderTy &Builder, 1006193326Sed const ObjCInterfaceDecl *ID); 1007199482Srdivacky 1008199482Srdivacky /// EmitSuperClassRef - Emits reference to class's main metadata class. 1009199482Srdivacky llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID); 1010193326Sed 1011193326Sed CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, 1012193326Sed QualType ResultType, 1013193326Sed Selector Sel, 1014193326Sed llvm::Value *Arg0, 1015193326Sed QualType Arg0Ty, 1016193326Sed bool IsSuper, 1017193326Sed const CallArgList &CallArgs); 1018193326Sed 1019193326Sed /// EmitIvarList - Emit the ivar list for the given 1020193326Sed /// implementation. If ForClass is true the list of class ivars 1021193326Sed /// (i.e. metaclass ivars) is emitted, otherwise the list of 1022193326Sed /// interface ivars will be emitted. The return value has type 1023193326Sed /// IvarListPtrTy. 1024193326Sed llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID, 1025193326Sed bool ForClass); 1026198092Srdivacky 1027193326Sed /// EmitMetaClass - Emit a forward reference to the class structure 1028193326Sed /// for the metaclass of the given interface. The return value has 1029193326Sed /// type ClassPtrTy. 1030193326Sed llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID); 1031193326Sed 1032193326Sed /// EmitMetaClass - Emit a class structure for the metaclass of the 1033193326Sed /// given implementation. The return value has type ClassPtrTy. 1034193326Sed llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID, 1035193326Sed llvm::Constant *Protocols, 1036193326Sed const ConstantVector &Methods); 1037198092Srdivacky 1038193326Sed llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); 1039198092Srdivacky 1040193326Sed llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD); 1041193326Sed 1042193326Sed /// EmitMethodList - Emit the method list for the given 1043193326Sed /// implementation. The return value has type MethodListPtrTy. 1044198398Srdivacky llvm::Constant *EmitMethodList(llvm::Twine Name, 1045193326Sed const char *Section, 1046193326Sed const ConstantVector &Methods); 1047193326Sed 1048193326Sed /// EmitMethodDescList - Emit a method description list for a list of 1049198092Srdivacky /// method declarations. 1050193326Sed /// - TypeName: The name for the type containing the methods. 1051193326Sed /// - IsProtocol: True iff these methods are for a protocol. 1052193326Sed /// - ClassMethds: True iff these are class methods. 1053193326Sed /// - Required: When true, only "required" methods are 1054193326Sed /// listed. Similarly, when false only "optional" methods are 1055193326Sed /// listed. For classes this should always be true. 1056193326Sed /// - begin, end: The method list to output. 1057193326Sed /// 1058193326Sed /// The return value has type MethodDescriptionListPtrTy. 1059198398Srdivacky llvm::Constant *EmitMethodDescList(llvm::Twine Name, 1060193326Sed const char *Section, 1061193326Sed const ConstantVector &Methods); 1062193326Sed 1063193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1064193326Sed /// declaration, emitting it if necessary. The return value has type 1065193326Sed /// ProtocolPtrTy. 1066193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD); 1067193326Sed 1068193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1069193326Sed /// object for the given declaration, emitting it if needed. These 1070193326Sed /// forward references will be filled in with empty bodies if no 1071193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1072193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD); 1073193326Sed 1074193326Sed /// EmitProtocolExtension - Generate the protocol extension 1075193326Sed /// structure used to store optional instance and class methods, and 1076193326Sed /// protocol properties. The return value has type 1077193326Sed /// ProtocolExtensionPtrTy. 1078193326Sed llvm::Constant * 1079193326Sed EmitProtocolExtension(const ObjCProtocolDecl *PD, 1080193326Sed const ConstantVector &OptInstanceMethods, 1081193326Sed const ConstantVector &OptClassMethods); 1082193326Sed 1083193326Sed /// EmitProtocolList - Generate the list of referenced 1084193326Sed /// protocols. The return value has type ProtocolListPtrTy. 1085198398Srdivacky llvm::Constant *EmitProtocolList(llvm::Twine Name, 1086193326Sed ObjCProtocolDecl::protocol_iterator begin, 1087193326Sed ObjCProtocolDecl::protocol_iterator end); 1088193326Sed 1089193326Sed /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, 1090193326Sed /// for the given selector. 1091193326Sed llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel); 1092198092Srdivacky 1093198092Srdivackypublic: 1094193326Sed CGObjCMac(CodeGen::CodeGenModule &cgm); 1095193326Sed 1096193326Sed virtual llvm::Function *ModuleInitFunction(); 1097198092Srdivacky 1098193326Sed virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1099193326Sed QualType ResultType, 1100193326Sed Selector Sel, 1101193326Sed llvm::Value *Receiver, 1102193326Sed bool IsClassMessage, 1103193326Sed const CallArgList &CallArgs, 1104193326Sed const ObjCMethodDecl *Method); 1105193326Sed 1106198092Srdivacky virtual CodeGen::RValue 1107193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1108193326Sed QualType ResultType, 1109193326Sed Selector Sel, 1110193326Sed const ObjCInterfaceDecl *Class, 1111193326Sed bool isCategoryImpl, 1112193326Sed llvm::Value *Receiver, 1113193326Sed bool IsClassMessage, 1114198092Srdivacky const CallArgList &CallArgs, 1115198092Srdivacky const ObjCMethodDecl *Method); 1116198092Srdivacky 1117193326Sed virtual llvm::Value *GetClass(CGBuilderTy &Builder, 1118193326Sed const ObjCInterfaceDecl *ID); 1119193326Sed 1120193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel); 1121193326Sed 1122193326Sed /// The NeXT/Apple runtimes do not support typed selectors; just emit an 1123193326Sed /// untyped one. 1124193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, 1125193326Sed const ObjCMethodDecl *Method); 1126193326Sed 1127193326Sed virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); 1128193326Sed 1129193326Sed virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); 1130193326Sed 1131193326Sed virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, 1132193326Sed const ObjCProtocolDecl *PD); 1133198092Srdivacky 1134193326Sed virtual llvm::Constant *GetPropertyGetFunction(); 1135193326Sed virtual llvm::Constant *GetPropertySetFunction(); 1136193326Sed virtual llvm::Constant *EnumerationMutationFunction(); 1137198092Srdivacky 1138193326Sed virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1139193326Sed const Stmt &S); 1140193326Sed virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 1141193326Sed const ObjCAtThrowStmt &S); 1142193326Sed virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1143198092Srdivacky llvm::Value *AddrWeakObj); 1144193326Sed virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1145198092Srdivacky llvm::Value *src, llvm::Value *dst); 1146193326Sed virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1147193326Sed llvm::Value *src, llvm::Value *dest); 1148193326Sed virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 1149198092Srdivacky llvm::Value *src, llvm::Value *dest, 1150198092Srdivacky llvm::Value *ivarOffset); 1151193326Sed virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 1152193326Sed llvm::Value *src, llvm::Value *dest); 1153198092Srdivacky virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 1154198092Srdivacky llvm::Value *dest, llvm::Value *src, 1155198092Srdivacky QualType Ty); 1156198092Srdivacky 1157193326Sed virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 1158193326Sed QualType ObjectTy, 1159193326Sed llvm::Value *BaseValue, 1160193326Sed const ObjCIvarDecl *Ivar, 1161193326Sed unsigned CVRQualifiers); 1162193326Sed virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 1163193326Sed const ObjCInterfaceDecl *Interface, 1164193326Sed const ObjCIvarDecl *Ivar); 1165193326Sed}; 1166198092Srdivacky 1167193326Sedclass CGObjCNonFragileABIMac : public CGObjCCommonMac { 1168193326Sedprivate: 1169193326Sed ObjCNonFragileABITypesHelper ObjCTypes; 1170193326Sed llvm::GlobalVariable* ObjCEmptyCacheVar; 1171193326Sed llvm::GlobalVariable* ObjCEmptyVtableVar; 1172198092Srdivacky 1173193326Sed /// SuperClassReferences - uniqued super class references. 1174193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences; 1175198092Srdivacky 1176193326Sed /// MetaClassReferences - uniqued meta class references. 1177193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences; 1178193326Sed 1179193326Sed /// EHTypeReferences - uniqued class ehtype references. 1180193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences; 1181198092Srdivacky 1182193326Sed /// NonLegacyDispatchMethods - List of methods for which we do *not* generate 1183193326Sed /// legacy messaging dispatch. 1184193326Sed llvm::DenseSet<Selector> NonLegacyDispatchMethods; 1185198092Srdivacky 1186199482Srdivacky /// DefinedMetaClasses - List of defined meta-classes. 1187199482Srdivacky std::vector<llvm::GlobalValue*> DefinedMetaClasses; 1188199482Srdivacky 1189193326Sed /// LegacyDispatchedSelector - Returns true if SEL is not in the list of 1190193326Sed /// NonLegacyDispatchMethods; false otherwise. 1191193326Sed bool LegacyDispatchedSelector(Selector Sel); 1192198092Srdivacky 1193193326Sed /// FinishNonFragileABIModule - Write out global data structures at the end of 1194193326Sed /// processing a translation unit. 1195193326Sed void FinishNonFragileABIModule(); 1196193326Sed 1197193326Sed /// AddModuleClassList - Add the given list of class pointers to the 1198193326Sed /// module with the provided symbol and section names. 1199193326Sed void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container, 1200193326Sed const char *SymbolName, 1201193326Sed const char *SectionName); 1202193326Sed 1203198092Srdivacky llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags, 1204198092Srdivacky unsigned InstanceStart, 1205198092Srdivacky unsigned InstanceSize, 1206198092Srdivacky const ObjCImplementationDecl *ID); 1207193326Sed llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName, 1208198092Srdivacky llvm::Constant *IsAGV, 1209193326Sed llvm::Constant *SuperClassGV, 1210193326Sed llvm::Constant *ClassRoGV, 1211193326Sed bool HiddenVisibility); 1212198092Srdivacky 1213193326Sed llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); 1214198092Srdivacky 1215193326Sed llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD); 1216198092Srdivacky 1217193326Sed /// EmitMethodList - Emit the method list for the given 1218193326Sed /// implementation. The return value has type MethodListnfABITy. 1219198398Srdivacky llvm::Constant *EmitMethodList(llvm::Twine Name, 1220193326Sed const char *Section, 1221193326Sed const ConstantVector &Methods); 1222193326Sed /// EmitIvarList - Emit the ivar list for the given 1223193326Sed /// implementation. If ForClass is true the list of class ivars 1224193326Sed /// (i.e. metaclass ivars) is emitted, otherwise the list of 1225193326Sed /// interface ivars will be emitted. The return value has type 1226193326Sed /// IvarListnfABIPtrTy. 1227193326Sed llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID); 1228198092Srdivacky 1229193326Sed llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, 1230193326Sed const ObjCIvarDecl *Ivar, 1231193326Sed unsigned long int offset); 1232198092Srdivacky 1233193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1234193326Sed /// declaration, emitting it if necessary. The return value has type 1235193326Sed /// ProtocolPtrTy. 1236193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD); 1237198092Srdivacky 1238193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1239193326Sed /// object for the given declaration, emitting it if needed. These 1240193326Sed /// forward references will be filled in with empty bodies if no 1241193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1242193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD); 1243198092Srdivacky 1244193326Sed /// EmitProtocolList - Generate the list of referenced 1245193326Sed /// protocols. The return value has type ProtocolListPtrTy. 1246198398Srdivacky llvm::Constant *EmitProtocolList(llvm::Twine Name, 1247193326Sed ObjCProtocolDecl::protocol_iterator begin, 1248193326Sed ObjCProtocolDecl::protocol_iterator end); 1249198092Srdivacky 1250193326Sed CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, 1251193326Sed QualType ResultType, 1252193326Sed Selector Sel, 1253193326Sed llvm::Value *Receiver, 1254193326Sed QualType Arg0Ty, 1255193326Sed bool IsSuper, 1256193326Sed const CallArgList &CallArgs); 1257193326Sed 1258193326Sed /// GetClassGlobal - Return the global variable for the Objective-C 1259193326Sed /// class of the given name. 1260193326Sed llvm::GlobalVariable *GetClassGlobal(const std::string &Name); 1261198092Srdivacky 1262193326Sed /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1263193326Sed /// for the given class reference. 1264198092Srdivacky llvm::Value *EmitClassRef(CGBuilderTy &Builder, 1265193326Sed const ObjCInterfaceDecl *ID); 1266198092Srdivacky 1267193326Sed /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1268193326Sed /// for the given super class reference. 1269198092Srdivacky llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder, 1270198092Srdivacky const ObjCInterfaceDecl *ID); 1271198092Srdivacky 1272193326Sed /// EmitMetaClassRef - Return a Value * of the address of _class_t 1273193326Sed /// meta-data 1274198092Srdivacky llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder, 1275193326Sed const ObjCInterfaceDecl *ID); 1276193326Sed 1277193326Sed /// ObjCIvarOffsetVariable - Returns the ivar offset variable for 1278193326Sed /// the given ivar. 1279193326Sed /// 1280193326Sed llvm::GlobalVariable * ObjCIvarOffsetVariable( 1281198092Srdivacky const ObjCInterfaceDecl *ID, 1282198092Srdivacky const ObjCIvarDecl *Ivar); 1283198092Srdivacky 1284193326Sed /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, 1285193326Sed /// for the given selector. 1286193326Sed llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel); 1287193326Sed 1288193326Sed /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C 1289193326Sed /// interface. The return value has type EHTypePtrTy. 1290193326Sed llvm::Value *GetInterfaceEHType(const ObjCInterfaceDecl *ID, 1291193326Sed bool ForDefinition); 1292193326Sed 1293198092Srdivacky const char *getMetaclassSymbolPrefix() const { 1294193326Sed return "OBJC_METACLASS_$_"; 1295193326Sed } 1296198092Srdivacky 1297193326Sed const char *getClassSymbolPrefix() const { 1298193326Sed return "OBJC_CLASS_$_"; 1299193326Sed } 1300193326Sed 1301193326Sed void GetClassSizeInfo(const ObjCImplementationDecl *OID, 1302193326Sed uint32_t &InstanceStart, 1303193326Sed uint32_t &InstanceSize); 1304198092Srdivacky 1305193326Sed // Shamelessly stolen from Analysis/CFRefCount.cpp 1306193326Sed Selector GetNullarySelector(const char* name) const { 1307193326Sed IdentifierInfo* II = &CGM.getContext().Idents.get(name); 1308193326Sed return CGM.getContext().Selectors.getSelector(0, &II); 1309193326Sed } 1310198092Srdivacky 1311193326Sed Selector GetUnarySelector(const char* name) const { 1312193326Sed IdentifierInfo* II = &CGM.getContext().Idents.get(name); 1313193326Sed return CGM.getContext().Selectors.getSelector(1, &II); 1314193326Sed } 1315193326Sed 1316193326Sed /// ImplementationIsNonLazy - Check whether the given category or 1317193326Sed /// class implementation is "non-lazy". 1318193326Sed bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const; 1319193326Sed 1320193326Sedpublic: 1321193326Sed CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); 1322193326Sed // FIXME. All stubs for now! 1323193326Sed virtual llvm::Function *ModuleInitFunction(); 1324198092Srdivacky 1325193326Sed virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1326193326Sed QualType ResultType, 1327193326Sed Selector Sel, 1328193326Sed llvm::Value *Receiver, 1329193326Sed bool IsClassMessage, 1330193326Sed const CallArgList &CallArgs, 1331193326Sed const ObjCMethodDecl *Method); 1332198092Srdivacky 1333198092Srdivacky virtual CodeGen::RValue 1334193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1335193326Sed QualType ResultType, 1336193326Sed Selector Sel, 1337193326Sed const ObjCInterfaceDecl *Class, 1338193326Sed bool isCategoryImpl, 1339193326Sed llvm::Value *Receiver, 1340193326Sed bool IsClassMessage, 1341198092Srdivacky const CallArgList &CallArgs, 1342198092Srdivacky const ObjCMethodDecl *Method); 1343198092Srdivacky 1344193326Sed virtual llvm::Value *GetClass(CGBuilderTy &Builder, 1345193326Sed const ObjCInterfaceDecl *ID); 1346198092Srdivacky 1347193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel) 1348193326Sed { return EmitSelector(Builder, Sel); } 1349193326Sed 1350193326Sed /// The NeXT/Apple runtimes do not support typed selectors; just emit an 1351193326Sed /// untyped one. 1352193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, 1353193326Sed const ObjCMethodDecl *Method) 1354193326Sed { return EmitSelector(Builder, Method->getSelector()); } 1355198092Srdivacky 1356193326Sed virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); 1357198092Srdivacky 1358193326Sed virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); 1359193326Sed virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, 1360193326Sed const ObjCProtocolDecl *PD); 1361198092Srdivacky 1362198092Srdivacky virtual llvm::Constant *GetPropertyGetFunction() { 1363193326Sed return ObjCTypes.getGetPropertyFn(); 1364193326Sed } 1365198092Srdivacky virtual llvm::Constant *GetPropertySetFunction() { 1366198092Srdivacky return ObjCTypes.getSetPropertyFn(); 1367193326Sed } 1368193326Sed virtual llvm::Constant *EnumerationMutationFunction() { 1369193326Sed return ObjCTypes.getEnumerationMutationFn(); 1370193326Sed } 1371198092Srdivacky 1372193326Sed virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1373193326Sed const Stmt &S); 1374193326Sed virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 1375193326Sed const ObjCAtThrowStmt &S); 1376193326Sed virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1377193326Sed llvm::Value *AddrWeakObj); 1378193326Sed virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1379193326Sed llvm::Value *src, llvm::Value *dst); 1380193326Sed virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1381193326Sed llvm::Value *src, llvm::Value *dest); 1382193326Sed virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 1383198092Srdivacky llvm::Value *src, llvm::Value *dest, 1384198092Srdivacky llvm::Value *ivarOffset); 1385193326Sed virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 1386193326Sed llvm::Value *src, llvm::Value *dest); 1387198092Srdivacky virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 1388198092Srdivacky llvm::Value *dest, llvm::Value *src, 1389198092Srdivacky QualType Ty); 1390193326Sed virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 1391193326Sed QualType ObjectTy, 1392193326Sed llvm::Value *BaseValue, 1393193326Sed const ObjCIvarDecl *Ivar, 1394193326Sed unsigned CVRQualifiers); 1395193326Sed virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 1396193326Sed const ObjCInterfaceDecl *Interface, 1397193326Sed const ObjCIvarDecl *Ivar); 1398193326Sed}; 1399198092Srdivacky 1400193326Sed} // end anonymous namespace 1401193326Sed 1402193326Sed/* *** Helper Functions *** */ 1403193326Sed 1404193326Sed/// getConstantGEP() - Help routine to construct simple GEPs. 1405198092Srdivackystatic llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext, 1406198092Srdivacky llvm::Constant *C, 1407193326Sed unsigned idx0, 1408193326Sed unsigned idx1) { 1409193326Sed llvm::Value *Idxs[] = { 1410198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0), 1411198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1) 1412193326Sed }; 1413193326Sed return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2); 1414193326Sed} 1415193326Sed 1416193326Sed/// hasObjCExceptionAttribute - Return true if this class or any super 1417193326Sed/// class has the __objc_exception__ attribute. 1418198092Srdivackystatic bool hasObjCExceptionAttribute(ASTContext &Context, 1419194613Sed const ObjCInterfaceDecl *OID) { 1420195341Sed if (OID->hasAttr<ObjCExceptionAttr>()) 1421193326Sed return true; 1422193326Sed if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 1423194613Sed return hasObjCExceptionAttribute(Context, Super); 1424193326Sed return false; 1425193326Sed} 1426193326Sed 1427193326Sed/* *** CGObjCMac Public Interface *** */ 1428198092Srdivacky 1429193326SedCGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), 1430198092Srdivacky ObjCTypes(cgm) { 1431193326Sed ObjCABI = 1; 1432198092Srdivacky EmitImageInfo(); 1433193326Sed} 1434193326Sed 1435193326Sed/// GetClass - Return a reference to the class for the given interface 1436193326Sed/// decl. 1437193326Sedllvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder, 1438193326Sed const ObjCInterfaceDecl *ID) { 1439193326Sed return EmitClassRef(Builder, ID); 1440193326Sed} 1441193326Sed 1442193326Sed/// GetSelector - Return the pointer to the unique'd string for this selector. 1443193326Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) { 1444193326Sed return EmitSelector(Builder, Sel); 1445193326Sed} 1446193326Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl 1447198092Srdivacky *Method) { 1448193326Sed return EmitSelector(Builder, Method->getSelector()); 1449193326Sed} 1450193326Sed 1451193326Sed/// Generate a constant CFString object. 1452198092Srdivacky/* 1453198092Srdivacky struct __builtin_CFString { 1454198092Srdivacky const int *isa; // point to __CFConstantStringClassReference 1455198092Srdivacky int flags; 1456198092Srdivacky const char *str; 1457198092Srdivacky long length; 1458198092Srdivacky }; 1459193326Sed*/ 1460193326Sed 1461193326Sedllvm::Constant *CGObjCCommonMac::GenerateConstantString( 1462202879Srdivacky const StringLiteral *SL) { 1463202879Srdivacky return CGM.GetAddrOfConstantCFString(SL); 1464193326Sed} 1465193326Sed 1466193326Sed/// Generates a message send where the super is the receiver. This is 1467193326Sed/// a message send to self with special delivery semantics indicating 1468193326Sed/// which class's method should be called. 1469193326SedCodeGen::RValue 1470193326SedCGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1471193326Sed QualType ResultType, 1472193326Sed Selector Sel, 1473193326Sed const ObjCInterfaceDecl *Class, 1474193326Sed bool isCategoryImpl, 1475193326Sed llvm::Value *Receiver, 1476193326Sed bool IsClassMessage, 1477198092Srdivacky const CodeGen::CallArgList &CallArgs, 1478198092Srdivacky const ObjCMethodDecl *Method) { 1479193326Sed // Create and init a super structure; this is a (receiver, class) 1480193326Sed // pair we will pass to objc_msgSendSuper. 1481198092Srdivacky llvm::Value *ObjCSuper = 1482193326Sed CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); 1483198092Srdivacky llvm::Value *ReceiverAsObject = 1484193326Sed CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); 1485198092Srdivacky CGF.Builder.CreateStore(ReceiverAsObject, 1486193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 1487193326Sed 1488193326Sed // If this is a class message the metaclass is passed as the target. 1489193326Sed llvm::Value *Target; 1490193326Sed if (IsClassMessage) { 1491193326Sed if (isCategoryImpl) { 1492193326Sed // Message sent to 'super' in a class method defined in a category 1493193326Sed // implementation requires an odd treatment. 1494193326Sed // If we are in a class method, we must retrieve the 1495193326Sed // _metaclass_ for the current class, pointed at by 1496193326Sed // the class's "isa" pointer. The following assumes that 1497193326Sed // isa" is the first ivar in a class (which it must be). 1498193326Sed Target = EmitClassRef(CGF.Builder, Class->getSuperClass()); 1499193326Sed Target = CGF.Builder.CreateStructGEP(Target, 0); 1500193326Sed Target = CGF.Builder.CreateLoad(Target); 1501198092Srdivacky } else { 1502193326Sed llvm::Value *MetaClassPtr = EmitMetaClassRef(Class); 1503193326Sed llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1); 1504193326Sed llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr); 1505193326Sed Target = Super; 1506198092Srdivacky } 1507199482Srdivacky } 1508199482Srdivacky else if (isCategoryImpl) 1509193326Sed Target = EmitClassRef(CGF.Builder, Class->getSuperClass()); 1510199482Srdivacky else { 1511199482Srdivacky llvm::Value *ClassPtr = EmitSuperClassRef(Class); 1512199482Srdivacky ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1); 1513199482Srdivacky Target = CGF.Builder.CreateLoad(ClassPtr); 1514193326Sed } 1515193326Sed // FIXME: We shouldn't need to do this cast, rectify the ASTContext and 1516193326Sed // ObjCTypes types. 1517198092Srdivacky const llvm::Type *ClassTy = 1518193326Sed CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); 1519193326Sed Target = CGF.Builder.CreateBitCast(Target, ClassTy); 1520198092Srdivacky CGF.Builder.CreateStore(Target, 1521193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 1522198092Srdivacky return EmitLegacyMessageSend(CGF, ResultType, 1523193326Sed EmitSelector(CGF.Builder, Sel), 1524193326Sed ObjCSuper, ObjCTypes.SuperPtrCTy, 1525198092Srdivacky true, CallArgs, Method, ObjCTypes); 1526193326Sed} 1527198092Srdivacky 1528198092Srdivacky/// Generate code for a message send expression. 1529193326SedCodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1530193326Sed QualType ResultType, 1531193326Sed Selector Sel, 1532193326Sed llvm::Value *Receiver, 1533193326Sed bool IsClassMessage, 1534193326Sed const CallArgList &CallArgs, 1535193326Sed const ObjCMethodDecl *Method) { 1536193326Sed return EmitLegacyMessageSend(CGF, ResultType, 1537193326Sed EmitSelector(CGF.Builder, Sel), 1538193326Sed Receiver, CGF.getContext().getObjCIdType(), 1539198092Srdivacky false, CallArgs, Method, ObjCTypes); 1540193326Sed} 1541193326Sed 1542198092SrdivackyCodeGen::RValue 1543198092SrdivackyCGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, 1544198092Srdivacky QualType ResultType, 1545198092Srdivacky llvm::Value *Sel, 1546198092Srdivacky llvm::Value *Arg0, 1547198092Srdivacky QualType Arg0Ty, 1548198092Srdivacky bool IsSuper, 1549198092Srdivacky const CallArgList &CallArgs, 1550198092Srdivacky const ObjCMethodDecl *Method, 1551198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 1552193326Sed CallArgList ActualArgs; 1553193326Sed if (!IsSuper) 1554193326Sed Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp"); 1555193326Sed ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty)); 1556193326Sed ActualArgs.push_back(std::make_pair(RValue::get(Sel), 1557193326Sed CGF.getContext().getObjCSelType())); 1558193326Sed ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); 1559198092Srdivacky 1560193326Sed CodeGenTypes &Types = CGM.getTypes(); 1561203955Srdivacky const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs, 1562203955Srdivacky CC_Default, false); 1563198092Srdivacky const llvm::FunctionType *FTy = 1564198092Srdivacky Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); 1565198092Srdivacky 1566193326Sed llvm::Constant *Fn = NULL; 1567193326Sed if (CGM.ReturnTypeUsesSret(FnInfo)) { 1568193326Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) 1569198092Srdivacky : ObjCTypes.getSendStretFn(IsSuper); 1570193326Sed } else if (ResultType->isFloatingType()) { 1571193326Sed if (ObjCABI == 2) { 1572198092Srdivacky if (const BuiltinType *BT = ResultType->getAs<BuiltinType>()) { 1573193326Sed BuiltinType::Kind k = BT->getKind(); 1574193326Sed Fn = (k == BuiltinType::LongDouble) ? ObjCTypes.getSendFpretFn2(IsSuper) 1575198092Srdivacky : ObjCTypes.getSendFn2(IsSuper); 1576194179Sed } else { 1577194179Sed Fn = ObjCTypes.getSendFn2(IsSuper); 1578193326Sed } 1579198092Srdivacky } else 1580193326Sed // FIXME. This currently matches gcc's API for x86-32. May need to change 1581193326Sed // for others if we have their API. 1582193326Sed Fn = ObjCTypes.getSendFpretFn(IsSuper); 1583193326Sed } else { 1584193326Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper) 1585198092Srdivacky : ObjCTypes.getSendFn(IsSuper); 1586193326Sed } 1587193326Sed assert(Fn && "EmitLegacyMessageSend - unknown API"); 1588198092Srdivacky Fn = llvm::ConstantExpr::getBitCast(Fn, 1589198092Srdivacky llvm::PointerType::getUnqual(FTy)); 1590201361Srdivacky return CGF.EmitCall(FnInfo, Fn, ReturnValueSlot(), ActualArgs); 1591193326Sed} 1592193326Sed 1593198092Srdivackyllvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder, 1594193326Sed const ObjCProtocolDecl *PD) { 1595193326Sed // FIXME: I don't understand why gcc generates this, or where it is 1596193326Sed // resolved. Investigate. Its also wasteful to look this up over and over. 1597193326Sed LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); 1598193326Sed 1599193326Sed return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD), 1600193326Sed ObjCTypes.ExternalProtocolPtrTy); 1601193326Sed} 1602193326Sed 1603193326Sedvoid CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) { 1604193326Sed // FIXME: We shouldn't need this, the protocol decl should contain enough 1605193326Sed // information to tell us whether this was a declaration or a definition. 1606193326Sed DefinedProtocols.insert(PD->getIdentifier()); 1607193326Sed 1608193326Sed // If we have generated a forward reference to this protocol, emit 1609193326Sed // it now. Otherwise do nothing, the protocol objects are lazily 1610193326Sed // emitted. 1611198092Srdivacky if (Protocols.count(PD->getIdentifier())) 1612193326Sed GetOrEmitProtocol(PD); 1613193326Sed} 1614193326Sed 1615193326Sedllvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) { 1616193326Sed if (DefinedProtocols.count(PD->getIdentifier())) 1617193326Sed return GetOrEmitProtocol(PD); 1618193326Sed return GetOrEmitProtocolRef(PD); 1619193326Sed} 1620193326Sed 1621193326Sed/* 1622198092Srdivacky// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions 1623198092Srdivackystruct _objc_protocol { 1624198092Srdivackystruct _objc_protocol_extension *isa; 1625198092Srdivackychar *protocol_name; 1626198092Srdivackystruct _objc_protocol_list *protocol_list; 1627198092Srdivackystruct _objc__method_prototype_list *instance_methods; 1628198092Srdivackystruct _objc__method_prototype_list *class_methods 1629198092Srdivacky}; 1630193326Sed 1631198092SrdivackySee EmitProtocolExtension(). 1632193326Sed*/ 1633193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { 1634193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 1635193326Sed 1636193326Sed // Early exit if a defining object has already been generated. 1637193326Sed if (Entry && Entry->hasInitializer()) 1638193326Sed return Entry; 1639193326Sed 1640193326Sed // FIXME: I don't understand why gcc generates this, or where it is 1641193326Sed // resolved. Investigate. Its also wasteful to look this up over and over. 1642193326Sed LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); 1643193326Sed 1644193326Sed // Construct method lists. 1645193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 1646193326Sed std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; 1647198092Srdivacky for (ObjCProtocolDecl::instmeth_iterator 1648195341Sed i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { 1649193326Sed ObjCMethodDecl *MD = *i; 1650193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 1651193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 1652193326Sed OptInstanceMethods.push_back(C); 1653193326Sed } else { 1654193326Sed InstanceMethods.push_back(C); 1655198092Srdivacky } 1656193326Sed } 1657193326Sed 1658198092Srdivacky for (ObjCProtocolDecl::classmeth_iterator 1659195341Sed i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { 1660193326Sed ObjCMethodDecl *MD = *i; 1661193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 1662193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 1663193326Sed OptClassMethods.push_back(C); 1664193326Sed } else { 1665193326Sed ClassMethods.push_back(C); 1666198092Srdivacky } 1667193326Sed } 1668193326Sed 1669193326Sed std::vector<llvm::Constant*> Values(5); 1670193326Sed Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods); 1671193326Sed Values[1] = GetClassName(PD->getIdentifier()); 1672198092Srdivacky Values[2] = 1673198398Srdivacky EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(), 1674193326Sed PD->protocol_begin(), 1675193326Sed PD->protocol_end()); 1676198092Srdivacky Values[3] = 1677198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(), 1678193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 1679193326Sed InstanceMethods); 1680198092Srdivacky Values[4] = 1681198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(), 1682193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1683193326Sed ClassMethods); 1684193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, 1685193326Sed Values); 1686198092Srdivacky 1687193326Sed if (Entry) { 1688193326Sed // Already created, fix the linkage and update the initializer. 1689193326Sed Entry->setLinkage(llvm::GlobalValue::InternalLinkage); 1690193326Sed Entry->setInitializer(Init); 1691193326Sed } else { 1692198092Srdivacky Entry = 1693198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, 1694193326Sed llvm::GlobalValue::InternalLinkage, 1695198092Srdivacky Init, 1696198398Srdivacky "\01L_OBJC_PROTOCOL_" + PD->getName()); 1697193326Sed Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); 1698193326Sed Entry->setAlignment(4); 1699193326Sed // FIXME: Is this necessary? Why only for protocol? 1700193326Sed Entry->setAlignment(4); 1701193326Sed } 1702198092Srdivacky CGM.AddUsedGlobal(Entry); 1703193326Sed 1704193326Sed return Entry; 1705193326Sed} 1706193326Sed 1707193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { 1708193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 1709193326Sed 1710193326Sed if (!Entry) { 1711193326Sed // We use the initializer as a marker of whether this is a forward 1712193326Sed // reference or not. At module finalization we add the empty 1713193326Sed // contents for protocols which were referenced but never defined. 1714198092Srdivacky Entry = 1715198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, 1716193326Sed llvm::GlobalValue::ExternalLinkage, 1717193326Sed 0, 1718198398Srdivacky "\01L_OBJC_PROTOCOL_" + PD->getName()); 1719193326Sed Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); 1720193326Sed Entry->setAlignment(4); 1721193326Sed // FIXME: Is this necessary? Why only for protocol? 1722193326Sed Entry->setAlignment(4); 1723193326Sed } 1724198092Srdivacky 1725193326Sed return Entry; 1726193326Sed} 1727193326Sed 1728193326Sed/* 1729193326Sed struct _objc_protocol_extension { 1730198092Srdivacky uint32_t size; 1731198092Srdivacky struct objc_method_description_list *optional_instance_methods; 1732198092Srdivacky struct objc_method_description_list *optional_class_methods; 1733198092Srdivacky struct objc_property_list *instance_properties; 1734193326Sed }; 1735193326Sed*/ 1736193326Sedllvm::Constant * 1737193326SedCGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, 1738193326Sed const ConstantVector &OptInstanceMethods, 1739193326Sed const ConstantVector &OptClassMethods) { 1740198092Srdivacky uint64_t Size = 1741193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); 1742193326Sed std::vector<llvm::Constant*> Values(4); 1743193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 1744198092Srdivacky Values[1] = 1745198092Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_" 1746198398Srdivacky + PD->getName(), 1747193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 1748193326Sed OptInstanceMethods); 1749198092Srdivacky Values[2] = 1750198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(), 1751193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1752193326Sed OptClassMethods); 1753198398Srdivacky Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 1754193326Sed 0, PD, ObjCTypes); 1755193326Sed 1756193326Sed // Return null if no extension bits are used. 1757198092Srdivacky if (Values[1]->isNullValue() && Values[2]->isNullValue() && 1758193326Sed Values[3]->isNullValue()) 1759193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); 1760193326Sed 1761198092Srdivacky llvm::Constant *Init = 1762193326Sed llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values); 1763193326Sed 1764193326Sed // No special section, but goes in llvm.used 1765198398Srdivacky return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(), 1766198092Srdivacky Init, 1767193326Sed 0, 0, true); 1768193326Sed} 1769193326Sed 1770193326Sed/* 1771193326Sed struct objc_protocol_list { 1772198092Srdivacky struct objc_protocol_list *next; 1773198092Srdivacky long count; 1774198092Srdivacky Protocol *list[]; 1775193326Sed }; 1776193326Sed*/ 1777193326Sedllvm::Constant * 1778198398SrdivackyCGObjCMac::EmitProtocolList(llvm::Twine Name, 1779193326Sed ObjCProtocolDecl::protocol_iterator begin, 1780193326Sed ObjCProtocolDecl::protocol_iterator end) { 1781193326Sed std::vector<llvm::Constant*> ProtocolRefs; 1782193326Sed 1783193326Sed for (; begin != end; ++begin) 1784193326Sed ProtocolRefs.push_back(GetProtocolRef(*begin)); 1785193326Sed 1786193326Sed // Just return null for empty protocol lists 1787198092Srdivacky if (ProtocolRefs.empty()) 1788193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 1789193326Sed 1790193326Sed // This list is null terminated. 1791193326Sed ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy)); 1792193326Sed 1793193326Sed std::vector<llvm::Constant*> Values(3); 1794193326Sed // This field is only used by the runtime. 1795193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 1796198092Srdivacky Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, 1797198092Srdivacky ProtocolRefs.size() - 1); 1798198092Srdivacky Values[2] = 1799198092Srdivacky llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy, 1800198092Srdivacky ProtocolRefs.size()), 1801193326Sed ProtocolRefs); 1802198092Srdivacky 1803198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 1804198092Srdivacky llvm::GlobalVariable *GV = 1805193326Sed CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1806193326Sed 4, false); 1807193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy); 1808193326Sed} 1809193326Sed 1810200583Srdivackyvoid CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet, 1811200583Srdivacky std::vector<llvm::Constant*> &Properties, 1812200583Srdivacky const Decl *Container, 1813200583Srdivacky const ObjCProtocolDecl *PROTO, 1814200583Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 1815200583Srdivacky std::vector<llvm::Constant*> Prop(2); 1816200583Srdivacky for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(), 1817200583Srdivacky E = PROTO->protocol_end(); P != E; ++P) 1818200583Srdivacky PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes); 1819200583Srdivacky for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(), 1820200583Srdivacky E = PROTO->prop_end(); I != E; ++I) { 1821200583Srdivacky const ObjCPropertyDecl *PD = *I; 1822200583Srdivacky if (!PropertySet.insert(PD->getIdentifier())) 1823200583Srdivacky continue; 1824200583Srdivacky Prop[0] = GetPropertyName(PD->getIdentifier()); 1825200583Srdivacky Prop[1] = GetPropertyTypeString(PD, Container); 1826200583Srdivacky Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop)); 1827200583Srdivacky } 1828200583Srdivacky} 1829200583Srdivacky 1830193326Sed/* 1831193326Sed struct _objc_property { 1832198092Srdivacky const char * const name; 1833198092Srdivacky const char * const attributes; 1834193326Sed }; 1835193326Sed 1836193326Sed struct _objc_property_list { 1837198092Srdivacky uint32_t entsize; // sizeof (struct _objc_property) 1838198092Srdivacky uint32_t prop_count; 1839198092Srdivacky struct _objc_property[prop_count]; 1840193326Sed }; 1841193326Sed*/ 1842198398Srdivackyllvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name, 1843198092Srdivacky const Decl *Container, 1844198092Srdivacky const ObjCContainerDecl *OCD, 1845198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 1846193326Sed std::vector<llvm::Constant*> Properties, Prop(2); 1847200583Srdivacky llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet; 1848198092Srdivacky for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(), 1849198092Srdivacky E = OCD->prop_end(); I != E; ++I) { 1850193326Sed const ObjCPropertyDecl *PD = *I; 1851200583Srdivacky PropertySet.insert(PD->getIdentifier()); 1852193326Sed Prop[0] = GetPropertyName(PD->getIdentifier()); 1853193326Sed Prop[1] = GetPropertyTypeString(PD, Container); 1854193326Sed Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, 1855193326Sed Prop)); 1856193326Sed } 1857200583Srdivacky if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) 1858200583Srdivacky for (ObjCInterfaceDecl::protocol_iterator P = OID->protocol_begin(), 1859200583Srdivacky E = OID->protocol_end(); P != E; ++P) 1860200583Srdivacky PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes); 1861193326Sed 1862193326Sed // Return null for empty list. 1863193326Sed if (Properties.empty()) 1864193326Sed return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 1865193326Sed 1866198092Srdivacky unsigned PropertySize = 1867193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy); 1868193326Sed std::vector<llvm::Constant*> Values(3); 1869193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize); 1870193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size()); 1871198092Srdivacky llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy, 1872193326Sed Properties.size()); 1873193326Sed Values[2] = llvm::ConstantArray::get(AT, Properties); 1874198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 1875193326Sed 1876198092Srdivacky llvm::GlobalVariable *GV = 1877198092Srdivacky CreateMetadataVar(Name, Init, 1878198092Srdivacky (ObjCABI == 2) ? "__DATA, __objc_const" : 1879193326Sed "__OBJC,__property,regular,no_dead_strip", 1880198092Srdivacky (ObjCABI == 2) ? 8 : 4, 1881193326Sed true); 1882193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy); 1883193326Sed} 1884193326Sed 1885193326Sed/* 1886193326Sed struct objc_method_description_list { 1887198092Srdivacky int count; 1888198092Srdivacky struct objc_method_description list[]; 1889193326Sed }; 1890193326Sed*/ 1891193326Sedllvm::Constant * 1892193326SedCGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { 1893193326Sed std::vector<llvm::Constant*> Desc(2); 1894198092Srdivacky Desc[0] = 1895198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 1896198092Srdivacky ObjCTypes.SelectorPtrTy); 1897193326Sed Desc[1] = GetMethodVarType(MD); 1898193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy, 1899193326Sed Desc); 1900193326Sed} 1901193326Sed 1902198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name, 1903193326Sed const char *Section, 1904193326Sed const ConstantVector &Methods) { 1905193326Sed // Return null for empty list. 1906193326Sed if (Methods.empty()) 1907193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); 1908193326Sed 1909193326Sed std::vector<llvm::Constant*> Values(2); 1910193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 1911198092Srdivacky llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy, 1912193326Sed Methods.size()); 1913193326Sed Values[1] = llvm::ConstantArray::get(AT, Methods); 1914198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 1915193326Sed 1916193326Sed llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true); 1917198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, 1918193326Sed ObjCTypes.MethodDescriptionListPtrTy); 1919193326Sed} 1920193326Sed 1921193326Sed/* 1922193326Sed struct _objc_category { 1923198092Srdivacky char *category_name; 1924198092Srdivacky char *class_name; 1925198092Srdivacky struct _objc_method_list *instance_methods; 1926198092Srdivacky struct _objc_method_list *class_methods; 1927198092Srdivacky struct _objc_protocol_list *protocols; 1928198092Srdivacky uint32_t size; // <rdar://4585769> 1929198092Srdivacky struct _objc_property_list *instance_properties; 1930193326Sed }; 1931198092Srdivacky*/ 1932193326Sedvoid CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 1933193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy); 1934193326Sed 1935193326Sed // FIXME: This is poor design, the OCD should have a pointer to the category 1936193326Sed // decl. Additionally, note that Category can be null for the @implementation 1937193326Sed // w/o an @interface case. Sema should just create one for us as it does for 1938193326Sed // @implementation so everyone else can live life under a clear blue sky. 1939193326Sed const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); 1940198092Srdivacky const ObjCCategoryDecl *Category = 1941193326Sed Interface->FindCategoryDeclaration(OCD->getIdentifier()); 1942193326Sed 1943198398Srdivacky llvm::SmallString<256> ExtName; 1944198398Srdivacky llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_' 1945198398Srdivacky << OCD->getName(); 1946198398Srdivacky 1947193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 1948198092Srdivacky for (ObjCCategoryImplDecl::instmeth_iterator 1949195341Sed i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { 1950193326Sed // Instance methods should always be defined. 1951193326Sed InstanceMethods.push_back(GetMethodConstant(*i)); 1952193326Sed } 1953198092Srdivacky for (ObjCCategoryImplDecl::classmeth_iterator 1954195341Sed i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { 1955193326Sed // Class methods should always be defined. 1956193326Sed ClassMethods.push_back(GetMethodConstant(*i)); 1957193326Sed } 1958193326Sed 1959193326Sed std::vector<llvm::Constant*> Values(7); 1960193326Sed Values[0] = GetClassName(OCD->getIdentifier()); 1961193326Sed Values[1] = GetClassName(Interface->getIdentifier()); 1962193326Sed LazySymbols.insert(Interface->getIdentifier()); 1963198092Srdivacky Values[2] = 1964198398Srdivacky EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(), 1965193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 1966193326Sed InstanceMethods); 1967198092Srdivacky Values[3] = 1968198398Srdivacky EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(), 1969193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1970193326Sed ClassMethods); 1971193326Sed if (Category) { 1972198092Srdivacky Values[4] = 1973198398Srdivacky EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(), 1974193326Sed Category->protocol_begin(), 1975193326Sed Category->protocol_end()); 1976193326Sed } else { 1977193326Sed Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 1978193326Sed } 1979193326Sed Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 1980193326Sed 1981193326Sed // If there is no category @interface then there can be no properties. 1982193326Sed if (Category) { 1983198398Srdivacky Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), 1984193326Sed OCD, Category, ObjCTypes); 1985193326Sed } else { 1986193326Sed Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 1987193326Sed } 1988198092Srdivacky 1989193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy, 1990193326Sed Values); 1991193326Sed 1992198092Srdivacky llvm::GlobalVariable *GV = 1993198398Srdivacky CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init, 1994193326Sed "__OBJC,__category,regular,no_dead_strip", 1995193326Sed 4, true); 1996193326Sed DefinedCategories.push_back(GV); 1997193326Sed} 1998193326Sed 1999193326Sed// FIXME: Get from somewhere? 2000193326Sedenum ClassFlags { 2001193326Sed eClassFlags_Factory = 0x00001, 2002193326Sed eClassFlags_Meta = 0x00002, 2003193326Sed // <rdr://5142207> 2004193326Sed eClassFlags_HasCXXStructors = 0x02000, 2005193326Sed eClassFlags_Hidden = 0x20000, 2006193326Sed eClassFlags_ABI2_Hidden = 0x00010, 2007193326Sed eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634> 2008193326Sed}; 2009193326Sed 2010193326Sed/* 2011193326Sed struct _objc_class { 2012198092Srdivacky Class isa; 2013198092Srdivacky Class super_class; 2014198092Srdivacky const char *name; 2015198092Srdivacky long version; 2016198092Srdivacky long info; 2017198092Srdivacky long instance_size; 2018198092Srdivacky struct _objc_ivar_list *ivars; 2019198092Srdivacky struct _objc_method_list *methods; 2020198092Srdivacky struct _objc_cache *cache; 2021198092Srdivacky struct _objc_protocol_list *protocols; 2022198092Srdivacky // Objective-C 1.0 extensions (<rdr://4585769>) 2023198092Srdivacky const char *ivar_layout; 2024198092Srdivacky struct _objc_class_ext *ext; 2025193326Sed }; 2026193326Sed 2027193326Sed See EmitClassExtension(); 2028198092Srdivacky*/ 2029193326Sedvoid CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { 2030193326Sed DefinedSymbols.insert(ID->getIdentifier()); 2031193326Sed 2032193326Sed std::string ClassName = ID->getNameAsString(); 2033193326Sed // FIXME: Gross 2034198092Srdivacky ObjCInterfaceDecl *Interface = 2035193326Sed const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); 2036198092Srdivacky llvm::Constant *Protocols = 2037198398Srdivacky EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(), 2038193326Sed Interface->protocol_begin(), 2039193326Sed Interface->protocol_end()); 2040193326Sed unsigned Flags = eClassFlags_Factory; 2041198092Srdivacky unsigned Size = 2042193326Sed CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8; 2043193326Sed 2044193326Sed // FIXME: Set CXX-structors flag. 2045193326Sed if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden) 2046193326Sed Flags |= eClassFlags_Hidden; 2047193326Sed 2048193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 2049198092Srdivacky for (ObjCImplementationDecl::instmeth_iterator 2050195341Sed i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { 2051193326Sed // Instance methods should always be defined. 2052193326Sed InstanceMethods.push_back(GetMethodConstant(*i)); 2053193326Sed } 2054198092Srdivacky for (ObjCImplementationDecl::classmeth_iterator 2055195341Sed i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { 2056193326Sed // Class methods should always be defined. 2057193326Sed ClassMethods.push_back(GetMethodConstant(*i)); 2058193326Sed } 2059193326Sed 2060198092Srdivacky for (ObjCImplementationDecl::propimpl_iterator 2061195341Sed i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { 2062193326Sed ObjCPropertyImplDecl *PID = *i; 2063193326Sed 2064193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { 2065193326Sed ObjCPropertyDecl *PD = PID->getPropertyDecl(); 2066193326Sed 2067193326Sed if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) 2068193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 2069193326Sed InstanceMethods.push_back(C); 2070193326Sed if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) 2071193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 2072193326Sed InstanceMethods.push_back(C); 2073193326Sed } 2074193326Sed } 2075193326Sed 2076193326Sed std::vector<llvm::Constant*> Values(12); 2077193326Sed Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods); 2078193326Sed if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) { 2079193326Sed // Record a reference to the super class. 2080193326Sed LazySymbols.insert(Super->getIdentifier()); 2081193326Sed 2082198092Srdivacky Values[ 1] = 2083193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), 2084193326Sed ObjCTypes.ClassPtrTy); 2085193326Sed } else { 2086193326Sed Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy); 2087193326Sed } 2088193326Sed Values[ 2] = GetClassName(ID->getIdentifier()); 2089193326Sed // Version is always 0. 2090193326Sed Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 2091193326Sed Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); 2092193326Sed Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 2093193326Sed Values[ 6] = EmitIvarList(ID, false); 2094198092Srdivacky Values[ 7] = 2095198398Srdivacky EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(), 2096193326Sed "__OBJC,__inst_meth,regular,no_dead_strip", 2097193326Sed InstanceMethods); 2098193326Sed // cache is always NULL. 2099193326Sed Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy); 2100193326Sed Values[ 9] = Protocols; 2101198092Srdivacky Values[10] = BuildIvarLayout(ID, true); 2102193326Sed Values[11] = EmitClassExtension(ID); 2103193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy, 2104193326Sed Values); 2105199482Srdivacky std::string Name("\01L_OBJC_CLASS_"); 2106199482Srdivacky Name += ClassName; 2107199482Srdivacky const char *Section = "__OBJC,__class,regular,no_dead_strip"; 2108199482Srdivacky // Check for a forward reference. 2109199482Srdivacky llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 2110199482Srdivacky if (GV) { 2111199482Srdivacky assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2112199482Srdivacky "Forward metaclass reference has incorrect type."); 2113199482Srdivacky GV->setLinkage(llvm::GlobalValue::InternalLinkage); 2114199482Srdivacky GV->setInitializer(Init); 2115199482Srdivacky GV->setSection(Section); 2116199482Srdivacky GV->setAlignment(4); 2117199482Srdivacky CGM.AddUsedGlobal(GV); 2118199482Srdivacky } 2119199482Srdivacky else 2120199482Srdivacky GV = CreateMetadataVar(Name, Init, Section, 4, true); 2121193326Sed DefinedClasses.push_back(GV); 2122193326Sed} 2123193326Sed 2124193326Sedllvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, 2125193326Sed llvm::Constant *Protocols, 2126193326Sed const ConstantVector &Methods) { 2127193326Sed unsigned Flags = eClassFlags_Meta; 2128193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy); 2129193326Sed 2130193326Sed if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden) 2131193326Sed Flags |= eClassFlags_Hidden; 2132198092Srdivacky 2133193326Sed std::vector<llvm::Constant*> Values(12); 2134193326Sed // The isa for the metaclass is the root of the hierarchy. 2135193326Sed const ObjCInterfaceDecl *Root = ID->getClassInterface(); 2136193326Sed while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) 2137193326Sed Root = Super; 2138198092Srdivacky Values[ 0] = 2139193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()), 2140193326Sed ObjCTypes.ClassPtrTy); 2141193326Sed // The super class for the metaclass is emitted as the name of the 2142193326Sed // super class. The runtime fixes this up to point to the 2143193326Sed // *metaclass* for the super class. 2144193326Sed if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) { 2145198092Srdivacky Values[ 1] = 2146193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), 2147193326Sed ObjCTypes.ClassPtrTy); 2148193326Sed } else { 2149193326Sed Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy); 2150193326Sed } 2151193326Sed Values[ 2] = GetClassName(ID->getIdentifier()); 2152193326Sed // Version is always 0. 2153193326Sed Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 2154193326Sed Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); 2155193326Sed Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 2156193326Sed Values[ 6] = EmitIvarList(ID, true); 2157198092Srdivacky Values[ 7] = 2158193326Sed EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(), 2159193326Sed "__OBJC,__cls_meth,regular,no_dead_strip", 2160193326Sed Methods); 2161193326Sed // cache is always NULL. 2162193326Sed Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy); 2163193326Sed Values[ 9] = Protocols; 2164193326Sed // ivar_layout for metaclass is always NULL. 2165193326Sed Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 2166193326Sed // The class extension is always unused for metaclasses. 2167193326Sed Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); 2168193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy, 2169193326Sed Values); 2170193326Sed 2171193326Sed std::string Name("\01L_OBJC_METACLASS_"); 2172193326Sed Name += ID->getNameAsCString(); 2173193326Sed 2174193326Sed // Check for a forward reference. 2175193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 2176193326Sed if (GV) { 2177193326Sed assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2178193326Sed "Forward metaclass reference has incorrect type."); 2179193326Sed GV->setLinkage(llvm::GlobalValue::InternalLinkage); 2180193326Sed GV->setInitializer(Init); 2181193326Sed } else { 2182198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 2183193326Sed llvm::GlobalValue::InternalLinkage, 2184198092Srdivacky Init, Name); 2185193326Sed } 2186193326Sed GV->setSection("__OBJC,__meta_class,regular,no_dead_strip"); 2187193326Sed GV->setAlignment(4); 2188198092Srdivacky CGM.AddUsedGlobal(GV); 2189193326Sed 2190193326Sed return GV; 2191193326Sed} 2192193326Sed 2193198092Srdivackyllvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) { 2194193326Sed std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString(); 2195193326Sed 2196193326Sed // FIXME: Should we look these up somewhere other than the module. Its a bit 2197193326Sed // silly since we only generate these while processing an implementation, so 2198193326Sed // exactly one pointer would work if know when we entered/exitted an 2199193326Sed // implementation block. 2200193326Sed 2201193326Sed // Check for an existing forward reference. 2202193326Sed // Previously, metaclass with internal linkage may have been defined. 2203193326Sed // pass 'true' as 2nd argument so it is returned. 2204198092Srdivacky if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, 2205198092Srdivacky true)) { 2206193326Sed assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2207193326Sed "Forward metaclass reference has incorrect type."); 2208193326Sed return GV; 2209193326Sed } else { 2210193326Sed // Generate as an external reference to keep a consistent 2211193326Sed // module. This will be patched up when we emit the metaclass. 2212198092Srdivacky return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 2213193326Sed llvm::GlobalValue::ExternalLinkage, 2214193326Sed 0, 2215198092Srdivacky Name); 2216193326Sed } 2217193326Sed} 2218193326Sed 2219199482Srdivackyllvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) { 2220199482Srdivacky std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString(); 2221199482Srdivacky 2222199482Srdivacky if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, 2223199482Srdivacky true)) { 2224199482Srdivacky assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2225199482Srdivacky "Forward class metadata reference has incorrect type."); 2226199482Srdivacky return GV; 2227199482Srdivacky } else { 2228199482Srdivacky return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 2229199482Srdivacky llvm::GlobalValue::ExternalLinkage, 2230199482Srdivacky 0, 2231199482Srdivacky Name); 2232199482Srdivacky } 2233199482Srdivacky} 2234199482Srdivacky 2235193326Sed/* 2236193326Sed struct objc_class_ext { 2237198092Srdivacky uint32_t size; 2238198092Srdivacky const char *weak_ivar_layout; 2239198092Srdivacky struct _objc_property_list *properties; 2240193326Sed }; 2241193326Sed*/ 2242193326Sedllvm::Constant * 2243193326SedCGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) { 2244198092Srdivacky uint64_t Size = 2245193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy); 2246193326Sed 2247193326Sed std::vector<llvm::Constant*> Values(3); 2248193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 2249193326Sed Values[1] = BuildIvarLayout(ID, false); 2250198398Srdivacky Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), 2251193326Sed ID, ID->getClassInterface(), ObjCTypes); 2252193326Sed 2253193326Sed // Return null if no extension bits are used. 2254193326Sed if (Values[1]->isNullValue() && Values[2]->isNullValue()) 2255193326Sed return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); 2256193326Sed 2257198092Srdivacky llvm::Constant *Init = 2258193326Sed llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values); 2259198398Srdivacky return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(), 2260198092Srdivacky Init, "__OBJC,__class_ext,regular,no_dead_strip", 2261193326Sed 4, true); 2262193326Sed} 2263193326Sed 2264193326Sed/* 2265193326Sed struct objc_ivar { 2266198092Srdivacky char *ivar_name; 2267198092Srdivacky char *ivar_type; 2268198092Srdivacky int ivar_offset; 2269193326Sed }; 2270193326Sed 2271193326Sed struct objc_ivar_list { 2272198092Srdivacky int ivar_count; 2273198092Srdivacky struct objc_ivar list[count]; 2274193326Sed }; 2275198092Srdivacky*/ 2276193326Sedllvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, 2277193326Sed bool ForClass) { 2278193326Sed std::vector<llvm::Constant*> Ivars, Ivar(3); 2279193326Sed 2280193326Sed // When emitting the root class GCC emits ivar entries for the 2281193326Sed // actual class structure. It is not clear if we need to follow this 2282193326Sed // behavior; for now lets try and get away with not doing it. If so, 2283193326Sed // the cleanest solution would be to make up an ObjCInterfaceDecl 2284193326Sed // for the class. 2285193326Sed if (ForClass) 2286193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); 2287198092Srdivacky 2288198092Srdivacky ObjCInterfaceDecl *OID = 2289193326Sed const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); 2290198092Srdivacky 2291193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; 2292193576Sed CGM.getContext().ShallowCollectObjCIvars(OID, OIvars); 2293198092Srdivacky 2294193326Sed for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { 2295193326Sed ObjCIvarDecl *IVD = OIvars[i]; 2296193576Sed // Ignore unnamed bit-fields. 2297193576Sed if (!IVD->getDeclName()) 2298198092Srdivacky continue; 2299193326Sed Ivar[0] = GetMethodVarName(IVD->getIdentifier()); 2300193326Sed Ivar[1] = GetMethodVarType(IVD); 2301198092Srdivacky Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, 2302193326Sed ComputeIvarBaseOffset(CGM, OID, IVD)); 2303193326Sed Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar)); 2304193326Sed } 2305193326Sed 2306193326Sed // Return null for empty list. 2307193326Sed if (Ivars.empty()) 2308193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); 2309193326Sed 2310193326Sed std::vector<llvm::Constant*> Values(2); 2311193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size()); 2312193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy, 2313193326Sed Ivars.size()); 2314193326Sed Values[1] = llvm::ConstantArray::get(AT, Ivars); 2315198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 2316193326Sed 2317193326Sed llvm::GlobalVariable *GV; 2318193326Sed if (ForClass) 2319198398Srdivacky GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(), 2320198092Srdivacky Init, "__OBJC,__class_vars,regular,no_dead_strip", 2321193326Sed 4, true); 2322193326Sed else 2323198398Srdivacky GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(), 2324193326Sed Init, "__OBJC,__instance_vars,regular,no_dead_strip", 2325193326Sed 4, true); 2326193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy); 2327193326Sed} 2328193326Sed 2329193326Sed/* 2330193326Sed struct objc_method { 2331198092Srdivacky SEL method_name; 2332198092Srdivacky char *method_types; 2333198092Srdivacky void *method; 2334193326Sed }; 2335198092Srdivacky 2336193326Sed struct objc_method_list { 2337198092Srdivacky struct objc_method_list *obsolete; 2338198092Srdivacky int count; 2339198092Srdivacky struct objc_method methods_list[count]; 2340193326Sed }; 2341193326Sed*/ 2342193326Sed 2343193326Sed/// GetMethodConstant - Return a struct objc_method constant for the 2344193326Sed/// given method if it has been defined. The result is null if the 2345193326Sed/// method has not been defined. The return value has type MethodPtrTy. 2346193326Sedllvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) { 2347193326Sed // FIXME: Use DenseMap::lookup 2348193326Sed llvm::Function *Fn = MethodDefinitions[MD]; 2349193326Sed if (!Fn) 2350193326Sed return 0; 2351198092Srdivacky 2352193326Sed std::vector<llvm::Constant*> Method(3); 2353198092Srdivacky Method[0] = 2354193326Sed llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 2355193326Sed ObjCTypes.SelectorPtrTy); 2356193326Sed Method[1] = GetMethodVarType(MD); 2357193326Sed Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy); 2358193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method); 2359193326Sed} 2360193326Sed 2361198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name, 2362193326Sed const char *Section, 2363193326Sed const ConstantVector &Methods) { 2364193326Sed // Return null for empty list. 2365193326Sed if (Methods.empty()) 2366193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy); 2367193326Sed 2368193326Sed std::vector<llvm::Constant*> Values(3); 2369193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 2370193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 2371193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy, 2372193326Sed Methods.size()); 2373193326Sed Values[2] = llvm::ConstantArray::get(AT, Methods); 2374198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 2375193326Sed 2376193326Sed llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true); 2377193326Sed return llvm::ConstantExpr::getBitCast(GV, 2378193326Sed ObjCTypes.MethodListPtrTy); 2379193326Sed} 2380193326Sed 2381193326Sedllvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD, 2382198092Srdivacky const ObjCContainerDecl *CD) { 2383198398Srdivacky llvm::SmallString<256> Name; 2384193326Sed GetNameForMethod(OMD, CD, Name); 2385193326Sed 2386193326Sed CodeGenTypes &Types = CGM.getTypes(); 2387193326Sed const llvm::FunctionType *MethodTy = 2388193326Sed Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic()); 2389198092Srdivacky llvm::Function *Method = 2390193326Sed llvm::Function::Create(MethodTy, 2391193326Sed llvm::GlobalValue::InternalLinkage, 2392198398Srdivacky Name.str(), 2393193326Sed &CGM.getModule()); 2394193326Sed MethodDefinitions.insert(std::make_pair(OMD, Method)); 2395193326Sed 2396193326Sed return Method; 2397193326Sed} 2398193326Sed 2399193326Sedllvm::GlobalVariable * 2400198398SrdivackyCGObjCCommonMac::CreateMetadataVar(llvm::Twine Name, 2401193326Sed llvm::Constant *Init, 2402193326Sed const char *Section, 2403193326Sed unsigned Align, 2404193326Sed bool AddToUsed) { 2405193326Sed const llvm::Type *Ty = Init->getType(); 2406198092Srdivacky llvm::GlobalVariable *GV = 2407198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Ty, false, 2408198092Srdivacky llvm::GlobalValue::InternalLinkage, Init, Name); 2409193326Sed if (Section) 2410193326Sed GV->setSection(Section); 2411193326Sed if (Align) 2412193326Sed GV->setAlignment(Align); 2413193326Sed if (AddToUsed) 2414198092Srdivacky CGM.AddUsedGlobal(GV); 2415193326Sed return GV; 2416193326Sed} 2417193326Sed 2418198092Srdivackyllvm::Function *CGObjCMac::ModuleInitFunction() { 2419193326Sed // Abuse this interface function as a place to finalize. 2420193326Sed FinishModule(); 2421193326Sed return NULL; 2422193326Sed} 2423193326Sed 2424193326Sedllvm::Constant *CGObjCMac::GetPropertyGetFunction() { 2425193326Sed return ObjCTypes.getGetPropertyFn(); 2426193326Sed} 2427193326Sed 2428193326Sedllvm::Constant *CGObjCMac::GetPropertySetFunction() { 2429193326Sed return ObjCTypes.getSetPropertyFn(); 2430193326Sed} 2431193326Sed 2432193326Sedllvm::Constant *CGObjCMac::EnumerationMutationFunction() { 2433193326Sed return ObjCTypes.getEnumerationMutationFn(); 2434193326Sed} 2435193326Sed 2436198092Srdivacky/* 2437193326Sed 2438198092Srdivacky Objective-C setjmp-longjmp (sjlj) Exception Handling 2439198092Srdivacky -- 2440193326Sed 2441198092Srdivacky The basic framework for a @try-catch-finally is as follows: 2442198092Srdivacky { 2443193326Sed objc_exception_data d; 2444193326Sed id _rethrow = null; 2445193326Sed bool _call_try_exit = true; 2446198092Srdivacky 2447193326Sed objc_exception_try_enter(&d); 2448193326Sed if (!setjmp(d.jmp_buf)) { 2449198092Srdivacky ... try body ... 2450193326Sed } else { 2451198092Srdivacky // exception path 2452198092Srdivacky id _caught = objc_exception_extract(&d); 2453198092Srdivacky 2454198092Srdivacky // enter new try scope for handlers 2455198092Srdivacky if (!setjmp(d.jmp_buf)) { 2456198092Srdivacky ... match exception and execute catch blocks ... 2457198092Srdivacky 2458198092Srdivacky // fell off end, rethrow. 2459198092Srdivacky _rethrow = _caught; 2460198092Srdivacky ... jump-through-finally to finally_rethrow ... 2461198092Srdivacky } else { 2462198092Srdivacky // exception in catch block 2463198092Srdivacky _rethrow = objc_exception_extract(&d); 2464198092Srdivacky _call_try_exit = false; 2465198092Srdivacky ... jump-through-finally to finally_rethrow ... 2466193326Sed } 2467198092Srdivacky } 2468193326Sed ... jump-through-finally to finally_end ... 2469193326Sed 2470198092Srdivacky finally: 2471193326Sed if (_call_try_exit) 2472198092Srdivacky objc_exception_try_exit(&d); 2473193326Sed 2474193326Sed ... finally block .... 2475193326Sed ... dispatch to finally destination ... 2476193326Sed 2477198092Srdivacky finally_rethrow: 2478193326Sed objc_exception_throw(_rethrow); 2479193326Sed 2480198092Srdivacky finally_end: 2481198092Srdivacky } 2482193326Sed 2483198092Srdivacky This framework differs slightly from the one gcc uses, in that gcc 2484198092Srdivacky uses _rethrow to determine if objc_exception_try_exit should be called 2485198092Srdivacky and if the object should be rethrown. This breaks in the face of 2486198092Srdivacky throwing nil and introduces unnecessary branches. 2487193326Sed 2488198092Srdivacky We specialize this framework for a few particular circumstances: 2489193326Sed 2490198092Srdivacky - If there are no catch blocks, then we avoid emitting the second 2491198092Srdivacky exception handling context. 2492193326Sed 2493198092Srdivacky - If there is a catch-all catch block (i.e. @catch(...) or @catch(id 2494198092Srdivacky e)) we avoid emitting the code to rethrow an uncaught exception. 2495193326Sed 2496198092Srdivacky - FIXME: If there is no @finally block we can do a few more 2497198092Srdivacky simplifications. 2498193326Sed 2499198092Srdivacky Rethrows and Jumps-Through-Finally 2500198092Srdivacky -- 2501193326Sed 2502198092Srdivacky Support for implicit rethrows and jumping through the finally block is 2503198092Srdivacky handled by storing the current exception-handling context in 2504198092Srdivacky ObjCEHStack. 2505193326Sed 2506198092Srdivacky In order to implement proper @finally semantics, we support one basic 2507198092Srdivacky mechanism for jumping through the finally block to an arbitrary 2508198092Srdivacky destination. Constructs which generate exits from a @try or @catch 2509198092Srdivacky block use this mechanism to implement the proper semantics by chaining 2510198092Srdivacky jumps, as necessary. 2511193326Sed 2512198092Srdivacky This mechanism works like the one used for indirect goto: we 2513198092Srdivacky arbitrarily assign an ID to each destination and store the ID for the 2514198092Srdivacky destination in a variable prior to entering the finally block. At the 2515198092Srdivacky end of the finally block we simply create a switch to the proper 2516198092Srdivacky destination. 2517198092Srdivacky 2518198092Srdivacky Code gen for @synchronized(expr) stmt; 2519198092Srdivacky Effectively generating code for: 2520198092Srdivacky objc_sync_enter(expr); 2521198092Srdivacky @try stmt @finally { objc_sync_exit(expr); } 2522193326Sed*/ 2523193326Sed 2524193326Sedvoid CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 2525193326Sed const Stmt &S) { 2526193326Sed bool isTry = isa<ObjCAtTryStmt>(S); 2527193326Sed // Create various blocks we refer to for handling @finally. 2528193326Sed llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally"); 2529193326Sed llvm::BasicBlock *FinallyExit = CGF.createBasicBlock("finally.exit"); 2530193326Sed llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit"); 2531193326Sed llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); 2532193326Sed llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); 2533198092Srdivacky 2534193326Sed // For @synchronized, call objc_sync_enter(sync.expr). The 2535193326Sed // evaluation of the expression must occur before we enter the 2536193326Sed // @synchronized. We can safely avoid a temp here because jumps into 2537193326Sed // @synchronized are illegal & this will dominate uses. 2538193326Sed llvm::Value *SyncArg = 0; 2539193326Sed if (!isTry) { 2540198092Srdivacky SyncArg = 2541193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 2542193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); 2543193326Sed CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg); 2544193326Sed } 2545193326Sed 2546193326Sed // Push an EH context entry, used for handling rethrows and jumps 2547193326Sed // through finally. 2548193326Sed CGF.PushCleanupBlock(FinallyBlock); 2549193326Sed 2550200583Srdivacky if (CGF.ObjCEHValueStack.empty()) 2551200583Srdivacky CGF.ObjCEHValueStack.push_back(0); 2552200583Srdivacky // If This is a nested @try, caught exception is that of enclosing @try. 2553200583Srdivacky else 2554200583Srdivacky CGF.ObjCEHValueStack.push_back(CGF.ObjCEHValueStack.back()); 2555193326Sed // Allocate memory for the exception data and rethrow pointer. 2556193326Sed llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy, 2557193326Sed "exceptiondata.ptr"); 2558198092Srdivacky llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy, 2559193326Sed "_rethrow"); 2560198092Srdivacky llvm::Value *CallTryExitPtr = CGF.CreateTempAlloca( 2561198092Srdivacky llvm::Type::getInt1Ty(VMContext), 2562193326Sed "_call_try_exit"); 2563198092Srdivacky CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), 2564198092Srdivacky CallTryExitPtr); 2565198092Srdivacky 2566193326Sed // Enter a new try block and call setjmp. 2567193326Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData); 2568198092Srdivacky llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0, 2569193326Sed "jmpbufarray"); 2570193326Sed JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp"); 2571193326Sed llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), 2572193326Sed JmpBufPtr, "result"); 2573193326Sed 2574193326Sed llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); 2575193326Sed llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); 2576198092Srdivacky CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"), 2577193326Sed TryHandler, TryBlock); 2578193326Sed 2579193326Sed // Emit the @try block. 2580193326Sed CGF.EmitBlock(TryBlock); 2581198092Srdivacky CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() 2582198092Srdivacky : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); 2583193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 2584198092Srdivacky 2585193326Sed // Emit the "exception in @try" block. 2586193326Sed CGF.EmitBlock(TryHandler); 2587193326Sed 2588193326Sed // Retrieve the exception object. We may emit multiple blocks but 2589193326Sed // nothing can cross this so the value is already in SSA form. 2590193326Sed llvm::Value *Caught = 2591193326Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(), 2592193326Sed ExceptionData, "caught"); 2593193326Sed CGF.ObjCEHValueStack.back() = Caught; 2594198092Srdivacky if (!isTry) { 2595193326Sed CGF.Builder.CreateStore(Caught, RethrowPtr); 2596198092Srdivacky CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), 2597198092Srdivacky CallTryExitPtr); 2598193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 2599198092Srdivacky } else if (const ObjCAtCatchStmt* CatchStmt = 2600198092Srdivacky cast<ObjCAtTryStmt>(S).getCatchStmts()) { 2601193326Sed // Enter a new exception try block (in case a @catch block throws 2602193326Sed // an exception). 2603193326Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData); 2604198092Srdivacky 2605193326Sed llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), 2606193326Sed JmpBufPtr, "result"); 2607193326Sed llvm::Value *Threw = CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"); 2608193326Sed 2609193326Sed llvm::BasicBlock *CatchBlock = CGF.createBasicBlock("catch"); 2610193326Sed llvm::BasicBlock *CatchHandler = CGF.createBasicBlock("catch.handler"); 2611193326Sed CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock); 2612198092Srdivacky 2613193326Sed CGF.EmitBlock(CatchBlock); 2614198092Srdivacky 2615193326Sed // Handle catch list. As a special case we check if everything is 2616193326Sed // matched and avoid generating code for falling off the end if 2617193326Sed // so. 2618193326Sed bool AllMatched = false; 2619193326Sed for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) { 2620193326Sed llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch"); 2621193326Sed 2622193326Sed const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl(); 2623198092Srdivacky const ObjCObjectPointerType *OPT = 0; 2624193326Sed 2625193326Sed // catch(...) always matches. 2626193326Sed if (!CatchParam) { 2627193326Sed AllMatched = true; 2628193326Sed } else { 2629198092Srdivacky OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>(); 2630198092Srdivacky 2631198092Srdivacky // catch(id e) always matches. 2632193326Sed // FIXME: For the time being we also match id<X>; this should 2633193326Sed // be rejected by Sema instead. 2634198092Srdivacky if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())) 2635193326Sed AllMatched = true; 2636193326Sed } 2637198092Srdivacky 2638198092Srdivacky if (AllMatched) { 2639193326Sed if (CatchParam) { 2640193326Sed CGF.EmitLocalBlockVarDecl(*CatchParam); 2641193326Sed assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); 2642193326Sed CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam)); 2643193326Sed } 2644198092Srdivacky 2645193326Sed CGF.EmitStmt(CatchStmt->getCatchBody()); 2646193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 2647193326Sed break; 2648193326Sed } 2649198092Srdivacky 2650198092Srdivacky assert(OPT && "Unexpected non-object pointer type in @catch"); 2651198092Srdivacky QualType T = OPT->getPointeeType(); 2652198092Srdivacky const ObjCInterfaceType *ObjCType = T->getAs<ObjCInterfaceType>(); 2653193326Sed assert(ObjCType && "Catch parameter must have Objective-C type!"); 2654193326Sed 2655193326Sed // Check if the @catch block matches the exception object. 2656193326Sed llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl()); 2657198092Srdivacky 2658193326Sed llvm::Value *Match = 2659193326Sed CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(), 2660193326Sed Class, Caught, "match"); 2661198092Srdivacky 2662193326Sed llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("matched"); 2663198092Srdivacky 2664198092Srdivacky CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"), 2665193326Sed MatchedBlock, NextCatchBlock); 2666198092Srdivacky 2667193326Sed // Emit the @catch block. 2668193326Sed CGF.EmitBlock(MatchedBlock); 2669193326Sed CGF.EmitLocalBlockVarDecl(*CatchParam); 2670193326Sed assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); 2671193326Sed 2672198092Srdivacky llvm::Value *Tmp = 2673198092Srdivacky CGF.Builder.CreateBitCast(Caught, 2674198092Srdivacky CGF.ConvertType(CatchParam->getType()), 2675193326Sed "tmp"); 2676193326Sed CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam)); 2677198092Srdivacky 2678193326Sed CGF.EmitStmt(CatchStmt->getCatchBody()); 2679193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 2680198092Srdivacky 2681193326Sed CGF.EmitBlock(NextCatchBlock); 2682193326Sed } 2683193326Sed 2684193326Sed if (!AllMatched) { 2685193326Sed // None of the handlers caught the exception, so store it to be 2686193326Sed // rethrown at the end of the @finally block. 2687193326Sed CGF.Builder.CreateStore(Caught, RethrowPtr); 2688193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 2689193326Sed } 2690198092Srdivacky 2691193326Sed // Emit the exception handler for the @catch blocks. 2692198092Srdivacky CGF.EmitBlock(CatchHandler); 2693193326Sed CGF.Builder.CreateStore( 2694198092Srdivacky CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(), 2695198092Srdivacky ExceptionData), 2696198092Srdivacky RethrowPtr); 2697198092Srdivacky CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), 2698198092Srdivacky CallTryExitPtr); 2699193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 2700193326Sed } else { 2701193326Sed CGF.Builder.CreateStore(Caught, RethrowPtr); 2702198092Srdivacky CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), 2703198092Srdivacky CallTryExitPtr); 2704193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 2705193326Sed } 2706198092Srdivacky 2707193326Sed // Pop the exception-handling stack entry. It is important to do 2708193326Sed // this now, because the code in the @finally block is not in this 2709193326Sed // context. 2710193326Sed CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); 2711193326Sed 2712193326Sed CGF.ObjCEHValueStack.pop_back(); 2713198092Srdivacky 2714193326Sed // Emit the @finally block. 2715193326Sed CGF.EmitBlock(FinallyBlock); 2716193326Sed llvm::Value* CallTryExit = CGF.Builder.CreateLoad(CallTryExitPtr, "tmp"); 2717198092Srdivacky 2718193326Sed CGF.Builder.CreateCondBr(CallTryExit, FinallyExit, FinallyNoExit); 2719198092Srdivacky 2720193326Sed CGF.EmitBlock(FinallyExit); 2721193326Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData); 2722193326Sed 2723193326Sed CGF.EmitBlock(FinallyNoExit); 2724193326Sed if (isTry) { 2725198092Srdivacky if (const ObjCAtFinallyStmt* FinallyStmt = 2726198092Srdivacky cast<ObjCAtTryStmt>(S).getFinallyStmt()) 2727193326Sed CGF.EmitStmt(FinallyStmt->getFinallyBody()); 2728193326Sed } else { 2729193326Sed // Emit objc_sync_exit(expr); as finally's sole statement for 2730193326Sed // @synchronized. 2731193326Sed CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg); 2732193326Sed } 2733193326Sed 2734193326Sed // Emit the switch block 2735193326Sed if (Info.SwitchBlock) 2736193326Sed CGF.EmitBlock(Info.SwitchBlock); 2737193326Sed if (Info.EndBlock) 2738193326Sed CGF.EmitBlock(Info.EndBlock); 2739198092Srdivacky 2740193326Sed CGF.EmitBlock(FinallyRethrow); 2741198092Srdivacky CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), 2742193326Sed CGF.Builder.CreateLoad(RethrowPtr)); 2743193326Sed CGF.Builder.CreateUnreachable(); 2744198092Srdivacky 2745193326Sed CGF.EmitBlock(FinallyEnd); 2746193326Sed} 2747193326Sed 2748193326Sedvoid CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 2749193326Sed const ObjCAtThrowStmt &S) { 2750193326Sed llvm::Value *ExceptionAsObject; 2751198092Srdivacky 2752193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 2753193326Sed llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr); 2754198092Srdivacky ExceptionAsObject = 2755193326Sed CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp"); 2756193326Sed } else { 2757198092Srdivacky assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && 2758193326Sed "Unexpected rethrow outside @catch block."); 2759193326Sed ExceptionAsObject = CGF.ObjCEHValueStack.back(); 2760193326Sed } 2761198092Srdivacky 2762193326Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject); 2763193326Sed CGF.Builder.CreateUnreachable(); 2764193326Sed 2765193326Sed // Clear the insertion point to indicate we are in unreachable code. 2766193326Sed CGF.Builder.ClearInsertionPoint(); 2767193326Sed} 2768193326Sed 2769193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak 2770193326Sed/// object: objc_read_weak (id *src) 2771193326Sed/// 2772193326Sedllvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 2773198092Srdivacky llvm::Value *AddrWeakObj) { 2774193326Sed const llvm::Type* DestTy = 2775198092Srdivacky cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); 2776198092Srdivacky AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, 2777198092Srdivacky ObjCTypes.PtrObjectPtrTy); 2778193326Sed llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(), 2779193326Sed AddrWeakObj, "weakread"); 2780193326Sed read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); 2781193326Sed return read_weak; 2782193326Sed} 2783193326Sed 2784193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. 2785193326Sed/// objc_assign_weak (id src, id *dst) 2786193326Sed/// 2787193326Sedvoid CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 2788198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2789193326Sed const llvm::Type * SrcTy = src->getType(); 2790193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 2791193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 2792193326Sed assert(Size <= 8 && "does not support size > 8"); 2793193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 2794198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 2795193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 2796193326Sed } 2797193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 2798193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 2799193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(), 2800193326Sed src, dst, "weakassign"); 2801193326Sed return; 2802193326Sed} 2803193326Sed 2804193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. 2805193326Sed/// objc_assign_global (id src, id *dst) 2806193326Sed/// 2807193326Sedvoid CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 2808198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2809193326Sed const llvm::Type * SrcTy = src->getType(); 2810193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 2811193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 2812193326Sed assert(Size <= 8 && "does not support size > 8"); 2813193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 2814198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 2815193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 2816193326Sed } 2817193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 2818193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 2819193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(), 2820193326Sed src, dst, "globalassign"); 2821193326Sed return; 2822193326Sed} 2823193326Sed 2824193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. 2825198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset) 2826193326Sed/// 2827193326Sedvoid CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 2828198092Srdivacky llvm::Value *src, llvm::Value *dst, 2829198092Srdivacky llvm::Value *ivarOffset) { 2830198092Srdivacky assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL"); 2831193326Sed const llvm::Type * SrcTy = src->getType(); 2832193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 2833193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 2834193326Sed assert(Size <= 8 && "does not support size > 8"); 2835193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 2836198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 2837193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 2838193326Sed } 2839193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 2840193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 2841198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(), 2842198092Srdivacky src, dst, ivarOffset); 2843193326Sed return; 2844193326Sed} 2845193326Sed 2846193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. 2847193326Sed/// objc_assign_strongCast (id src, id *dst) 2848193326Sed/// 2849193326Sedvoid CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 2850198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2851193326Sed const llvm::Type * SrcTy = src->getType(); 2852193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 2853193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 2854193326Sed assert(Size <= 8 && "does not support size > 8"); 2855193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 2856198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 2857193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 2858193326Sed } 2859193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 2860193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 2861193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(), 2862193326Sed src, dst, "weakassign"); 2863193326Sed return; 2864193326Sed} 2865193326Sed 2866198092Srdivackyvoid CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 2867198092Srdivacky llvm::Value *DestPtr, 2868198092Srdivacky llvm::Value *SrcPtr, 2869198092Srdivacky QualType Ty) { 2870198092Srdivacky // Get size info for this aggregate. 2871198092Srdivacky std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty); 2872198092Srdivacky unsigned long size = TypeInfo.first/8; 2873198092Srdivacky SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); 2874198092Srdivacky DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); 2875198092Srdivacky llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size); 2876198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(), 2877198092Srdivacky DestPtr, SrcPtr, N); 2878198092Srdivacky return; 2879198092Srdivacky} 2880198092Srdivacky 2881193326Sed/// EmitObjCValueForIvar - Code Gen for ivar reference. 2882193326Sed/// 2883193326SedLValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 2884193326Sed QualType ObjectTy, 2885193326Sed llvm::Value *BaseValue, 2886193326Sed const ObjCIvarDecl *Ivar, 2887193326Sed unsigned CVRQualifiers) { 2888198092Srdivacky const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); 2889193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 2890193326Sed EmitIvarOffset(CGF, ID, Ivar)); 2891193326Sed} 2892193326Sed 2893193326Sedllvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 2894193326Sed const ObjCInterfaceDecl *Interface, 2895193326Sed const ObjCIvarDecl *Ivar) { 2896193326Sed uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar); 2897193326Sed return llvm::ConstantInt::get( 2898198092Srdivacky CGM.getTypes().ConvertType(CGM.getContext().LongTy), 2899198092Srdivacky Offset); 2900193326Sed} 2901193326Sed 2902193326Sed/* *** Private Interface *** */ 2903193326Sed 2904193326Sed/// EmitImageInfo - Emit the image info marker used to encode some module 2905193326Sed/// level information. 2906193326Sed/// 2907193326Sed/// See: <rdr://4810609&4810587&4810587> 2908193326Sed/// struct IMAGE_INFO { 2909193326Sed/// unsigned version; 2910193326Sed/// unsigned flags; 2911193326Sed/// }; 2912193326Sedenum ImageInfoFlags { 2913193326Sed eImageInfo_FixAndContinue = (1 << 0), // FIXME: Not sure what 2914193326Sed // this implies. 2915198092Srdivacky eImageInfo_GarbageCollected = (1 << 1), 2916198092Srdivacky eImageInfo_GCOnly = (1 << 2), 2917193326Sed eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set. 2918193326Sed 2919193326Sed // A flag indicating that the module has no instances of an 2920193326Sed // @synthesize of a superclass variable. <rdar://problem/6803242> 2921193326Sed eImageInfo_CorrectedSynthesize = (1 << 4) 2922193326Sed}; 2923193326Sed 2924193326Sedvoid CGObjCMac::EmitImageInfo() { 2925193326Sed unsigned version = 0; // Version is unused? 2926193326Sed unsigned flags = 0; 2927193326Sed 2928193326Sed // FIXME: Fix and continue? 2929193326Sed if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) 2930193326Sed flags |= eImageInfo_GarbageCollected; 2931193326Sed if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) 2932193326Sed flags |= eImageInfo_GCOnly; 2933198092Srdivacky 2934193326Sed // We never allow @synthesize of a superclass property. 2935193326Sed flags |= eImageInfo_CorrectedSynthesize; 2936193326Sed 2937193326Sed // Emitted as int[2]; 2938193326Sed llvm::Constant *values[2] = { 2939198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), version), 2940198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), flags) 2941193326Sed }; 2942198092Srdivacky llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext), 2); 2943193326Sed 2944193326Sed const char *Section; 2945193326Sed if (ObjCABI == 1) 2946193326Sed Section = "__OBJC, __image_info,regular"; 2947193326Sed else 2948193326Sed Section = "__DATA, __objc_imageinfo, regular, no_dead_strip"; 2949198092Srdivacky llvm::GlobalVariable *GV = 2950193326Sed CreateMetadataVar("\01L_OBJC_IMAGE_INFO", 2951193326Sed llvm::ConstantArray::get(AT, values, 2), 2952193326Sed Section, 2953193326Sed 0, 2954193326Sed true); 2955193326Sed GV->setConstant(true); 2956193326Sed} 2957193326Sed 2958193326Sed 2959193326Sed// struct objc_module { 2960193326Sed// unsigned long version; 2961193326Sed// unsigned long size; 2962193326Sed// const char *name; 2963193326Sed// Symtab symtab; 2964193326Sed// }; 2965193326Sed 2966193326Sed// FIXME: Get from somewhere 2967193326Sedstatic const int ModuleVersion = 7; 2968193326Sed 2969193326Sedvoid CGObjCMac::EmitModuleInfo() { 2970193326Sed uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy); 2971198092Srdivacky 2972193326Sed std::vector<llvm::Constant*> Values(4); 2973193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion); 2974193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 2975193326Sed // This used to be the filename, now it is unused. <rdr://4327263> 2976193326Sed Values[2] = GetClassName(&CGM.getContext().Idents.get("")); 2977193326Sed Values[3] = EmitModuleSymbols(); 2978198092Srdivacky CreateMetadataVar("\01L_OBJC_MODULES", 2979193326Sed llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values), 2980193326Sed "__OBJC,__module_info,regular,no_dead_strip", 2981193326Sed 4, true); 2982193326Sed} 2983193326Sed 2984193326Sedllvm::Constant *CGObjCMac::EmitModuleSymbols() { 2985193326Sed unsigned NumClasses = DefinedClasses.size(); 2986193326Sed unsigned NumCategories = DefinedCategories.size(); 2987193326Sed 2988193326Sed // Return null if no symbols were defined. 2989193326Sed if (!NumClasses && !NumCategories) 2990193326Sed return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy); 2991193326Sed 2992193326Sed std::vector<llvm::Constant*> Values(5); 2993193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 2994193326Sed Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy); 2995193326Sed Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses); 2996193326Sed Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories); 2997193326Sed 2998193326Sed // The runtime expects exactly the list of defined classes followed 2999193326Sed // by the list of defined categories, in a single array. 3000193326Sed std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories); 3001193326Sed for (unsigned i=0; i<NumClasses; i++) 3002193326Sed Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i], 3003193326Sed ObjCTypes.Int8PtrTy); 3004193326Sed for (unsigned i=0; i<NumCategories; i++) 3005198092Srdivacky Symbols[NumClasses + i] = 3006193326Sed llvm::ConstantExpr::getBitCast(DefinedCategories[i], 3007193326Sed ObjCTypes.Int8PtrTy); 3008193326Sed 3009198092Srdivacky Values[4] = 3010193326Sed llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 3011193326Sed NumClasses + NumCategories), 3012193326Sed Symbols); 3013193326Sed 3014198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 3015193326Sed 3016193326Sed llvm::GlobalVariable *GV = 3017193326Sed CreateMetadataVar("\01L_OBJC_SYMBOLS", Init, 3018193326Sed "__OBJC,__symbols,regular,no_dead_strip", 3019193326Sed 4, true); 3020193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy); 3021193326Sed} 3022193326Sed 3023198092Srdivackyllvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder, 3024193326Sed const ObjCInterfaceDecl *ID) { 3025193326Sed LazySymbols.insert(ID->getIdentifier()); 3026193326Sed 3027193326Sed llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()]; 3028198092Srdivacky 3029193326Sed if (!Entry) { 3030198092Srdivacky llvm::Constant *Casted = 3031193326Sed llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()), 3032193326Sed ObjCTypes.ClassPtrTy); 3033198092Srdivacky Entry = 3034193326Sed CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted, 3035193326Sed "__OBJC,__cls_refs,literal_pointers,no_dead_strip", 3036193326Sed 4, true); 3037193326Sed } 3038193326Sed 3039199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 3040193326Sed} 3041193326Sed 3042193326Sedllvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) { 3043193326Sed llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; 3044198092Srdivacky 3045193326Sed if (!Entry) { 3046198092Srdivacky llvm::Constant *Casted = 3047193326Sed llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), 3048193326Sed ObjCTypes.SelectorPtrTy); 3049198092Srdivacky Entry = 3050193326Sed CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted, 3051193326Sed "__OBJC,__message_refs,literal_pointers,no_dead_strip", 3052193326Sed 4, true); 3053193326Sed } 3054193326Sed 3055199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 3056193326Sed} 3057193326Sed 3058193326Sedllvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) { 3059193326Sed llvm::GlobalVariable *&Entry = ClassNames[Ident]; 3060193326Sed 3061193326Sed if (!Entry) 3062198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", 3063198398Srdivacky llvm::ConstantArray::get(VMContext, 3064198398Srdivacky Ident->getNameStart()), 3065193326Sed "__TEXT,__cstring,cstring_literals", 3066193326Sed 1, true); 3067193326Sed 3068198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3069193326Sed} 3070193326Sed 3071193326Sed/// GetIvarLayoutName - Returns a unique constant for the given 3072193326Sed/// ivar layout bitmap. 3073193326Sedllvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, 3074198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 3075193326Sed return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 3076193326Sed} 3077193326Sed 3078198092Srdivackystatic Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) { 3079193326Sed if (FQT.isObjCGCStrong()) 3080198092Srdivacky return Qualifiers::Strong; 3081193326Sed 3082193326Sed if (FQT.isObjCGCWeak()) 3083198092Srdivacky return Qualifiers::Weak; 3084193326Sed 3085198092Srdivacky if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) 3086198092Srdivacky return Qualifiers::Strong; 3087193326Sed 3088198092Srdivacky if (const PointerType *PT = FQT->getAs<PointerType>()) 3089193326Sed return GetGCAttrTypeForType(Ctx, PT->getPointeeType()); 3090193326Sed 3091198092Srdivacky return Qualifiers::GCNone; 3092193326Sed} 3093193326Sed 3094193326Sedvoid CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT, 3095198092Srdivacky unsigned int BytePos, 3096193326Sed bool ForStrongLayout, 3097193326Sed bool &HasUnion) { 3098193326Sed const RecordDecl *RD = RT->getDecl(); 3099193326Sed // FIXME - Use iterator. 3100195341Sed llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end()); 3101193326Sed const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); 3102198092Srdivacky const llvm::StructLayout *RecLayout = 3103193326Sed CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty)); 3104198092Srdivacky 3105193326Sed BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos, 3106193326Sed ForStrongLayout, HasUnion); 3107193326Sed} 3108193326Sed 3109193326Sedvoid CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, 3110198092Srdivacky const llvm::StructLayout *Layout, 3111198092Srdivacky const RecordDecl *RD, 3112193326Sed const llvm::SmallVectorImpl<FieldDecl*> &RecFields, 3113198092Srdivacky unsigned int BytePos, bool ForStrongLayout, 3114198092Srdivacky bool &HasUnion) { 3115193326Sed bool IsUnion = (RD && RD->isUnion()); 3116193326Sed uint64_t MaxUnionIvarSize = 0; 3117193326Sed uint64_t MaxSkippedUnionIvarSize = 0; 3118193326Sed FieldDecl *MaxField = 0; 3119193326Sed FieldDecl *MaxSkippedField = 0; 3120193326Sed FieldDecl *LastFieldBitfield = 0; 3121193326Sed uint64_t MaxFieldOffset = 0; 3122193326Sed uint64_t MaxSkippedFieldOffset = 0; 3123193326Sed uint64_t LastBitfieldOffset = 0; 3124198092Srdivacky 3125193326Sed if (RecFields.empty()) 3126193326Sed return; 3127193326Sed unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0); 3128193326Sed unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth(); 3129193326Sed 3130193326Sed for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { 3131193326Sed FieldDecl *Field = RecFields[i]; 3132193326Sed uint64_t FieldOffset; 3133198092Srdivacky if (RD) { 3134198092Srdivacky if (Field->isBitField()) { 3135198092Srdivacky CodeGenTypes::BitFieldInfo Info = CGM.getTypes().getBitFieldInfo(Field); 3136198092Srdivacky 3137198092Srdivacky const llvm::Type *Ty = 3138198092Srdivacky CGM.getTypes().ConvertTypeForMemRecursive(Field->getType()); 3139198092Srdivacky uint64_t TypeSize = 3140198092Srdivacky CGM.getTypes().getTargetData().getTypeAllocSize(Ty); 3141198092Srdivacky FieldOffset = Info.FieldNo * TypeSize; 3142198092Srdivacky } else 3143198092Srdivacky FieldOffset = 3144198092Srdivacky Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field)); 3145198092Srdivacky } else 3146193326Sed FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)); 3147193326Sed 3148193326Sed // Skip over unnamed or bitfields 3149193326Sed if (!Field->getIdentifier() || Field->isBitField()) { 3150193326Sed LastFieldBitfield = Field; 3151193326Sed LastBitfieldOffset = FieldOffset; 3152193326Sed continue; 3153193326Sed } 3154193326Sed 3155193326Sed LastFieldBitfield = 0; 3156193326Sed QualType FQT = Field->getType(); 3157193326Sed if (FQT->isRecordType() || FQT->isUnionType()) { 3158193326Sed if (FQT->isUnionType()) 3159193326Sed HasUnion = true; 3160193326Sed 3161198092Srdivacky BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(), 3162193326Sed BytePos + FieldOffset, 3163193326Sed ForStrongLayout, HasUnion); 3164193326Sed continue; 3165193326Sed } 3166198092Srdivacky 3167193326Sed if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 3168198092Srdivacky const ConstantArrayType *CArray = 3169193326Sed dyn_cast_or_null<ConstantArrayType>(Array); 3170193326Sed uint64_t ElCount = CArray->getSize().getZExtValue(); 3171193326Sed assert(CArray && "only array with known element size is supported"); 3172193326Sed FQT = CArray->getElementType(); 3173193326Sed while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 3174193326Sed const ConstantArrayType *CArray = 3175193326Sed dyn_cast_or_null<ConstantArrayType>(Array); 3176193326Sed ElCount *= CArray->getSize().getZExtValue(); 3177193326Sed FQT = CArray->getElementType(); 3178193326Sed } 3179198092Srdivacky 3180198092Srdivacky assert(!FQT->isUnionType() && 3181193326Sed "layout for array of unions not supported"); 3182193326Sed if (FQT->isRecordType()) { 3183193326Sed int OldIndex = IvarsInfo.size() - 1; 3184193326Sed int OldSkIndex = SkipIvars.size() -1; 3185198092Srdivacky 3186198092Srdivacky const RecordType *RT = FQT->getAs<RecordType>(); 3187193326Sed BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset, 3188193326Sed ForStrongLayout, HasUnion); 3189198092Srdivacky 3190193326Sed // Replicate layout information for each array element. Note that 3191193326Sed // one element is already done. 3192193326Sed uint64_t ElIx = 1; 3193198092Srdivacky for (int FirstIndex = IvarsInfo.size() - 1, 3194198092Srdivacky FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) { 3195193326Sed uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits; 3196193326Sed for (int i = OldIndex+1; i <= FirstIndex; ++i) 3197193326Sed IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx, 3198193326Sed IvarsInfo[i].ivar_size)); 3199193326Sed for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i) 3200193326Sed SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx, 3201193326Sed SkipIvars[i].ivar_size)); 3202193326Sed } 3203193326Sed continue; 3204193326Sed } 3205193326Sed } 3206193326Sed // At this point, we are done with Record/Union and array there of. 3207193326Sed // For other arrays we are down to its element type. 3208198092Srdivacky Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT); 3209193326Sed 3210193326Sed unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType()); 3211198092Srdivacky if ((ForStrongLayout && GCAttr == Qualifiers::Strong) 3212198092Srdivacky || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) { 3213193326Sed if (IsUnion) { 3214193326Sed uint64_t UnionIvarSize = FieldSize / WordSizeInBits; 3215193326Sed if (UnionIvarSize > MaxUnionIvarSize) { 3216193326Sed MaxUnionIvarSize = UnionIvarSize; 3217193326Sed MaxField = Field; 3218193326Sed MaxFieldOffset = FieldOffset; 3219193326Sed } 3220193326Sed } else { 3221193326Sed IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset, 3222193326Sed FieldSize / WordSizeInBits)); 3223193326Sed } 3224198092Srdivacky } else if ((ForStrongLayout && 3225198092Srdivacky (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)) 3226198092Srdivacky || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) { 3227193326Sed if (IsUnion) { 3228193326Sed // FIXME: Why the asymmetry? We divide by word size in bits on other 3229193326Sed // side. 3230193326Sed uint64_t UnionIvarSize = FieldSize; 3231193326Sed if (UnionIvarSize > MaxSkippedUnionIvarSize) { 3232193326Sed MaxSkippedUnionIvarSize = UnionIvarSize; 3233193326Sed MaxSkippedField = Field; 3234193326Sed MaxSkippedFieldOffset = FieldOffset; 3235193326Sed } 3236193326Sed } else { 3237193326Sed // FIXME: Why the asymmetry, we divide by byte size in bits here? 3238193326Sed SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset, 3239193326Sed FieldSize / ByteSizeInBits)); 3240193326Sed } 3241193326Sed } 3242193326Sed } 3243193326Sed 3244193326Sed if (LastFieldBitfield) { 3245193326Sed // Last field was a bitfield. Must update skip info. 3246193326Sed Expr *BitWidth = LastFieldBitfield->getBitWidth(); 3247193326Sed uint64_t BitFieldSize = 3248193326Sed BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); 3249193326Sed GC_IVAR skivar; 3250193326Sed skivar.ivar_bytepos = BytePos + LastBitfieldOffset; 3251198092Srdivacky skivar.ivar_size = (BitFieldSize / ByteSizeInBits) 3252198092Srdivacky + ((BitFieldSize % ByteSizeInBits) != 0); 3253198092Srdivacky SkipIvars.push_back(skivar); 3254193326Sed } 3255198092Srdivacky 3256193326Sed if (MaxField) 3257198092Srdivacky IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset, 3258193326Sed MaxUnionIvarSize)); 3259193326Sed if (MaxSkippedField) 3260193326Sed SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset, 3261193326Sed MaxSkippedUnionIvarSize)); 3262193326Sed} 3263193326Sed 3264193326Sed/// BuildIvarLayout - Builds ivar layout bitmap for the class 3265193326Sed/// implementation for the __strong or __weak case. 3266198092Srdivacky/// The layout map displays which words in ivar list must be skipped 3267198092Srdivacky/// and which must be scanned by GC (see below). String is built of bytes. 3268198092Srdivacky/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count 3269193326Sed/// of words to skip and right nibble is count of words to scan. So, each 3270198092Srdivacky/// nibble represents up to 15 workds to skip or scan. Skipping the rest is 3271193326Sed/// represented by a 0x00 byte which also ends the string. 3272193326Sed/// 1. when ForStrongLayout is true, following ivars are scanned: 3273193326Sed/// - id, Class 3274193326Sed/// - object * 3275193326Sed/// - __strong anything 3276198092Srdivacky/// 3277193326Sed/// 2. When ForStrongLayout is false, following ivars are scanned: 3278193326Sed/// - __weak anything 3279193326Sed/// 3280193326Sedllvm::Constant *CGObjCCommonMac::BuildIvarLayout( 3281198092Srdivacky const ObjCImplementationDecl *OMD, 3282198092Srdivacky bool ForStrongLayout) { 3283193326Sed bool hasUnion = false; 3284198092Srdivacky 3285193326Sed unsigned int WordsToScan, WordsToSkip; 3286198092Srdivacky const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext); 3287193326Sed if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) 3288193326Sed return llvm::Constant::getNullValue(PtrTy); 3289198092Srdivacky 3290193326Sed llvm::SmallVector<FieldDecl*, 32> RecFields; 3291193326Sed const ObjCInterfaceDecl *OI = OMD->getClassInterface(); 3292193326Sed CGM.getContext().CollectObjCIvars(OI, RecFields); 3293198092Srdivacky 3294193326Sed // Add this implementations synthesized ivars. 3295193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; 3296193326Sed CGM.getContext().CollectSynthesizedIvars(OI, Ivars); 3297193326Sed for (unsigned k = 0, e = Ivars.size(); k != e; ++k) 3298193326Sed RecFields.push_back(cast<FieldDecl>(Ivars[k])); 3299198092Srdivacky 3300193326Sed if (RecFields.empty()) 3301193326Sed return llvm::Constant::getNullValue(PtrTy); 3302198092Srdivacky 3303198092Srdivacky SkipIvars.clear(); 3304193326Sed IvarsInfo.clear(); 3305198092Srdivacky 3306193326Sed BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion); 3307193326Sed if (IvarsInfo.empty()) 3308193326Sed return llvm::Constant::getNullValue(PtrTy); 3309198092Srdivacky 3310193326Sed // Sort on byte position in case we encounterred a union nested in 3311193326Sed // the ivar list. 3312193326Sed if (hasUnion && !IvarsInfo.empty()) 3313193326Sed std::sort(IvarsInfo.begin(), IvarsInfo.end()); 3314193326Sed if (hasUnion && !SkipIvars.empty()) 3315193326Sed std::sort(SkipIvars.begin(), SkipIvars.end()); 3316198092Srdivacky 3317193326Sed // Build the string of skip/scan nibbles 3318193326Sed llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars; 3319198092Srdivacky unsigned int WordSize = 3320193326Sed CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy); 3321193326Sed if (IvarsInfo[0].ivar_bytepos == 0) { 3322193326Sed WordsToSkip = 0; 3323193326Sed WordsToScan = IvarsInfo[0].ivar_size; 3324193326Sed } else { 3325193326Sed WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize; 3326193326Sed WordsToScan = IvarsInfo[0].ivar_size; 3327193326Sed } 3328193326Sed for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) { 3329198092Srdivacky unsigned int TailPrevGCObjC = 3330193326Sed IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize; 3331193326Sed if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) { 3332193326Sed // consecutive 'scanned' object pointers. 3333193326Sed WordsToScan += IvarsInfo[i].ivar_size; 3334193326Sed } else { 3335193326Sed // Skip over 'gc'able object pointer which lay over each other. 3336193326Sed if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos) 3337193326Sed continue; 3338193326Sed // Must skip over 1 or more words. We save current skip/scan values 3339193326Sed // and start a new pair. 3340193326Sed SKIP_SCAN SkScan; 3341193326Sed SkScan.skip = WordsToSkip; 3342193326Sed SkScan.scan = WordsToScan; 3343193326Sed SkipScanIvars.push_back(SkScan); 3344198092Srdivacky 3345193326Sed // Skip the hole. 3346193326Sed SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize; 3347193326Sed SkScan.scan = 0; 3348193326Sed SkipScanIvars.push_back(SkScan); 3349193326Sed WordsToSkip = 0; 3350193326Sed WordsToScan = IvarsInfo[i].ivar_size; 3351193326Sed } 3352193326Sed } 3353193326Sed if (WordsToScan > 0) { 3354193326Sed SKIP_SCAN SkScan; 3355193326Sed SkScan.skip = WordsToSkip; 3356193326Sed SkScan.scan = WordsToScan; 3357193326Sed SkipScanIvars.push_back(SkScan); 3358193326Sed } 3359198092Srdivacky 3360193326Sed if (!SkipIvars.empty()) { 3361193326Sed unsigned int LastIndex = SkipIvars.size()-1; 3362198092Srdivacky int LastByteSkipped = 3363198092Srdivacky SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size; 3364193326Sed LastIndex = IvarsInfo.size()-1; 3365198092Srdivacky int LastByteScanned = 3366198092Srdivacky IvarsInfo[LastIndex].ivar_bytepos + 3367198092Srdivacky IvarsInfo[LastIndex].ivar_size * WordSize; 3368193326Sed // Compute number of bytes to skip at the tail end of the last ivar scanned. 3369201361Srdivacky if (LastByteSkipped > LastByteScanned) { 3370193326Sed unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize; 3371193326Sed SKIP_SCAN SkScan; 3372193326Sed SkScan.skip = TotalWords - (LastByteScanned/WordSize); 3373193326Sed SkScan.scan = 0; 3374193326Sed SkipScanIvars.push_back(SkScan); 3375193326Sed } 3376193326Sed } 3377193326Sed // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced 3378193326Sed // as 0xMN. 3379193326Sed int SkipScan = SkipScanIvars.size()-1; 3380193326Sed for (int i = 0; i <= SkipScan; i++) { 3381193326Sed if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0 3382193326Sed && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) { 3383193326Sed // 0xM0 followed by 0x0N detected. 3384193326Sed SkipScanIvars[i].scan = SkipScanIvars[i+1].scan; 3385193326Sed for (int j = i+1; j < SkipScan; j++) 3386193326Sed SkipScanIvars[j] = SkipScanIvars[j+1]; 3387193326Sed --SkipScan; 3388193326Sed } 3389193326Sed } 3390198092Srdivacky 3391193326Sed // Generate the string. 3392193326Sed std::string BitMap; 3393193326Sed for (int i = 0; i <= SkipScan; i++) { 3394193326Sed unsigned char byte; 3395193326Sed unsigned int skip_small = SkipScanIvars[i].skip % 0xf; 3396193326Sed unsigned int scan_small = SkipScanIvars[i].scan % 0xf; 3397193326Sed unsigned int skip_big = SkipScanIvars[i].skip / 0xf; 3398193326Sed unsigned int scan_big = SkipScanIvars[i].scan / 0xf; 3399193326Sed 3400193326Sed // first skip big. 3401193326Sed for (unsigned int ix = 0; ix < skip_big; ix++) 3402193326Sed BitMap += (unsigned char)(0xf0); 3403198092Srdivacky 3404193326Sed // next (skip small, scan) 3405193326Sed if (skip_small) { 3406193326Sed byte = skip_small << 4; 3407193326Sed if (scan_big > 0) { 3408193326Sed byte |= 0xf; 3409193326Sed --scan_big; 3410193326Sed } else if (scan_small) { 3411193326Sed byte |= scan_small; 3412193326Sed scan_small = 0; 3413193326Sed } 3414193326Sed BitMap += byte; 3415193326Sed } 3416193326Sed // next scan big 3417193326Sed for (unsigned int ix = 0; ix < scan_big; ix++) 3418193326Sed BitMap += (unsigned char)(0x0f); 3419193326Sed // last scan small 3420193326Sed if (scan_small) { 3421193326Sed byte = scan_small; 3422193326Sed BitMap += byte; 3423193326Sed } 3424193326Sed } 3425193326Sed // null terminate string. 3426193326Sed unsigned char zero = 0; 3427193326Sed BitMap += zero; 3428198092Srdivacky 3429193326Sed if (CGM.getLangOptions().ObjCGCBitmapPrint) { 3430198092Srdivacky printf("\n%s ivar layout for class '%s': ", 3431193326Sed ForStrongLayout ? "strong" : "weak", 3432193326Sed OMD->getClassInterface()->getNameAsCString()); 3433193326Sed const unsigned char *s = (unsigned char*)BitMap.c_str(); 3434193326Sed for (unsigned i = 0; i < BitMap.size(); i++) 3435193326Sed if (!(s[i] & 0xf0)) 3436193326Sed printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); 3437193326Sed else 3438193326Sed printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); 3439193326Sed printf("\n"); 3440193326Sed } 3441198092Srdivacky llvm::GlobalVariable * Entry = 3442198092Srdivacky CreateMetadataVar("\01L_OBJC_CLASS_NAME_", 3443198092Srdivacky llvm::ConstantArray::get(VMContext, BitMap.c_str()), 3444198092Srdivacky "__TEXT,__cstring,cstring_literals", 3445198092Srdivacky 1, true); 3446198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3447193326Sed} 3448193326Sed 3449193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) { 3450193326Sed llvm::GlobalVariable *&Entry = MethodVarNames[Sel]; 3451193326Sed 3452193326Sed // FIXME: Avoid std::string copying. 3453193326Sed if (!Entry) 3454198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_", 3455198092Srdivacky llvm::ConstantArray::get(VMContext, Sel.getAsString()), 3456193326Sed "__TEXT,__cstring,cstring_literals", 3457193326Sed 1, true); 3458193326Sed 3459198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3460193326Sed} 3461193326Sed 3462193326Sed// FIXME: Merge into a single cstring creation function. 3463193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) { 3464193326Sed return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID)); 3465193326Sed} 3466193326Sed 3467193326Sed// FIXME: Merge into a single cstring creation function. 3468193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) { 3469193326Sed return GetMethodVarName(&CGM.getContext().Idents.get(Name)); 3470193326Sed} 3471193326Sed 3472193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) { 3473193326Sed std::string TypeStr; 3474193326Sed CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field); 3475193326Sed 3476193326Sed llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; 3477193326Sed 3478193326Sed if (!Entry) 3479193326Sed Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", 3480198092Srdivacky llvm::ConstantArray::get(VMContext, TypeStr), 3481193326Sed "__TEXT,__cstring,cstring_literals", 3482193326Sed 1, true); 3483198092Srdivacky 3484198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3485193326Sed} 3486193326Sed 3487193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) { 3488193326Sed std::string TypeStr; 3489193326Sed CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D), 3490193326Sed TypeStr); 3491193326Sed 3492193326Sed llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; 3493193326Sed 3494193326Sed if (!Entry) 3495193326Sed Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", 3496198092Srdivacky llvm::ConstantArray::get(VMContext, TypeStr), 3497193326Sed "__TEXT,__cstring,cstring_literals", 3498193326Sed 1, true); 3499193326Sed 3500198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3501193326Sed} 3502193326Sed 3503193326Sed// FIXME: Merge into a single cstring creation function. 3504193326Sedllvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) { 3505193326Sed llvm::GlobalVariable *&Entry = PropertyNames[Ident]; 3506198092Srdivacky 3507193326Sed if (!Entry) 3508198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_", 3509198398Srdivacky llvm::ConstantArray::get(VMContext, 3510198398Srdivacky Ident->getNameStart()), 3511193326Sed "__TEXT,__cstring,cstring_literals", 3512193326Sed 1, true); 3513193326Sed 3514198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3515193326Sed} 3516193326Sed 3517193326Sed// FIXME: Merge into a single cstring creation function. 3518193326Sed// FIXME: This Decl should be more precise. 3519193326Sedllvm::Constant * 3520198092SrdivackyCGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD, 3521198092Srdivacky const Decl *Container) { 3522193326Sed std::string TypeStr; 3523193326Sed CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr); 3524193326Sed return GetPropertyName(&CGM.getContext().Idents.get(TypeStr)); 3525193326Sed} 3526193326Sed 3527198092Srdivackyvoid CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D, 3528193326Sed const ObjCContainerDecl *CD, 3529198398Srdivacky llvm::SmallVectorImpl<char> &Name) { 3530198398Srdivacky llvm::raw_svector_ostream OS(Name); 3531193326Sed assert (CD && "Missing container decl in GetNameForMethod"); 3532198398Srdivacky OS << '\01' << (D->isInstanceMethod() ? '-' : '+') 3533198398Srdivacky << '[' << CD->getName(); 3534198092Srdivacky if (const ObjCCategoryImplDecl *CID = 3535198398Srdivacky dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) 3536198398Srdivacky OS << '(' << CID->getNameAsString() << ')'; 3537198398Srdivacky OS << ' ' << D->getSelector().getAsString() << ']'; 3538193326Sed} 3539193326Sed 3540193326Sedvoid CGObjCMac::FinishModule() { 3541193326Sed EmitModuleInfo(); 3542193326Sed 3543193326Sed // Emit the dummy bodies for any protocols which were referenced but 3544193326Sed // never defined. 3545198092Srdivacky for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator 3546198092Srdivacky I = Protocols.begin(), e = Protocols.end(); I != e; ++I) { 3547198092Srdivacky if (I->second->hasInitializer()) 3548193326Sed continue; 3549193326Sed 3550193326Sed std::vector<llvm::Constant*> Values(5); 3551193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); 3552198092Srdivacky Values[1] = GetClassName(I->first); 3553193326Sed Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 3554193326Sed Values[3] = Values[4] = 3555193326Sed llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); 3556198092Srdivacky I->second->setLinkage(llvm::GlobalValue::InternalLinkage); 3557198092Srdivacky I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, 3558193326Sed Values)); 3559198092Srdivacky CGM.AddUsedGlobal(I->second); 3560193326Sed } 3561193326Sed 3562193326Sed // Add assembler directives to add lazy undefined symbol references 3563193326Sed // for classes which are referenced but not defined. This is 3564193326Sed // important for correct linker interaction. 3565198092Srdivacky // 3566198092Srdivacky // FIXME: It would be nice if we had an LLVM construct for this. 3567198092Srdivacky if (!LazySymbols.empty() || !DefinedSymbols.empty()) { 3568198092Srdivacky llvm::SmallString<256> Asm; 3569198092Srdivacky Asm += CGM.getModule().getModuleInlineAsm(); 3570198092Srdivacky if (!Asm.empty() && Asm.back() != '\n') 3571198092Srdivacky Asm += '\n'; 3572193326Sed 3573198092Srdivacky llvm::raw_svector_ostream OS(Asm); 3574198092Srdivacky for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(), 3575198092Srdivacky e = LazySymbols.end(); I != e; ++I) 3576198092Srdivacky OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n"; 3577198092Srdivacky for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(), 3578198092Srdivacky e = DefinedSymbols.end(); I != e; ++I) 3579198092Srdivacky OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n" 3580198092Srdivacky << "\t.globl .objc_class_name_" << (*I)->getName() << "\n"; 3581198092Srdivacky 3582198092Srdivacky CGM.getModule().setModuleInlineAsm(OS.str()); 3583193326Sed } 3584193326Sed} 3585193326Sed 3586198092SrdivackyCGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm) 3587193326Sed : CGObjCCommonMac(cgm), 3588198092Srdivacky ObjCTypes(cgm) { 3589193326Sed ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL; 3590193326Sed ObjCABI = 2; 3591193326Sed} 3592193326Sed 3593193326Sed/* *** */ 3594193326Sed 3595193326SedObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) 3596198092Srdivacky : VMContext(cgm.getLLVMContext()), CGM(cgm) { 3597193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 3598193326Sed ASTContext &Ctx = CGM.getContext(); 3599198092Srdivacky 3600193326Sed ShortTy = Types.ConvertType(Ctx.ShortTy); 3601193326Sed IntTy = Types.ConvertType(Ctx.IntTy); 3602193326Sed LongTy = Types.ConvertType(Ctx.LongTy); 3603193326Sed LongLongTy = Types.ConvertType(Ctx.LongLongTy); 3604198092Srdivacky Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); 3605198092Srdivacky 3606193326Sed ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType()); 3607193326Sed PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy); 3608193326Sed SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType()); 3609198092Srdivacky 3610193326Sed // FIXME: It would be nice to unify this with the opaque type, so that the IR 3611193326Sed // comes out a bit cleaner. 3612193326Sed const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType()); 3613193326Sed ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T); 3614198092Srdivacky 3615193326Sed // I'm not sure I like this. The implicit coordination is a bit 3616193326Sed // gross. We should solve this in a reasonable fashion because this 3617193326Sed // is a pretty common task (match some runtime data structure with 3618193326Sed // an LLVM data structure). 3619198092Srdivacky 3620193326Sed // FIXME: This is leaked. 3621193326Sed // FIXME: Merge with rewriter code? 3622198092Srdivacky 3623193326Sed // struct _objc_super { 3624193326Sed // id self; 3625193326Sed // Class cls; 3626193326Sed // } 3627193326Sed RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0, 3628193326Sed SourceLocation(), 3629198092Srdivacky &Ctx.Idents.get("_objc_super")); 3630195341Sed RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 3631198092Srdivacky Ctx.getObjCIdType(), 0, 0, false)); 3632198092Srdivacky RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 3633198092Srdivacky Ctx.getObjCClassType(), 0, 0, false)); 3634203955Srdivacky RD->completeDefinition(); 3635198092Srdivacky 3636193326Sed SuperCTy = Ctx.getTagDeclType(RD); 3637193326Sed SuperPtrCTy = Ctx.getPointerType(SuperCTy); 3638198092Srdivacky 3639193326Sed SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy)); 3640198092Srdivacky SuperPtrTy = llvm::PointerType::getUnqual(SuperTy); 3641198092Srdivacky 3642193326Sed // struct _prop_t { 3643193326Sed // char *name; 3644198092Srdivacky // char *attributes; 3645193326Sed // } 3646198092Srdivacky PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL); 3647198092Srdivacky CGM.getModule().addTypeName("struct._prop_t", 3648193326Sed PropertyTy); 3649198092Srdivacky 3650193326Sed // struct _prop_list_t { 3651193326Sed // uint32_t entsize; // sizeof(struct _prop_t) 3652193326Sed // uint32_t count_of_properties; 3653193326Sed // struct _prop_t prop_list[count_of_properties]; 3654193326Sed // } 3655198092Srdivacky PropertyListTy = llvm::StructType::get(VMContext, IntTy, 3656193326Sed IntTy, 3657193326Sed llvm::ArrayType::get(PropertyTy, 0), 3658193326Sed NULL); 3659198092Srdivacky CGM.getModule().addTypeName("struct._prop_list_t", 3660193326Sed PropertyListTy); 3661193326Sed // struct _prop_list_t * 3662193326Sed PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy); 3663198092Srdivacky 3664193326Sed // struct _objc_method { 3665193326Sed // SEL _cmd; 3666193326Sed // char *method_type; 3667193326Sed // char *_imp; 3668193326Sed // } 3669198092Srdivacky MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy, 3670193326Sed Int8PtrTy, 3671193326Sed Int8PtrTy, 3672193326Sed NULL); 3673193326Sed CGM.getModule().addTypeName("struct._objc_method", MethodTy); 3674198092Srdivacky 3675193326Sed // struct _objc_cache * 3676198092Srdivacky CacheTy = llvm::OpaqueType::get(VMContext); 3677193326Sed CGM.getModule().addTypeName("struct._objc_cache", CacheTy); 3678193326Sed CachePtrTy = llvm::PointerType::getUnqual(CacheTy); 3679193326Sed} 3680193326Sed 3681198092SrdivackyObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) 3682198092Srdivacky : ObjCCommonTypesHelper(cgm) { 3683193326Sed // struct _objc_method_description { 3684193326Sed // SEL name; 3685193326Sed // char *types; 3686193326Sed // } 3687198092Srdivacky MethodDescriptionTy = 3688198092Srdivacky llvm::StructType::get(VMContext, SelectorPtrTy, 3689193326Sed Int8PtrTy, 3690193326Sed NULL); 3691198092Srdivacky CGM.getModule().addTypeName("struct._objc_method_description", 3692193326Sed MethodDescriptionTy); 3693193326Sed 3694193326Sed // struct _objc_method_description_list { 3695193326Sed // int count; 3696193326Sed // struct _objc_method_description[1]; 3697193326Sed // } 3698198092Srdivacky MethodDescriptionListTy = 3699198092Srdivacky llvm::StructType::get(VMContext, IntTy, 3700193326Sed llvm::ArrayType::get(MethodDescriptionTy, 0), 3701193326Sed NULL); 3702198092Srdivacky CGM.getModule().addTypeName("struct._objc_method_description_list", 3703193326Sed MethodDescriptionListTy); 3704198092Srdivacky 3705193326Sed // struct _objc_method_description_list * 3706198092Srdivacky MethodDescriptionListPtrTy = 3707193326Sed llvm::PointerType::getUnqual(MethodDescriptionListTy); 3708193326Sed 3709193326Sed // Protocol description structures 3710193326Sed 3711193326Sed // struct _objc_protocol_extension { 3712193326Sed // uint32_t size; // sizeof(struct _objc_protocol_extension) 3713193326Sed // struct _objc_method_description_list *optional_instance_methods; 3714193326Sed // struct _objc_method_description_list *optional_class_methods; 3715193326Sed // struct _objc_property_list *instance_properties; 3716193326Sed // } 3717198092Srdivacky ProtocolExtensionTy = 3718198092Srdivacky llvm::StructType::get(VMContext, IntTy, 3719193326Sed MethodDescriptionListPtrTy, 3720193326Sed MethodDescriptionListPtrTy, 3721193326Sed PropertyListPtrTy, 3722193326Sed NULL); 3723198092Srdivacky CGM.getModule().addTypeName("struct._objc_protocol_extension", 3724193326Sed ProtocolExtensionTy); 3725198092Srdivacky 3726193326Sed // struct _objc_protocol_extension * 3727193326Sed ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy); 3728193326Sed 3729193326Sed // Handle recursive construction of Protocol and ProtocolList types 3730193326Sed 3731198092Srdivacky llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext); 3732198092Srdivacky llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext); 3733193326Sed 3734198092Srdivacky const llvm::Type *T = 3735198092Srdivacky llvm::StructType::get(VMContext, 3736198092Srdivacky llvm::PointerType::getUnqual(ProtocolListTyHolder), 3737193326Sed LongTy, 3738193326Sed llvm::ArrayType::get(ProtocolTyHolder, 0), 3739193326Sed NULL); 3740193326Sed cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T); 3741193326Sed 3742193326Sed // struct _objc_protocol { 3743193326Sed // struct _objc_protocol_extension *isa; 3744193326Sed // char *protocol_name; 3745193326Sed // struct _objc_protocol **_objc_protocol_list; 3746193326Sed // struct _objc_method_description_list *instance_methods; 3747193326Sed // struct _objc_method_description_list *class_methods; 3748193326Sed // } 3749198092Srdivacky T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy, 3750193326Sed Int8PtrTy, 3751193326Sed llvm::PointerType::getUnqual(ProtocolListTyHolder), 3752193326Sed MethodDescriptionListPtrTy, 3753193326Sed MethodDescriptionListPtrTy, 3754193326Sed NULL); 3755193326Sed cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T); 3756193326Sed 3757193326Sed ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get()); 3758198092Srdivacky CGM.getModule().addTypeName("struct._objc_protocol_list", 3759193326Sed ProtocolListTy); 3760193326Sed // struct _objc_protocol_list * 3761193326Sed ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy); 3762193326Sed 3763193326Sed ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get()); 3764193326Sed CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy); 3765193326Sed ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy); 3766193326Sed 3767193326Sed // Class description structures 3768193326Sed 3769193326Sed // struct _objc_ivar { 3770193326Sed // char *ivar_name; 3771193326Sed // char *ivar_type; 3772193326Sed // int ivar_offset; 3773193326Sed // } 3774198092Srdivacky IvarTy = llvm::StructType::get(VMContext, Int8PtrTy, 3775198092Srdivacky Int8PtrTy, 3776198092Srdivacky IntTy, 3777193326Sed NULL); 3778193326Sed CGM.getModule().addTypeName("struct._objc_ivar", IvarTy); 3779193326Sed 3780193326Sed // struct _objc_ivar_list * 3781198092Srdivacky IvarListTy = llvm::OpaqueType::get(VMContext); 3782193326Sed CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy); 3783193326Sed IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy); 3784193326Sed 3785193326Sed // struct _objc_method_list * 3786198092Srdivacky MethodListTy = llvm::OpaqueType::get(VMContext); 3787193326Sed CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy); 3788193326Sed MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy); 3789193326Sed 3790193326Sed // struct _objc_class_extension * 3791198092Srdivacky ClassExtensionTy = 3792198092Srdivacky llvm::StructType::get(VMContext, IntTy, 3793193326Sed Int8PtrTy, 3794193326Sed PropertyListPtrTy, 3795193326Sed NULL); 3796193326Sed CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy); 3797193326Sed ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy); 3798193326Sed 3799198092Srdivacky llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext); 3800193326Sed 3801193326Sed // struct _objc_class { 3802193326Sed // Class isa; 3803193326Sed // Class super_class; 3804193326Sed // char *name; 3805193326Sed // long version; 3806193326Sed // long info; 3807193326Sed // long instance_size; 3808193326Sed // struct _objc_ivar_list *ivars; 3809193326Sed // struct _objc_method_list *methods; 3810193326Sed // struct _objc_cache *cache; 3811193326Sed // struct _objc_protocol_list *protocols; 3812193326Sed // char *ivar_layout; 3813193326Sed // struct _objc_class_ext *ext; 3814193326Sed // }; 3815198092Srdivacky T = llvm::StructType::get(VMContext, 3816193326Sed llvm::PointerType::getUnqual(ClassTyHolder), 3817198092Srdivacky llvm::PointerType::getUnqual(ClassTyHolder), 3818193326Sed Int8PtrTy, 3819193326Sed LongTy, 3820193326Sed LongTy, 3821193326Sed LongTy, 3822193326Sed IvarListPtrTy, 3823193326Sed MethodListPtrTy, 3824193326Sed CachePtrTy, 3825193326Sed ProtocolListPtrTy, 3826193326Sed Int8PtrTy, 3827193326Sed ClassExtensionPtrTy, 3828193326Sed NULL); 3829193326Sed cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T); 3830198092Srdivacky 3831193326Sed ClassTy = cast<llvm::StructType>(ClassTyHolder.get()); 3832193326Sed CGM.getModule().addTypeName("struct._objc_class", ClassTy); 3833193326Sed ClassPtrTy = llvm::PointerType::getUnqual(ClassTy); 3834193326Sed 3835193326Sed // struct _objc_category { 3836193326Sed // char *category_name; 3837193326Sed // char *class_name; 3838193326Sed // struct _objc_method_list *instance_method; 3839193326Sed // struct _objc_method_list *class_method; 3840193326Sed // uint32_t size; // sizeof(struct _objc_category) 3841193326Sed // struct _objc_property_list *instance_properties;// category's @property 3842193326Sed // } 3843198092Srdivacky CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy, 3844193326Sed Int8PtrTy, 3845193326Sed MethodListPtrTy, 3846193326Sed MethodListPtrTy, 3847193326Sed ProtocolListPtrTy, 3848193326Sed IntTy, 3849193326Sed PropertyListPtrTy, 3850193326Sed NULL); 3851193326Sed CGM.getModule().addTypeName("struct._objc_category", CategoryTy); 3852193326Sed 3853193326Sed // Global metadata structures 3854193326Sed 3855193326Sed // struct _objc_symtab { 3856193326Sed // long sel_ref_cnt; 3857193326Sed // SEL *refs; 3858193326Sed // short cls_def_cnt; 3859193326Sed // short cat_def_cnt; 3860193326Sed // char *defs[cls_def_cnt + cat_def_cnt]; 3861193326Sed // } 3862198092Srdivacky SymtabTy = llvm::StructType::get(VMContext, LongTy, 3863193326Sed SelectorPtrTy, 3864193326Sed ShortTy, 3865193326Sed ShortTy, 3866193326Sed llvm::ArrayType::get(Int8PtrTy, 0), 3867193326Sed NULL); 3868193326Sed CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy); 3869193326Sed SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy); 3870193326Sed 3871193326Sed // struct _objc_module { 3872193326Sed // long version; 3873193326Sed // long size; // sizeof(struct _objc_module) 3874193326Sed // char *name; 3875193326Sed // struct _objc_symtab* symtab; 3876193326Sed // } 3877198092Srdivacky ModuleTy = 3878198092Srdivacky llvm::StructType::get(VMContext, LongTy, 3879193326Sed LongTy, 3880193326Sed Int8PtrTy, 3881193326Sed SymtabPtrTy, 3882193326Sed NULL); 3883193326Sed CGM.getModule().addTypeName("struct._objc_module", ModuleTy); 3884193326Sed 3885198092Srdivacky 3886193326Sed // FIXME: This is the size of the setjmp buffer and should be target 3887193326Sed // specific. 18 is what's used on 32-bit X86. 3888193326Sed uint64_t SetJmpBufferSize = 18; 3889198092Srdivacky 3890193326Sed // Exceptions 3891198092Srdivacky const llvm::Type *StackPtrTy = llvm::ArrayType::get( 3892198092Srdivacky llvm::Type::getInt8PtrTy(VMContext), 4); 3893198092Srdivacky 3894198092Srdivacky ExceptionDataTy = 3895198092Srdivacky llvm::StructType::get(VMContext, llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext), 3896198092Srdivacky SetJmpBufferSize), 3897193326Sed StackPtrTy, NULL); 3898198092Srdivacky CGM.getModule().addTypeName("struct._objc_exception_data", 3899193326Sed ExceptionDataTy); 3900193326Sed 3901193326Sed} 3902193326Sed 3903198092SrdivackyObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm) 3904198092Srdivacky : ObjCCommonTypesHelper(cgm) { 3905193326Sed // struct _method_list_t { 3906193326Sed // uint32_t entsize; // sizeof(struct _objc_method) 3907193326Sed // uint32_t method_count; 3908193326Sed // struct _objc_method method_list[method_count]; 3909193326Sed // } 3910198092Srdivacky MethodListnfABITy = llvm::StructType::get(VMContext, IntTy, 3911193326Sed IntTy, 3912193326Sed llvm::ArrayType::get(MethodTy, 0), 3913193326Sed NULL); 3914193326Sed CGM.getModule().addTypeName("struct.__method_list_t", 3915193326Sed MethodListnfABITy); 3916193326Sed // struct method_list_t * 3917193326Sed MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy); 3918198092Srdivacky 3919193326Sed // struct _protocol_t { 3920193326Sed // id isa; // NULL 3921193326Sed // const char * const protocol_name; 3922193326Sed // const struct _protocol_list_t * protocol_list; // super protocols 3923193326Sed // const struct method_list_t * const instance_methods; 3924193326Sed // const struct method_list_t * const class_methods; 3925193326Sed // const struct method_list_t *optionalInstanceMethods; 3926193326Sed // const struct method_list_t *optionalClassMethods; 3927193326Sed // const struct _prop_list_t * properties; 3928193326Sed // const uint32_t size; // sizeof(struct _protocol_t) 3929193326Sed // const uint32_t flags; // = 0 3930193326Sed // } 3931198092Srdivacky 3932193326Sed // Holder for struct _protocol_list_t * 3933198092Srdivacky llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext); 3934198092Srdivacky 3935198092Srdivacky ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy, 3936193326Sed Int8PtrTy, 3937193326Sed llvm::PointerType::getUnqual( 3938193326Sed ProtocolListTyHolder), 3939193326Sed MethodListnfABIPtrTy, 3940193326Sed MethodListnfABIPtrTy, 3941193326Sed MethodListnfABIPtrTy, 3942193326Sed MethodListnfABIPtrTy, 3943193326Sed PropertyListPtrTy, 3944193326Sed IntTy, 3945193326Sed IntTy, 3946193326Sed NULL); 3947193326Sed CGM.getModule().addTypeName("struct._protocol_t", 3948193326Sed ProtocolnfABITy); 3949193326Sed 3950193326Sed // struct _protocol_t* 3951193326Sed ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy); 3952198092Srdivacky 3953193326Sed // struct _protocol_list_t { 3954193326Sed // long protocol_count; // Note, this is 32/64 bit 3955193326Sed // struct _protocol_t *[protocol_count]; 3956193326Sed // } 3957198092Srdivacky ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy, 3958193326Sed llvm::ArrayType::get( 3959193326Sed ProtocolnfABIPtrTy, 0), 3960193326Sed NULL); 3961193326Sed CGM.getModule().addTypeName("struct._objc_protocol_list", 3962193326Sed ProtocolListnfABITy); 3963193326Sed cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo( 3964198092Srdivacky ProtocolListnfABITy); 3965198092Srdivacky 3966193326Sed // struct _objc_protocol_list* 3967193326Sed ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy); 3968198092Srdivacky 3969193326Sed // struct _ivar_t { 3970193326Sed // unsigned long int *offset; // pointer to ivar offset location 3971193326Sed // char *name; 3972193326Sed // char *type; 3973193326Sed // uint32_t alignment; 3974193326Sed // uint32_t size; 3975193326Sed // } 3976198092Srdivacky IvarnfABITy = llvm::StructType::get(VMContext, 3977198092Srdivacky llvm::PointerType::getUnqual(LongTy), 3978193326Sed Int8PtrTy, 3979193326Sed Int8PtrTy, 3980193326Sed IntTy, 3981193326Sed IntTy, 3982193326Sed NULL); 3983193326Sed CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy); 3984198092Srdivacky 3985193326Sed // struct _ivar_list_t { 3986193326Sed // uint32 entsize; // sizeof(struct _ivar_t) 3987193326Sed // uint32 count; 3988193326Sed // struct _iver_t list[count]; 3989193326Sed // } 3990198092Srdivacky IvarListnfABITy = llvm::StructType::get(VMContext, IntTy, 3991193326Sed IntTy, 3992193326Sed llvm::ArrayType::get( 3993198092Srdivacky IvarnfABITy, 0), 3994193326Sed NULL); 3995193326Sed CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy); 3996198092Srdivacky 3997193326Sed IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy); 3998198092Srdivacky 3999193326Sed // struct _class_ro_t { 4000193326Sed // uint32_t const flags; 4001193326Sed // uint32_t const instanceStart; 4002193326Sed // uint32_t const instanceSize; 4003193326Sed // uint32_t const reserved; // only when building for 64bit targets 4004193326Sed // const uint8_t * const ivarLayout; 4005193326Sed // const char *const name; 4006193326Sed // const struct _method_list_t * const baseMethods; 4007193326Sed // const struct _objc_protocol_list *const baseProtocols; 4008193326Sed // const struct _ivar_list_t *const ivars; 4009193326Sed // const uint8_t * const weakIvarLayout; 4010193326Sed // const struct _prop_list_t * const properties; 4011193326Sed // } 4012198092Srdivacky 4013193326Sed // FIXME. Add 'reserved' field in 64bit abi mode! 4014198092Srdivacky ClassRonfABITy = llvm::StructType::get(VMContext, IntTy, 4015193326Sed IntTy, 4016193326Sed IntTy, 4017193326Sed Int8PtrTy, 4018193326Sed Int8PtrTy, 4019193326Sed MethodListnfABIPtrTy, 4020193326Sed ProtocolListnfABIPtrTy, 4021193326Sed IvarListnfABIPtrTy, 4022193326Sed Int8PtrTy, 4023193326Sed PropertyListPtrTy, 4024193326Sed NULL); 4025193326Sed CGM.getModule().addTypeName("struct._class_ro_t", 4026193326Sed ClassRonfABITy); 4027198092Srdivacky 4028193326Sed // ImpnfABITy - LLVM for id (*)(id, SEL, ...) 4029193326Sed std::vector<const llvm::Type*> Params; 4030193326Sed Params.push_back(ObjectPtrTy); 4031193326Sed Params.push_back(SelectorPtrTy); 4032193326Sed ImpnfABITy = llvm::PointerType::getUnqual( 4033198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Params, false)); 4034198092Srdivacky 4035193326Sed // struct _class_t { 4036193326Sed // struct _class_t *isa; 4037193326Sed // struct _class_t * const superclass; 4038193326Sed // void *cache; 4039193326Sed // IMP *vtable; 4040193326Sed // struct class_ro_t *ro; 4041193326Sed // } 4042198092Srdivacky 4043198092Srdivacky llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext); 4044198092Srdivacky ClassnfABITy = 4045198092Srdivacky llvm::StructType::get(VMContext, 4046198092Srdivacky llvm::PointerType::getUnqual(ClassTyHolder), 4047198092Srdivacky llvm::PointerType::getUnqual(ClassTyHolder), 4048198092Srdivacky CachePtrTy, 4049198092Srdivacky llvm::PointerType::getUnqual(ImpnfABITy), 4050198092Srdivacky llvm::PointerType::getUnqual(ClassRonfABITy), 4051198092Srdivacky NULL); 4052193326Sed CGM.getModule().addTypeName("struct._class_t", ClassnfABITy); 4053193326Sed 4054193326Sed cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo( 4055198092Srdivacky ClassnfABITy); 4056198092Srdivacky 4057193326Sed // LLVM for struct _class_t * 4058193326Sed ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy); 4059198092Srdivacky 4060193326Sed // struct _category_t { 4061193326Sed // const char * const name; 4062193326Sed // struct _class_t *const cls; 4063193326Sed // const struct _method_list_t * const instance_methods; 4064193326Sed // const struct _method_list_t * const class_methods; 4065193326Sed // const struct _protocol_list_t * const protocols; 4066193326Sed // const struct _prop_list_t * const properties; 4067193326Sed // } 4068198092Srdivacky CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy, 4069193326Sed ClassnfABIPtrTy, 4070193326Sed MethodListnfABIPtrTy, 4071193326Sed MethodListnfABIPtrTy, 4072193326Sed ProtocolListnfABIPtrTy, 4073193326Sed PropertyListPtrTy, 4074193326Sed NULL); 4075193326Sed CGM.getModule().addTypeName("struct._category_t", CategorynfABITy); 4076198092Srdivacky 4077193326Sed // New types for nonfragile abi messaging. 4078193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 4079193326Sed ASTContext &Ctx = CGM.getContext(); 4080198092Srdivacky 4081193326Sed // MessageRefTy - LLVM for: 4082193326Sed // struct _message_ref_t { 4083193326Sed // IMP messenger; 4084193326Sed // SEL name; 4085193326Sed // }; 4086198092Srdivacky 4087193326Sed // First the clang type for struct _message_ref_t 4088193326Sed RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0, 4089193326Sed SourceLocation(), 4090193326Sed &Ctx.Idents.get("_message_ref_t")); 4091195341Sed RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 4092198092Srdivacky Ctx.VoidPtrTy, 0, 0, false)); 4093195341Sed RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 4094198092Srdivacky Ctx.getObjCSelType(), 0, 0, false)); 4095203955Srdivacky RD->completeDefinition(); 4096198092Srdivacky 4097193326Sed MessageRefCTy = Ctx.getTagDeclType(RD); 4098193326Sed MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy); 4099193326Sed MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy)); 4100198092Srdivacky 4101193326Sed // MessageRefPtrTy - LLVM for struct _message_ref_t* 4102193326Sed MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy); 4103198092Srdivacky 4104193326Sed // SuperMessageRefTy - LLVM for: 4105193326Sed // struct _super_message_ref_t { 4106193326Sed // SUPER_IMP messenger; 4107193326Sed // SEL name; 4108193326Sed // }; 4109198092Srdivacky SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy, 4110193326Sed SelectorPtrTy, 4111193326Sed NULL); 4112193326Sed CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy); 4113198092Srdivacky 4114193326Sed // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* 4115198092Srdivacky SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); 4116193326Sed 4117198092Srdivacky 4118193326Sed // struct objc_typeinfo { 4119193326Sed // const void** vtable; // objc_ehtype_vtable + 2 4120193326Sed // const char* name; // c++ typeinfo string 4121193326Sed // Class cls; 4122193326Sed // }; 4123198092Srdivacky EHTypeTy = llvm::StructType::get(VMContext, 4124198092Srdivacky llvm::PointerType::getUnqual(Int8PtrTy), 4125193326Sed Int8PtrTy, 4126193326Sed ClassnfABIPtrTy, 4127193326Sed NULL); 4128193326Sed CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy); 4129193326Sed EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy); 4130193326Sed} 4131193326Sed 4132198092Srdivackyllvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() { 4133193326Sed FinishNonFragileABIModule(); 4134198092Srdivacky 4135193326Sed return NULL; 4136193326Sed} 4137193326Sed 4138198092Srdivackyvoid CGObjCNonFragileABIMac::AddModuleClassList(const 4139198092Srdivacky std::vector<llvm::GlobalValue*> 4140198092Srdivacky &Container, 4141193326Sed const char *SymbolName, 4142193326Sed const char *SectionName) { 4143193326Sed unsigned NumClasses = Container.size(); 4144198092Srdivacky 4145193326Sed if (!NumClasses) 4146193326Sed return; 4147198092Srdivacky 4148193326Sed std::vector<llvm::Constant*> Symbols(NumClasses); 4149193326Sed for (unsigned i=0; i<NumClasses; i++) 4150193326Sed Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i], 4151193326Sed ObjCTypes.Int8PtrTy); 4152198092Srdivacky llvm::Constant* Init = 4153193326Sed llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 4154193326Sed NumClasses), 4155193326Sed Symbols); 4156198092Srdivacky 4157193326Sed llvm::GlobalVariable *GV = 4158198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 4159193326Sed llvm::GlobalValue::InternalLinkage, 4160193326Sed Init, 4161198092Srdivacky SymbolName); 4162193326Sed GV->setAlignment(8); 4163193326Sed GV->setSection(SectionName); 4164198092Srdivacky CGM.AddUsedGlobal(GV); 4165193326Sed} 4166198092Srdivacky 4167193326Sedvoid CGObjCNonFragileABIMac::FinishNonFragileABIModule() { 4168193326Sed // nonfragile abi has no module definition. 4169198092Srdivacky 4170193326Sed // Build list of all implemented class addresses in array 4171193326Sed // L_OBJC_LABEL_CLASS_$. 4172198092Srdivacky AddModuleClassList(DefinedClasses, 4173193326Sed "\01L_OBJC_LABEL_CLASS_$", 4174193326Sed "__DATA, __objc_classlist, regular, no_dead_strip"); 4175199482Srdivacky 4176199482Srdivacky for (unsigned i = 0; i < DefinedClasses.size(); i++) { 4177199482Srdivacky llvm::GlobalValue *IMPLGV = DefinedClasses[i]; 4178199482Srdivacky if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) 4179199482Srdivacky continue; 4180199482Srdivacky IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage); 4181199482Srdivacky } 4182199482Srdivacky 4183200583Srdivacky for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) { 4184200583Srdivacky llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i]; 4185200583Srdivacky if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) 4186200583Srdivacky continue; 4187200583Srdivacky IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage); 4188200583Srdivacky } 4189199482Srdivacky 4190198092Srdivacky AddModuleClassList(DefinedNonLazyClasses, 4191193326Sed "\01L_OBJC_LABEL_NONLAZY_CLASS_$", 4192193326Sed "__DATA, __objc_nlclslist, regular, no_dead_strip"); 4193198092Srdivacky 4194193326Sed // Build list of all implemented category addresses in array 4195193326Sed // L_OBJC_LABEL_CATEGORY_$. 4196198092Srdivacky AddModuleClassList(DefinedCategories, 4197193326Sed "\01L_OBJC_LABEL_CATEGORY_$", 4198193326Sed "__DATA, __objc_catlist, regular, no_dead_strip"); 4199198092Srdivacky AddModuleClassList(DefinedNonLazyCategories, 4200193326Sed "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$", 4201193326Sed "__DATA, __objc_nlcatlist, regular, no_dead_strip"); 4202198092Srdivacky 4203193326Sed // static int L_OBJC_IMAGE_INFO[2] = { 0, flags }; 4204193326Sed // FIXME. flags can be 0 | 1 | 2 | 6. For now just use 0 4205193326Sed std::vector<llvm::Constant*> Values(2); 4206193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, 0); 4207193326Sed unsigned int flags = 0; 4208193326Sed // FIXME: Fix and continue? 4209193326Sed if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) 4210193326Sed flags |= eImageInfo_GarbageCollected; 4211193326Sed if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) 4212193326Sed flags |= eImageInfo_GCOnly; 4213193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags); 4214193326Sed llvm::Constant* Init = llvm::ConstantArray::get( 4215198092Srdivacky llvm::ArrayType::get(ObjCTypes.IntTy, 2), 4216198092Srdivacky Values); 4217193326Sed llvm::GlobalVariable *IMGV = 4218198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 4219193326Sed llvm::GlobalValue::InternalLinkage, 4220193326Sed Init, 4221198092Srdivacky "\01L_OBJC_IMAGE_INFO"); 4222193326Sed IMGV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip"); 4223193326Sed IMGV->setConstant(true); 4224198092Srdivacky CGM.AddUsedGlobal(IMGV); 4225193326Sed} 4226193326Sed 4227193326Sed/// LegacyDispatchedSelector - Returns true if SEL is not in the list of 4228193326Sed/// NonLegacyDispatchMethods; false otherwise. What this means is that 4229198092Srdivacky/// except for the 19 selectors in the list, we generate 32bit-style 4230193326Sed/// message dispatch call for all the rest. 4231193326Sed/// 4232193326Sedbool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) { 4233203955Srdivacky if (CGM.getCodeGenOpts().ObjCLegacyDispatch) 4234203955Srdivacky return true; 4235203955Srdivacky 4236193326Sed if (NonLegacyDispatchMethods.empty()) { 4237193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("alloc")); 4238193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("class")); 4239193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("self")); 4240193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("isFlipped")); 4241193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("length")); 4242193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("count")); 4243193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("retain")); 4244193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("release")); 4245193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("autorelease")); 4246193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("hash")); 4247198092Srdivacky 4248193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("allocWithZone")); 4249193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("isKindOfClass")); 4250193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("respondsToSelector")); 4251193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("objectForKey")); 4252193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("objectAtIndex")); 4253193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("isEqualToString")); 4254193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("isEqual")); 4255193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("addObject")); 4256198092Srdivacky // "countByEnumeratingWithState:objects:count" 4257193326Sed IdentifierInfo *KeyIdents[] = { 4258198092Srdivacky &CGM.getContext().Idents.get("countByEnumeratingWithState"), 4259198092Srdivacky &CGM.getContext().Idents.get("objects"), 4260198092Srdivacky &CGM.getContext().Idents.get("count") 4261193326Sed }; 4262193326Sed NonLegacyDispatchMethods.insert( 4263193326Sed CGM.getContext().Selectors.getSelector(3, KeyIdents)); 4264193326Sed } 4265193326Sed return (NonLegacyDispatchMethods.count(Sel) == 0); 4266193326Sed} 4267193326Sed 4268193326Sed// Metadata flags 4269193326Sedenum MetaDataDlags { 4270193326Sed CLS = 0x0, 4271193326Sed CLS_META = 0x1, 4272193326Sed CLS_ROOT = 0x2, 4273193326Sed OBJC2_CLS_HIDDEN = 0x10, 4274193326Sed CLS_EXCEPTION = 0x20 4275193326Sed}; 4276193326Sed/// BuildClassRoTInitializer - generate meta-data for: 4277193326Sed/// struct _class_ro_t { 4278193326Sed/// uint32_t const flags; 4279193326Sed/// uint32_t const instanceStart; 4280193326Sed/// uint32_t const instanceSize; 4281193326Sed/// uint32_t const reserved; // only when building for 64bit targets 4282193326Sed/// const uint8_t * const ivarLayout; 4283193326Sed/// const char *const name; 4284193326Sed/// const struct _method_list_t * const baseMethods; 4285193326Sed/// const struct _protocol_list_t *const baseProtocols; 4286193326Sed/// const struct _ivar_list_t *const ivars; 4287193326Sed/// const uint8_t * const weakIvarLayout; 4288193326Sed/// const struct _prop_list_t * const properties; 4289193326Sed/// } 4290193326Sed/// 4291193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( 4292198092Srdivacky unsigned flags, 4293198092Srdivacky unsigned InstanceStart, 4294198092Srdivacky unsigned InstanceSize, 4295198092Srdivacky const ObjCImplementationDecl *ID) { 4296193326Sed std::string ClassName = ID->getNameAsString(); 4297193326Sed std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets! 4298193326Sed Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags); 4299193326Sed Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart); 4300193326Sed Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize); 4301193326Sed // FIXME. For 64bit targets add 0 here. 4302198092Srdivacky Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) 4303198092Srdivacky : BuildIvarLayout(ID, true); 4304193326Sed Values[ 4] = GetClassName(ID->getIdentifier()); 4305193326Sed // const struct _method_list_t * const baseMethods; 4306193326Sed std::vector<llvm::Constant*> Methods; 4307193326Sed std::string MethodListName("\01l_OBJC_$_"); 4308193326Sed if (flags & CLS_META) { 4309193326Sed MethodListName += "CLASS_METHODS_" + ID->getNameAsString(); 4310198092Srdivacky for (ObjCImplementationDecl::classmeth_iterator 4311195341Sed i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { 4312193326Sed // Class methods should always be defined. 4313193326Sed Methods.push_back(GetMethodConstant(*i)); 4314193326Sed } 4315193326Sed } else { 4316193326Sed MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString(); 4317198092Srdivacky for (ObjCImplementationDecl::instmeth_iterator 4318195341Sed i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { 4319193326Sed // Instance methods should always be defined. 4320193326Sed Methods.push_back(GetMethodConstant(*i)); 4321193326Sed } 4322198092Srdivacky for (ObjCImplementationDecl::propimpl_iterator 4323195341Sed i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { 4324193326Sed ObjCPropertyImplDecl *PID = *i; 4325198092Srdivacky 4326193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){ 4327193326Sed ObjCPropertyDecl *PD = PID->getPropertyDecl(); 4328198092Srdivacky 4329193326Sed if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) 4330193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 4331193326Sed Methods.push_back(C); 4332193326Sed if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) 4333193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 4334193326Sed Methods.push_back(C); 4335193326Sed } 4336193326Sed } 4337193326Sed } 4338198092Srdivacky Values[ 5] = EmitMethodList(MethodListName, 4339198092Srdivacky "__DATA, __objc_const", Methods); 4340198092Srdivacky 4341193326Sed const ObjCInterfaceDecl *OID = ID->getClassInterface(); 4342193326Sed assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer"); 4343198092Srdivacky Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_" 4344198398Srdivacky + OID->getName(), 4345193326Sed OID->protocol_begin(), 4346193326Sed OID->protocol_end()); 4347198092Srdivacky 4348193326Sed if (flags & CLS_META) 4349193326Sed Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); 4350193326Sed else 4351193326Sed Values[ 7] = EmitIvarList(ID); 4352198092Srdivacky Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) 4353198092Srdivacky : BuildIvarLayout(ID, false); 4354193326Sed if (flags & CLS_META) 4355193326Sed Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 4356193326Sed else 4357198398Srdivacky Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), 4358198398Srdivacky ID, ID->getClassInterface(), ObjCTypes); 4359193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy, 4360193326Sed Values); 4361193326Sed llvm::GlobalVariable *CLASS_RO_GV = 4362198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false, 4363198092Srdivacky llvm::GlobalValue::InternalLinkage, 4364198092Srdivacky Init, 4365198092Srdivacky (flags & CLS_META) ? 4366198092Srdivacky std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName : 4367198092Srdivacky std::string("\01l_OBJC_CLASS_RO_$_")+ClassName); 4368193326Sed CLASS_RO_GV->setAlignment( 4369193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassRonfABITy)); 4370193326Sed CLASS_RO_GV->setSection("__DATA, __objc_const"); 4371193326Sed return CLASS_RO_GV; 4372193326Sed 4373193326Sed} 4374193326Sed 4375193326Sed/// BuildClassMetaData - This routine defines that to-level meta-data 4376193326Sed/// for the given ClassName for: 4377193326Sed/// struct _class_t { 4378193326Sed/// struct _class_t *isa; 4379193326Sed/// struct _class_t * const superclass; 4380193326Sed/// void *cache; 4381193326Sed/// IMP *vtable; 4382193326Sed/// struct class_ro_t *ro; 4383193326Sed/// } 4384193326Sed/// 4385193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( 4386198092Srdivacky std::string &ClassName, 4387198092Srdivacky llvm::Constant *IsAGV, 4388198092Srdivacky llvm::Constant *SuperClassGV, 4389198092Srdivacky llvm::Constant *ClassRoGV, 4390198092Srdivacky bool HiddenVisibility) { 4391193326Sed std::vector<llvm::Constant*> Values(5); 4392193326Sed Values[0] = IsAGV; 4393198092Srdivacky Values[1] = SuperClassGV; 4394198092Srdivacky if (!Values[1]) 4395198092Srdivacky Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy); 4396193326Sed Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar 4397193326Sed Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar 4398193326Sed Values[4] = ClassRoGV; // &CLASS_RO_GV 4399198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy, 4400193326Sed Values); 4401193326Sed llvm::GlobalVariable *GV = GetClassGlobal(ClassName); 4402193326Sed GV->setInitializer(Init); 4403193326Sed GV->setSection("__DATA, __objc_data"); 4404193326Sed GV->setAlignment( 4405193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassnfABITy)); 4406193326Sed if (HiddenVisibility) 4407193326Sed GV->setVisibility(llvm::GlobalValue::HiddenVisibility); 4408193326Sed return GV; 4409193326Sed} 4410193326Sed 4411198092Srdivackybool 4412193326SedCGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const { 4413195341Sed return OD->getClassMethod(GetNullarySelector("load")) != 0; 4414193326Sed} 4415193326Sed 4416193326Sedvoid CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, 4417193326Sed uint32_t &InstanceStart, 4418193326Sed uint32_t &InstanceSize) { 4419198092Srdivacky const ASTRecordLayout &RL = 4420193326Sed CGM.getContext().getASTObjCImplementationLayout(OID); 4421198092Srdivacky 4422193326Sed // InstanceSize is really instance end. 4423198092Srdivacky InstanceSize = llvm::RoundUpToAlignment(RL.getDataSize(), 8) / 8; 4424193326Sed 4425193326Sed // If there are no fields, the start is the same as the end. 4426193326Sed if (!RL.getFieldCount()) 4427193326Sed InstanceStart = InstanceSize; 4428193326Sed else 4429193326Sed InstanceStart = RL.getFieldOffset(0) / 8; 4430193326Sed} 4431193326Sed 4432193326Sedvoid CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { 4433193326Sed std::string ClassName = ID->getNameAsString(); 4434193326Sed if (!ObjCEmptyCacheVar) { 4435193326Sed ObjCEmptyCacheVar = new llvm::GlobalVariable( 4436198092Srdivacky CGM.getModule(), 4437198092Srdivacky ObjCTypes.CacheTy, 4438198092Srdivacky false, 4439198092Srdivacky llvm::GlobalValue::ExternalLinkage, 4440198092Srdivacky 0, 4441198092Srdivacky "_objc_empty_cache"); 4442198092Srdivacky 4443193326Sed ObjCEmptyVtableVar = new llvm::GlobalVariable( 4444198092Srdivacky CGM.getModule(), 4445198092Srdivacky ObjCTypes.ImpnfABITy, 4446198092Srdivacky false, 4447198092Srdivacky llvm::GlobalValue::ExternalLinkage, 4448198092Srdivacky 0, 4449198092Srdivacky "_objc_empty_vtable"); 4450193326Sed } 4451198092Srdivacky assert(ID->getClassInterface() && 4452193326Sed "CGObjCNonFragileABIMac::GenerateClass - class is 0"); 4453193326Sed // FIXME: Is this correct (that meta class size is never computed)? 4454198092Srdivacky uint32_t InstanceStart = 4455193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy); 4456193326Sed uint32_t InstanceSize = InstanceStart; 4457193326Sed uint32_t flags = CLS_META; 4458193326Sed std::string ObjCMetaClassName(getMetaclassSymbolPrefix()); 4459193326Sed std::string ObjCClassName(getClassSymbolPrefix()); 4460198092Srdivacky 4461193326Sed llvm::GlobalVariable *SuperClassGV, *IsAGV; 4462198092Srdivacky 4463198092Srdivacky bool classIsHidden = 4464193326Sed CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden; 4465193326Sed if (classIsHidden) 4466193326Sed flags |= OBJC2_CLS_HIDDEN; 4467193326Sed if (!ID->getClassInterface()->getSuperClass()) { 4468193326Sed // class is root 4469193326Sed flags |= CLS_ROOT; 4470193326Sed SuperClassGV = GetClassGlobal(ObjCClassName + ClassName); 4471193326Sed IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName); 4472193326Sed } else { 4473193326Sed // Has a root. Current class is not a root. 4474193326Sed const ObjCInterfaceDecl *Root = ID->getClassInterface(); 4475193326Sed while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) 4476193326Sed Root = Super; 4477193326Sed IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString()); 4478200583Srdivacky if (Root->hasAttr<WeakImportAttr>()) 4479200583Srdivacky IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 4480193326Sed // work on super class metadata symbol. 4481198092Srdivacky std::string SuperClassName = 4482200583Srdivacky ObjCMetaClassName + 4483200583Srdivacky ID->getClassInterface()->getSuperClass()->getNameAsString(); 4484193326Sed SuperClassGV = GetClassGlobal(SuperClassName); 4485199482Srdivacky if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>()) 4486199482Srdivacky SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 4487193326Sed } 4488193326Sed llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags, 4489193326Sed InstanceStart, 4490193326Sed InstanceSize,ID); 4491193326Sed std::string TClassName = ObjCMetaClassName + ClassName; 4492198092Srdivacky llvm::GlobalVariable *MetaTClass = 4493193326Sed BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV, 4494193326Sed classIsHidden); 4495199482Srdivacky DefinedMetaClasses.push_back(MetaTClass); 4496193326Sed 4497193326Sed // Metadata for the class 4498193326Sed flags = CLS; 4499193326Sed if (classIsHidden) 4500193326Sed flags |= OBJC2_CLS_HIDDEN; 4501193326Sed 4502194613Sed if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface())) 4503193326Sed flags |= CLS_EXCEPTION; 4504193326Sed 4505193326Sed if (!ID->getClassInterface()->getSuperClass()) { 4506193326Sed flags |= CLS_ROOT; 4507193326Sed SuperClassGV = 0; 4508193326Sed } else { 4509193326Sed // Has a root. Current class is not a root. 4510193326Sed std::string RootClassName = 4511193326Sed ID->getClassInterface()->getSuperClass()->getNameAsString(); 4512193326Sed SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName); 4513199482Srdivacky if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>()) 4514199482Srdivacky SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 4515193326Sed } 4516193326Sed GetClassSizeInfo(ID, InstanceStart, InstanceSize); 4517193326Sed CLASS_RO_GV = BuildClassRoTInitializer(flags, 4518193326Sed InstanceStart, 4519198092Srdivacky InstanceSize, 4520193326Sed ID); 4521198092Srdivacky 4522193326Sed TClassName = ObjCClassName + ClassName; 4523198092Srdivacky llvm::GlobalVariable *ClassMD = 4524193326Sed BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV, 4525193326Sed classIsHidden); 4526193326Sed DefinedClasses.push_back(ClassMD); 4527193326Sed 4528193326Sed // Determine if this class is also "non-lazy". 4529193326Sed if (ImplementationIsNonLazy(ID)) 4530193326Sed DefinedNonLazyClasses.push_back(ClassMD); 4531193326Sed 4532193326Sed // Force the definition of the EHType if necessary. 4533193326Sed if (flags & CLS_EXCEPTION) 4534193326Sed GetInterfaceEHType(ID->getClassInterface(), true); 4535193326Sed} 4536193326Sed 4537193326Sed/// GenerateProtocolRef - This routine is called to generate code for 4538193326Sed/// a protocol reference expression; as in: 4539193326Sed/// @code 4540193326Sed/// @protocol(Proto1); 4541193326Sed/// @endcode 4542193326Sed/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1 4543193326Sed/// which will hold address of the protocol meta-data. 4544193326Sed/// 4545193326Sedllvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder, 4546198092Srdivacky const ObjCProtocolDecl *PD) { 4547198092Srdivacky 4548193326Sed // This routine is called for @protocol only. So, we must build definition 4549193326Sed // of protocol's meta-data (not a reference to it!) 4550193326Sed // 4551198092Srdivacky llvm::Constant *Init = 4552198092Srdivacky llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD), 4553198092Srdivacky ObjCTypes.ExternalProtocolPtrTy); 4554198092Srdivacky 4555193326Sed std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_"); 4556193326Sed ProtocolName += PD->getNameAsCString(); 4557198092Srdivacky 4558193326Sed llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName); 4559193326Sed if (PTGV) 4560199990Srdivacky return Builder.CreateLoad(PTGV, "tmp"); 4561193326Sed PTGV = new llvm::GlobalVariable( 4562198092Srdivacky CGM.getModule(), 4563198092Srdivacky Init->getType(), false, 4564198092Srdivacky llvm::GlobalValue::WeakAnyLinkage, 4565198092Srdivacky Init, 4566198092Srdivacky ProtocolName); 4567193326Sed PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip"); 4568193326Sed PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 4569198092Srdivacky CGM.AddUsedGlobal(PTGV); 4570199990Srdivacky return Builder.CreateLoad(PTGV, "tmp"); 4571193326Sed} 4572193326Sed 4573193326Sed/// GenerateCategory - Build metadata for a category implementation. 4574193326Sed/// struct _category_t { 4575193326Sed/// const char * const name; 4576193326Sed/// struct _class_t *const cls; 4577193326Sed/// const struct _method_list_t * const instance_methods; 4578193326Sed/// const struct _method_list_t * const class_methods; 4579193326Sed/// const struct _protocol_list_t * const protocols; 4580193326Sed/// const struct _prop_list_t * const properties; 4581193326Sed/// } 4582193326Sed/// 4583193326Sedvoid CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 4584193326Sed const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); 4585193326Sed const char *Prefix = "\01l_OBJC_$_CATEGORY_"; 4586198092Srdivacky std::string ExtCatName(Prefix + Interface->getNameAsString()+ 4587198092Srdivacky "_$_" + OCD->getNameAsString()); 4588198092Srdivacky std::string ExtClassName(getClassSymbolPrefix() + 4589193326Sed Interface->getNameAsString()); 4590198092Srdivacky 4591193326Sed std::vector<llvm::Constant*> Values(6); 4592193326Sed Values[0] = GetClassName(OCD->getIdentifier()); 4593193326Sed // meta-class entry symbol 4594193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName); 4595199482Srdivacky if (Interface->hasAttr<WeakImportAttr>()) 4596199482Srdivacky ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 4597199482Srdivacky 4598193326Sed Values[1] = ClassGV; 4599193326Sed std::vector<llvm::Constant*> Methods; 4600193326Sed std::string MethodListName(Prefix); 4601198092Srdivacky MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() + 4602193326Sed "_$_" + OCD->getNameAsString(); 4603198092Srdivacky 4604198092Srdivacky for (ObjCCategoryImplDecl::instmeth_iterator 4605195341Sed i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { 4606193326Sed // Instance methods should always be defined. 4607193326Sed Methods.push_back(GetMethodConstant(*i)); 4608193326Sed } 4609198092Srdivacky 4610198092Srdivacky Values[2] = EmitMethodList(MethodListName, 4611198092Srdivacky "__DATA, __objc_const", 4612193326Sed Methods); 4613193326Sed 4614193326Sed MethodListName = Prefix; 4615193326Sed MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" + 4616193326Sed OCD->getNameAsString(); 4617193326Sed Methods.clear(); 4618198092Srdivacky for (ObjCCategoryImplDecl::classmeth_iterator 4619195341Sed i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { 4620193326Sed // Class methods should always be defined. 4621193326Sed Methods.push_back(GetMethodConstant(*i)); 4622193326Sed } 4623198092Srdivacky 4624198092Srdivacky Values[3] = EmitMethodList(MethodListName, 4625198092Srdivacky "__DATA, __objc_const", 4626193326Sed Methods); 4627198092Srdivacky const ObjCCategoryDecl *Category = 4628193326Sed Interface->FindCategoryDeclaration(OCD->getIdentifier()); 4629193326Sed if (Category) { 4630198398Srdivacky llvm::SmallString<256> ExtName; 4631198398Srdivacky llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_" 4632198398Srdivacky << OCD->getName(); 4633193326Sed Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_" 4634198398Srdivacky + Interface->getName() + "_$_" 4635198398Srdivacky + Category->getName(), 4636193326Sed Category->protocol_begin(), 4637193326Sed Category->protocol_end()); 4638198398Srdivacky Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), 4639198398Srdivacky OCD, Category, ObjCTypes); 4640198092Srdivacky } else { 4641193326Sed Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); 4642193326Sed Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 4643193326Sed } 4644198092Srdivacky 4645198092Srdivacky llvm::Constant *Init = 4646198092Srdivacky llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy, 4647193326Sed Values); 4648193326Sed llvm::GlobalVariable *GCATV 4649198092Srdivacky = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy, 4650193326Sed false, 4651193326Sed llvm::GlobalValue::InternalLinkage, 4652193326Sed Init, 4653198092Srdivacky ExtCatName); 4654193326Sed GCATV->setAlignment( 4655193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.CategorynfABITy)); 4656193326Sed GCATV->setSection("__DATA, __objc_const"); 4657198092Srdivacky CGM.AddUsedGlobal(GCATV); 4658193326Sed DefinedCategories.push_back(GCATV); 4659193326Sed 4660193326Sed // Determine if this category is also "non-lazy". 4661193326Sed if (ImplementationIsNonLazy(OCD)) 4662193326Sed DefinedNonLazyCategories.push_back(GCATV); 4663193326Sed} 4664193326Sed 4665193326Sed/// GetMethodConstant - Return a struct objc_method constant for the 4666193326Sed/// given method if it has been defined. The result is null if the 4667193326Sed/// method has not been defined. The return value has type MethodPtrTy. 4668193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant( 4669198092Srdivacky const ObjCMethodDecl *MD) { 4670193326Sed // FIXME: Use DenseMap::lookup 4671193326Sed llvm::Function *Fn = MethodDefinitions[MD]; 4672193326Sed if (!Fn) 4673193326Sed return 0; 4674198092Srdivacky 4675193326Sed std::vector<llvm::Constant*> Method(3); 4676198092Srdivacky Method[0] = 4677198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 4678198092Srdivacky ObjCTypes.SelectorPtrTy); 4679193326Sed Method[1] = GetMethodVarType(MD); 4680193326Sed Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy); 4681193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method); 4682193326Sed} 4683193326Sed 4684193326Sed/// EmitMethodList - Build meta-data for method declarations 4685193326Sed/// struct _method_list_t { 4686193326Sed/// uint32_t entsize; // sizeof(struct _objc_method) 4687193326Sed/// uint32_t method_count; 4688193326Sed/// struct _objc_method method_list[method_count]; 4689193326Sed/// } 4690193326Sed/// 4691198398Srdivackyllvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name, 4692198398Srdivacky const char *Section, 4693198398Srdivacky const ConstantVector &Methods) { 4694193326Sed // Return null for empty list. 4695193326Sed if (Methods.empty()) 4696193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy); 4697198092Srdivacky 4698193326Sed std::vector<llvm::Constant*> Values(3); 4699193326Sed // sizeof(struct _objc_method) 4700193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy); 4701193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 4702193326Sed // method_count 4703193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 4704193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy, 4705193326Sed Methods.size()); 4706193326Sed Values[2] = llvm::ConstantArray::get(AT, Methods); 4707198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 4708198092Srdivacky 4709193326Sed llvm::GlobalVariable *GV = 4710198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 4711193326Sed llvm::GlobalValue::InternalLinkage, 4712193326Sed Init, 4713198092Srdivacky Name); 4714193326Sed GV->setAlignment( 4715193326Sed CGM.getTargetData().getPrefTypeAlignment(Init->getType())); 4716193326Sed GV->setSection(Section); 4717198092Srdivacky CGM.AddUsedGlobal(GV); 4718193326Sed return llvm::ConstantExpr::getBitCast(GV, 4719193326Sed ObjCTypes.MethodListnfABIPtrTy); 4720193326Sed} 4721193326Sed 4722193326Sed/// ObjCIvarOffsetVariable - Returns the ivar offset variable for 4723193326Sed/// the given ivar. 4724193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable( 4725198092Srdivacky const ObjCInterfaceDecl *ID, 4726198092Srdivacky const ObjCIvarDecl *Ivar) { 4727193326Sed // FIXME: We shouldn't need to do this lookup. 4728193326Sed unsigned Index; 4729198092Srdivacky const ObjCInterfaceDecl *Container = 4730193326Sed FindIvarInterface(CGM.getContext(), ID, Ivar, Index); 4731193326Sed assert(Container && "Unable to find ivar container!"); 4732193326Sed std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() + 4733193326Sed '.' + Ivar->getNameAsString(); 4734198092Srdivacky llvm::GlobalVariable *IvarOffsetGV = 4735193326Sed CGM.getModule().getGlobalVariable(Name); 4736193326Sed if (!IvarOffsetGV) 4737198092Srdivacky IvarOffsetGV = 4738198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy, 4739193326Sed false, 4740193326Sed llvm::GlobalValue::ExternalLinkage, 4741193326Sed 0, 4742198092Srdivacky Name); 4743193326Sed return IvarOffsetGV; 4744193326Sed} 4745193326Sed 4746193326Sedllvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar( 4747198092Srdivacky const ObjCInterfaceDecl *ID, 4748198092Srdivacky const ObjCIvarDecl *Ivar, 4749198092Srdivacky unsigned long int Offset) { 4750193326Sed llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar); 4751198092Srdivacky IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy, 4752193326Sed Offset)); 4753193326Sed IvarOffsetGV->setAlignment( 4754193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy)); 4755193326Sed 4756193326Sed // FIXME: This matches gcc, but shouldn't the visibility be set on the use as 4757193326Sed // well (i.e., in ObjCIvarOffsetVariable). 4758193326Sed if (Ivar->getAccessControl() == ObjCIvarDecl::Private || 4759193326Sed Ivar->getAccessControl() == ObjCIvarDecl::Package || 4760193326Sed CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden) 4761193326Sed IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 4762193326Sed else 4763193326Sed IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); 4764193326Sed IvarOffsetGV->setSection("__DATA, __objc_const"); 4765193326Sed return IvarOffsetGV; 4766193326Sed} 4767193326Sed 4768193326Sed/// EmitIvarList - Emit the ivar list for the given 4769193326Sed/// implementation. The return value has type 4770193326Sed/// IvarListnfABIPtrTy. 4771193326Sed/// struct _ivar_t { 4772193326Sed/// unsigned long int *offset; // pointer to ivar offset location 4773193326Sed/// char *name; 4774193326Sed/// char *type; 4775193326Sed/// uint32_t alignment; 4776193326Sed/// uint32_t size; 4777193326Sed/// } 4778193326Sed/// struct _ivar_list_t { 4779193326Sed/// uint32 entsize; // sizeof(struct _ivar_t) 4780193326Sed/// uint32 count; 4781193326Sed/// struct _iver_t list[count]; 4782193326Sed/// } 4783193326Sed/// 4784193326Sed 4785193326Sedllvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( 4786198092Srdivacky const ObjCImplementationDecl *ID) { 4787198092Srdivacky 4788193326Sed std::vector<llvm::Constant*> Ivars, Ivar(5); 4789198092Srdivacky 4790193326Sed const ObjCInterfaceDecl *OID = ID->getClassInterface(); 4791193326Sed assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface"); 4792198092Srdivacky 4793193326Sed // FIXME. Consolidate this with similar code in GenerateClass. 4794198092Srdivacky 4795193326Sed // Collect declared and synthesized ivars in a small vector. 4796193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; 4797193576Sed CGM.getContext().ShallowCollectObjCIvars(OID, OIvars); 4798198092Srdivacky 4799193326Sed for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { 4800193326Sed ObjCIvarDecl *IVD = OIvars[i]; 4801193576Sed // Ignore unnamed bit-fields. 4802193576Sed if (!IVD->getDeclName()) 4803193576Sed continue; 4804198092Srdivacky Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD, 4805193326Sed ComputeIvarBaseOffset(CGM, ID, IVD)); 4806193326Sed Ivar[1] = GetMethodVarName(IVD->getIdentifier()); 4807193326Sed Ivar[2] = GetMethodVarType(IVD); 4808193326Sed const llvm::Type *FieldTy = 4809193326Sed CGM.getTypes().ConvertTypeForMem(IVD->getType()); 4810193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy); 4811193326Sed unsigned Align = CGM.getContext().getPreferredTypeAlign( 4812198092Srdivacky IVD->getType().getTypePtr()) >> 3; 4813193326Sed Align = llvm::Log2_32(Align); 4814193326Sed Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align); 4815193326Sed // NOTE. Size of a bitfield does not match gcc's, because of the 4816193326Sed // way bitfields are treated special in each. But I am told that 4817193326Sed // 'size' for bitfield ivars is ignored by the runtime so it does 4818193326Sed // not matter. If it matters, there is enough info to get the 4819193326Sed // bitfield right! 4820193326Sed Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 4821193326Sed Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar)); 4822193326Sed } 4823193326Sed // Return null for empty list. 4824193326Sed if (Ivars.empty()) 4825193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); 4826193326Sed std::vector<llvm::Constant*> Values(3); 4827193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy); 4828193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 4829193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size()); 4830193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy, 4831193326Sed Ivars.size()); 4832193326Sed Values[2] = llvm::ConstantArray::get(AT, Ivars); 4833198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 4834193326Sed const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_"; 4835193326Sed llvm::GlobalVariable *GV = 4836198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 4837193326Sed llvm::GlobalValue::InternalLinkage, 4838193326Sed Init, 4839198398Srdivacky Prefix + OID->getName()); 4840193326Sed GV->setAlignment( 4841193326Sed CGM.getTargetData().getPrefTypeAlignment(Init->getType())); 4842193326Sed GV->setSection("__DATA, __objc_const"); 4843198092Srdivacky 4844198092Srdivacky CGM.AddUsedGlobal(GV); 4845198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy); 4846193326Sed} 4847193326Sed 4848193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( 4849198092Srdivacky const ObjCProtocolDecl *PD) { 4850193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 4851198092Srdivacky 4852193326Sed if (!Entry) { 4853193326Sed // We use the initializer as a marker of whether this is a forward 4854193326Sed // reference or not. At module finalization we add the empty 4855193326Sed // contents for protocols which were referenced but never defined. 4856198092Srdivacky Entry = 4857198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false, 4858198092Srdivacky llvm::GlobalValue::ExternalLinkage, 4859198092Srdivacky 0, 4860198398Srdivacky "\01l_OBJC_PROTOCOL_$_" + PD->getName()); 4861193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 4862193326Sed } 4863198092Srdivacky 4864193326Sed return Entry; 4865193326Sed} 4866193326Sed 4867193326Sed/// GetOrEmitProtocol - Generate the protocol meta-data: 4868193326Sed/// @code 4869193326Sed/// struct _protocol_t { 4870193326Sed/// id isa; // NULL 4871193326Sed/// const char * const protocol_name; 4872193326Sed/// const struct _protocol_list_t * protocol_list; // super protocols 4873193326Sed/// const struct method_list_t * const instance_methods; 4874193326Sed/// const struct method_list_t * const class_methods; 4875193326Sed/// const struct method_list_t *optionalInstanceMethods; 4876193326Sed/// const struct method_list_t *optionalClassMethods; 4877193326Sed/// const struct _prop_list_t * properties; 4878193326Sed/// const uint32_t size; // sizeof(struct _protocol_t) 4879193326Sed/// const uint32_t flags; // = 0 4880193326Sed/// } 4881193326Sed/// @endcode 4882193326Sed/// 4883193326Sed 4884193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( 4885198092Srdivacky const ObjCProtocolDecl *PD) { 4886193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 4887198092Srdivacky 4888193326Sed // Early exit if a defining object has already been generated. 4889193326Sed if (Entry && Entry->hasInitializer()) 4890193326Sed return Entry; 4891193326Sed 4892193326Sed // Construct method lists. 4893193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 4894193326Sed std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; 4895198092Srdivacky for (ObjCProtocolDecl::instmeth_iterator 4896195341Sed i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { 4897193326Sed ObjCMethodDecl *MD = *i; 4898193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 4899193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 4900193326Sed OptInstanceMethods.push_back(C); 4901193326Sed } else { 4902193326Sed InstanceMethods.push_back(C); 4903198092Srdivacky } 4904193326Sed } 4905198092Srdivacky 4906198092Srdivacky for (ObjCProtocolDecl::classmeth_iterator 4907195341Sed i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { 4908193326Sed ObjCMethodDecl *MD = *i; 4909193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 4910193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 4911193326Sed OptClassMethods.push_back(C); 4912193326Sed } else { 4913193326Sed ClassMethods.push_back(C); 4914198092Srdivacky } 4915193326Sed } 4916198092Srdivacky 4917193326Sed std::vector<llvm::Constant*> Values(10); 4918193326Sed // isa is NULL 4919193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy); 4920193326Sed Values[1] = GetClassName(PD->getIdentifier()); 4921198398Srdivacky Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(), 4922198398Srdivacky PD->protocol_begin(), 4923198398Srdivacky PD->protocol_end()); 4924198092Srdivacky 4925193326Sed Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_" 4926198398Srdivacky + PD->getName(), 4927193326Sed "__DATA, __objc_const", 4928193326Sed InstanceMethods); 4929198092Srdivacky Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_" 4930198398Srdivacky + PD->getName(), 4931193326Sed "__DATA, __objc_const", 4932193326Sed ClassMethods); 4933193326Sed Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_" 4934198398Srdivacky + PD->getName(), 4935193326Sed "__DATA, __objc_const", 4936193326Sed OptInstanceMethods); 4937198092Srdivacky Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_" 4938198398Srdivacky + PD->getName(), 4939193326Sed "__DATA, __objc_const", 4940193326Sed OptClassMethods); 4941198398Srdivacky Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(), 4942193326Sed 0, PD, ObjCTypes); 4943198092Srdivacky uint32_t Size = 4944193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); 4945193326Sed Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 4946193326Sed Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy); 4947193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy, 4948193326Sed Values); 4949198092Srdivacky 4950193326Sed if (Entry) { 4951193326Sed // Already created, fix the linkage and update the initializer. 4952193326Sed Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 4953193326Sed Entry->setInitializer(Init); 4954193326Sed } else { 4955198092Srdivacky Entry = 4956198398Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, 4957198398Srdivacky false, llvm::GlobalValue::WeakAnyLinkage, Init, 4958198398Srdivacky "\01l_OBJC_PROTOCOL_$_" + PD->getName()); 4959193326Sed Entry->setAlignment( 4960193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy)); 4961193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 4962193326Sed } 4963193326Sed Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); 4964198092Srdivacky CGM.AddUsedGlobal(Entry); 4965198092Srdivacky 4966193326Sed // Use this protocol meta-data to build protocol list table in section 4967193326Sed // __DATA, __objc_protolist 4968198398Srdivacky llvm::GlobalVariable *PTGV = 4969198398Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, 4970198398Srdivacky false, llvm::GlobalValue::WeakAnyLinkage, Entry, 4971198398Srdivacky "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName()); 4972193326Sed PTGV->setAlignment( 4973193326Sed CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); 4974193326Sed PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip"); 4975193326Sed PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 4976198092Srdivacky CGM.AddUsedGlobal(PTGV); 4977193326Sed return Entry; 4978193326Sed} 4979193326Sed 4980193326Sed/// EmitProtocolList - Generate protocol list meta-data: 4981193326Sed/// @code 4982193326Sed/// struct _protocol_list_t { 4983193326Sed/// long protocol_count; // Note, this is 32/64 bit 4984193326Sed/// struct _protocol_t[protocol_count]; 4985193326Sed/// } 4986193326Sed/// @endcode 4987193326Sed/// 4988193326Sedllvm::Constant * 4989198398SrdivackyCGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name, 4990198398Srdivacky ObjCProtocolDecl::protocol_iterator begin, 4991198398Srdivacky ObjCProtocolDecl::protocol_iterator end) { 4992193326Sed std::vector<llvm::Constant*> ProtocolRefs; 4993198092Srdivacky 4994193326Sed // Just return null for empty protocol lists 4995198092Srdivacky if (begin == end) 4996193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); 4997198092Srdivacky 4998193326Sed // FIXME: We shouldn't need to do this lookup here, should we? 4999198398Srdivacky llvm::SmallString<256> TmpName; 5000198398Srdivacky Name.toVector(TmpName); 5001198398Srdivacky llvm::GlobalVariable *GV = 5002198398Srdivacky CGM.getModule().getGlobalVariable(TmpName.str(), true); 5003193326Sed if (GV) 5004198398Srdivacky return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy); 5005198092Srdivacky 5006193326Sed for (; begin != end; ++begin) 5007193326Sed ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented??? 5008193326Sed 5009193326Sed // This list is null terminated. 5010193326Sed ProtocolRefs.push_back(llvm::Constant::getNullValue( 5011198092Srdivacky ObjCTypes.ProtocolnfABIPtrTy)); 5012198092Srdivacky 5013193326Sed std::vector<llvm::Constant*> Values(2); 5014198092Srdivacky Values[0] = 5015198092Srdivacky llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1); 5016198092Srdivacky Values[1] = 5017198092Srdivacky llvm::ConstantArray::get( 5018198092Srdivacky llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy, 5019198092Srdivacky ProtocolRefs.size()), 5020198092Srdivacky ProtocolRefs); 5021198092Srdivacky 5022198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 5023198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 5024193326Sed llvm::GlobalValue::InternalLinkage, 5025193326Sed Init, 5026198092Srdivacky Name); 5027193326Sed GV->setSection("__DATA, __objc_const"); 5028193326Sed GV->setAlignment( 5029193326Sed CGM.getTargetData().getPrefTypeAlignment(Init->getType())); 5030198092Srdivacky CGM.AddUsedGlobal(GV); 5031198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, 5032193326Sed ObjCTypes.ProtocolListnfABIPtrTy); 5033193326Sed} 5034193326Sed 5035193326Sed/// GetMethodDescriptionConstant - This routine build following meta-data: 5036193326Sed/// struct _objc_method { 5037193326Sed/// SEL _cmd; 5038193326Sed/// char *method_type; 5039193326Sed/// char *_imp; 5040193326Sed/// } 5041193326Sed 5042193326Sedllvm::Constant * 5043193326SedCGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { 5044193326Sed std::vector<llvm::Constant*> Desc(3); 5045198092Srdivacky Desc[0] = 5046198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 5047198092Srdivacky ObjCTypes.SelectorPtrTy); 5048193326Sed Desc[1] = GetMethodVarType(MD); 5049193326Sed // Protocol methods have no implementation. So, this entry is always NULL. 5050193326Sed Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 5051193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc); 5052193326Sed} 5053193326Sed 5054193326Sed/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference. 5055193326Sed/// This code gen. amounts to generating code for: 5056193326Sed/// @code 5057193326Sed/// (type *)((char *)base + _OBJC_IVAR_$_.ivar; 5058193326Sed/// @encode 5059198092Srdivacky/// 5060193326SedLValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( 5061198092Srdivacky CodeGen::CodeGenFunction &CGF, 5062198092Srdivacky QualType ObjectTy, 5063198092Srdivacky llvm::Value *BaseValue, 5064198092Srdivacky const ObjCIvarDecl *Ivar, 5065198092Srdivacky unsigned CVRQualifiers) { 5066198092Srdivacky const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); 5067193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 5068193326Sed EmitIvarOffset(CGF, ID, Ivar)); 5069193326Sed} 5070193326Sed 5071193326Sedllvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset( 5072198092Srdivacky CodeGen::CodeGenFunction &CGF, 5073198092Srdivacky const ObjCInterfaceDecl *Interface, 5074198092Srdivacky const ObjCIvarDecl *Ivar) { 5075199990Srdivacky return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar"); 5076193326Sed} 5077193326Sed 5078193326SedCodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( 5079198092Srdivacky CodeGen::CodeGenFunction &CGF, 5080198092Srdivacky QualType ResultType, 5081198092Srdivacky Selector Sel, 5082198092Srdivacky llvm::Value *Receiver, 5083198092Srdivacky QualType Arg0Ty, 5084198092Srdivacky bool IsSuper, 5085198092Srdivacky const CallArgList &CallArgs) { 5086193326Sed // FIXME. Even though IsSuper is passes. This function doese not handle calls 5087193326Sed // to 'super' receivers. 5088193326Sed CodeGenTypes &Types = CGM.getTypes(); 5089193326Sed llvm::Value *Arg0 = Receiver; 5090193326Sed if (!IsSuper) 5091193326Sed Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp"); 5092198092Srdivacky 5093193326Sed // Find the message function name. 5094193326Sed // FIXME. This is too much work to get the ABI-specific result type needed to 5095193326Sed // find the message name. 5096198092Srdivacky const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, 5097203955Srdivacky llvm::SmallVector<QualType, 16>(), 5098203955Srdivacky CC_Default, false); 5099193326Sed llvm::Constant *Fn = 0; 5100193326Sed std::string Name("\01l_"); 5101193326Sed if (CGM.ReturnTypeUsesSret(FnInfo)) { 5102193326Sed#if 0 5103193326Sed // unlike what is documented. gcc never generates this API!! 5104193326Sed if (Receiver->getType() == ObjCTypes.ObjectPtrTy) { 5105193326Sed Fn = ObjCTypes.getMessageSendIdStretFixupFn(); 5106193326Sed // FIXME. Is there a better way of getting these names. 5107193326Sed // They are available in RuntimeFunctions vector pair. 5108193326Sed Name += "objc_msgSendId_stret_fixup"; 5109198092Srdivacky } else 5110193326Sed#endif 5111198092Srdivacky if (IsSuper) { 5112193326Sed Fn = ObjCTypes.getMessageSendSuper2StretFixupFn(); 5113193326Sed Name += "objc_msgSendSuper2_stret_fixup"; 5114198092Srdivacky } else { 5115198092Srdivacky Fn = ObjCTypes.getMessageSendStretFixupFn(); 5116198092Srdivacky Name += "objc_msgSend_stret_fixup"; 5117198092Srdivacky } 5118198092Srdivacky } else if (!IsSuper && ResultType->isFloatingType()) { 5119195099Sed if (ResultType->isSpecificBuiltinType(BuiltinType::LongDouble)) { 5120195099Sed Fn = ObjCTypes.getMessageSendFpretFixupFn(); 5121195099Sed Name += "objc_msgSend_fpret_fixup"; 5122198092Srdivacky } else { 5123195099Sed Fn = ObjCTypes.getMessageSendFixupFn(); 5124195099Sed Name += "objc_msgSend_fixup"; 5125193326Sed } 5126198092Srdivacky } else { 5127193326Sed#if 0 5128193326Sed// unlike what is documented. gcc never generates this API!! 5129193326Sed if (Receiver->getType() == ObjCTypes.ObjectPtrTy) { 5130193326Sed Fn = ObjCTypes.getMessageSendIdFixupFn(); 5131193326Sed Name += "objc_msgSendId_fixup"; 5132198092Srdivacky } else 5133193326Sed#endif 5134198092Srdivacky if (IsSuper) { 5135193326Sed Fn = ObjCTypes.getMessageSendSuper2FixupFn(); 5136193326Sed Name += "objc_msgSendSuper2_fixup"; 5137198092Srdivacky } else { 5138198092Srdivacky Fn = ObjCTypes.getMessageSendFixupFn(); 5139198092Srdivacky Name += "objc_msgSend_fixup"; 5140198092Srdivacky } 5141193326Sed } 5142193326Sed assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend"); 5143193326Sed Name += '_'; 5144193326Sed std::string SelName(Sel.getAsString()); 5145193326Sed // Replace all ':' in selector name with '_' ouch! 5146198092Srdivacky for (unsigned i = 0; i < SelName.size(); i++) 5147193326Sed if (SelName[i] == ':') 5148193326Sed SelName[i] = '_'; 5149193326Sed Name += SelName; 5150193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 5151193326Sed if (!GV) { 5152193326Sed // Build message ref table entry. 5153193326Sed std::vector<llvm::Constant*> Values(2); 5154193326Sed Values[0] = Fn; 5155193326Sed Values[1] = GetMethodVarName(Sel); 5156198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 5157198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 5158193326Sed llvm::GlobalValue::WeakAnyLinkage, 5159193326Sed Init, 5160198092Srdivacky Name); 5161193326Sed GV->setVisibility(llvm::GlobalValue::HiddenVisibility); 5162193326Sed GV->setAlignment(16); 5163193326Sed GV->setSection("__DATA, __objc_msgrefs, coalesced"); 5164193326Sed } 5165193326Sed llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy); 5166198092Srdivacky 5167193326Sed CallArgList ActualArgs; 5168193326Sed ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty)); 5169198092Srdivacky ActualArgs.push_back(std::make_pair(RValue::get(Arg1), 5170193326Sed ObjCTypes.MessageRefCPtrTy)); 5171193326Sed ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); 5172203955Srdivacky const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs, 5173203955Srdivacky CC_Default, false); 5174193326Sed llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0); 5175193326Sed Callee = CGF.Builder.CreateLoad(Callee); 5176193326Sed const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true); 5177193326Sed Callee = CGF.Builder.CreateBitCast(Callee, 5178193326Sed llvm::PointerType::getUnqual(FTy)); 5179201361Srdivacky return CGF.EmitCall(FnInfo1, Callee, ReturnValueSlot(), ActualArgs); 5180193326Sed} 5181193326Sed 5182193326Sed/// Generate code for a message send expression in the nonfragile abi. 5183198092SrdivackyCodeGen::RValue 5184198092SrdivackyCGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 5185198092Srdivacky QualType ResultType, 5186198092Srdivacky Selector Sel, 5187198092Srdivacky llvm::Value *Receiver, 5188198092Srdivacky bool IsClassMessage, 5189198092Srdivacky const CallArgList &CallArgs, 5190198092Srdivacky const ObjCMethodDecl *Method) { 5191193326Sed return LegacyDispatchedSelector(Sel) 5192198092Srdivacky ? EmitLegacyMessageSend(CGF, ResultType, EmitSelector(CGF.Builder, Sel), 5193198092Srdivacky Receiver, CGF.getContext().getObjCIdType(), 5194198092Srdivacky false, CallArgs, Method, ObjCTypes) 5195198092Srdivacky : EmitMessageSend(CGF, ResultType, Sel, 5196198092Srdivacky Receiver, CGF.getContext().getObjCIdType(), 5197198092Srdivacky false, CallArgs); 5198193326Sed} 5199193326Sed 5200193326Sedllvm::GlobalVariable * 5201193326SedCGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) { 5202193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 5203193326Sed 5204193326Sed if (!GV) { 5205198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy, 5206198092Srdivacky false, llvm::GlobalValue::ExternalLinkage, 5207198092Srdivacky 0, Name); 5208193326Sed } 5209193326Sed 5210193326Sed return GV; 5211193326Sed} 5212193326Sed 5213198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder, 5214198092Srdivacky const ObjCInterfaceDecl *ID) { 5215193326Sed llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()]; 5216198092Srdivacky 5217193326Sed if (!Entry) { 5218193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5219193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 5220198092Srdivacky Entry = 5221198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, 5222198092Srdivacky false, llvm::GlobalValue::InternalLinkage, 5223198092Srdivacky ClassGV, 5224198092Srdivacky "\01L_OBJC_CLASSLIST_REFERENCES_$_"); 5225193326Sed Entry->setAlignment( 5226198092Srdivacky CGM.getTargetData().getPrefTypeAlignment( 5227198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 5228193326Sed Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip"); 5229198092Srdivacky CGM.AddUsedGlobal(Entry); 5230193326Sed } 5231198092Srdivacky 5232199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 5233193326Sed} 5234193326Sed 5235193326Sedllvm::Value * 5236198092SrdivackyCGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder, 5237193326Sed const ObjCInterfaceDecl *ID) { 5238193326Sed llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()]; 5239198092Srdivacky 5240193326Sed if (!Entry) { 5241193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5242193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 5243198092Srdivacky Entry = 5244198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, 5245198092Srdivacky false, llvm::GlobalValue::InternalLinkage, 5246198092Srdivacky ClassGV, 5247198092Srdivacky "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); 5248193326Sed Entry->setAlignment( 5249198092Srdivacky CGM.getTargetData().getPrefTypeAlignment( 5250198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 5251193326Sed Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); 5252198092Srdivacky CGM.AddUsedGlobal(Entry); 5253193326Sed } 5254198092Srdivacky 5255199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 5256193326Sed} 5257193326Sed 5258193326Sed/// EmitMetaClassRef - Return a Value * of the address of _class_t 5259193326Sed/// meta-data 5260193326Sed/// 5261198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder, 5262198092Srdivacky const ObjCInterfaceDecl *ID) { 5263193326Sed llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; 5264193326Sed if (Entry) 5265199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 5266198092Srdivacky 5267193326Sed std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString()); 5268193326Sed llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName); 5269198092Srdivacky Entry = 5270198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false, 5271193326Sed llvm::GlobalValue::InternalLinkage, 5272198092Srdivacky MetaClassGV, 5273198092Srdivacky "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); 5274193326Sed Entry->setAlignment( 5275198092Srdivacky CGM.getTargetData().getPrefTypeAlignment( 5276198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 5277198092Srdivacky 5278193326Sed Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); 5279198092Srdivacky CGM.AddUsedGlobal(Entry); 5280198092Srdivacky 5281199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 5282193326Sed} 5283193326Sed 5284193326Sed/// GetClass - Return a reference to the class for the given interface 5285193326Sed/// decl. 5286193326Sedllvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder, 5287193326Sed const ObjCInterfaceDecl *ID) { 5288199482Srdivacky if (ID->hasAttr<WeakImportAttr>()) { 5289199482Srdivacky std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5290199482Srdivacky llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 5291199482Srdivacky ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5292199482Srdivacky } 5293199482Srdivacky 5294193326Sed return EmitClassRef(Builder, ID); 5295193326Sed} 5296193326Sed 5297193326Sed/// Generates a message send where the super is the receiver. This is 5298193326Sed/// a message send to self with special delivery semantics indicating 5299193326Sed/// which class's method should be called. 5300193326SedCodeGen::RValue 5301193326SedCGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 5302198092Srdivacky QualType ResultType, 5303198092Srdivacky Selector Sel, 5304198092Srdivacky const ObjCInterfaceDecl *Class, 5305198092Srdivacky bool isCategoryImpl, 5306198092Srdivacky llvm::Value *Receiver, 5307198092Srdivacky bool IsClassMessage, 5308198092Srdivacky const CodeGen::CallArgList &CallArgs, 5309198092Srdivacky const ObjCMethodDecl *Method) { 5310193326Sed // ... 5311193326Sed // Create and init a super structure; this is a (receiver, class) 5312193326Sed // pair we will pass to objc_msgSendSuper. 5313193326Sed llvm::Value *ObjCSuper = 5314193326Sed CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); 5315198092Srdivacky 5316193326Sed llvm::Value *ReceiverAsObject = 5317193326Sed CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); 5318193326Sed CGF.Builder.CreateStore(ReceiverAsObject, 5319193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 5320198092Srdivacky 5321193326Sed // If this is a class message the metaclass is passed as the target. 5322193326Sed llvm::Value *Target; 5323193326Sed if (IsClassMessage) { 5324193326Sed if (isCategoryImpl) { 5325193326Sed // Message sent to "super' in a class method defined in 5326193326Sed // a category implementation. 5327193326Sed Target = EmitClassRef(CGF.Builder, Class); 5328193326Sed Target = CGF.Builder.CreateStructGEP(Target, 0); 5329193326Sed Target = CGF.Builder.CreateLoad(Target); 5330198092Srdivacky } else 5331193326Sed Target = EmitMetaClassRef(CGF.Builder, Class); 5332198092Srdivacky } else 5333193326Sed Target = EmitSuperClassRef(CGF.Builder, Class); 5334198092Srdivacky 5335193326Sed // FIXME: We shouldn't need to do this cast, rectify the ASTContext and 5336193326Sed // ObjCTypes types. 5337193326Sed const llvm::Type *ClassTy = 5338193326Sed CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); 5339193326Sed Target = CGF.Builder.CreateBitCast(Target, ClassTy); 5340193326Sed CGF.Builder.CreateStore(Target, 5341193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 5342198092Srdivacky 5343193326Sed return (LegacyDispatchedSelector(Sel)) 5344198092Srdivacky ? EmitLegacyMessageSend(CGF, ResultType,EmitSelector(CGF.Builder, Sel), 5345198092Srdivacky ObjCSuper, ObjCTypes.SuperPtrCTy, 5346198092Srdivacky true, CallArgs, Method, ObjCTypes) 5347198092Srdivacky : EmitMessageSend(CGF, ResultType, Sel, 5348198092Srdivacky ObjCSuper, ObjCTypes.SuperPtrCTy, 5349198092Srdivacky true, CallArgs); 5350193326Sed} 5351193326Sed 5352198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder, 5353193326Sed Selector Sel) { 5354193326Sed llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; 5355198092Srdivacky 5356193326Sed if (!Entry) { 5357198092Srdivacky llvm::Constant *Casted = 5358198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), 5359198092Srdivacky ObjCTypes.SelectorPtrTy); 5360198092Srdivacky Entry = 5361198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false, 5362198092Srdivacky llvm::GlobalValue::InternalLinkage, 5363198092Srdivacky Casted, "\01L_OBJC_SELECTOR_REFERENCES_"); 5364193326Sed Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip"); 5365198092Srdivacky CGM.AddUsedGlobal(Entry); 5366193326Sed } 5367198092Srdivacky 5368199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 5369193326Sed} 5370193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. 5371198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t) 5372193326Sed/// 5373193326Sedvoid CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 5374198092Srdivacky llvm::Value *src, 5375198092Srdivacky llvm::Value *dst, 5376198092Srdivacky llvm::Value *ivarOffset) { 5377193326Sed const llvm::Type * SrcTy = src->getType(); 5378193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5379193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5380193326Sed assert(Size <= 8 && "does not support size > 8"); 5381193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5382193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5383193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5384193326Sed } 5385193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5386193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5387198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(), 5388198092Srdivacky src, dst, ivarOffset); 5389193326Sed return; 5390193326Sed} 5391193326Sed 5392193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. 5393193326Sed/// objc_assign_strongCast (id src, id *dst) 5394193326Sed/// 5395193326Sedvoid CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( 5396198092Srdivacky CodeGen::CodeGenFunction &CGF, 5397198092Srdivacky llvm::Value *src, llvm::Value *dst) { 5398193326Sed const llvm::Type * SrcTy = src->getType(); 5399193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5400193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5401193326Sed assert(Size <= 8 && "does not support size > 8"); 5402193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5403198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5404193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5405193326Sed } 5406193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5407193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5408193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(), 5409193326Sed src, dst, "weakassign"); 5410193326Sed return; 5411193326Sed} 5412193326Sed 5413198092Srdivackyvoid CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( 5414198092Srdivacky CodeGen::CodeGenFunction &CGF, 5415198092Srdivacky llvm::Value *DestPtr, 5416198092Srdivacky llvm::Value *SrcPtr, 5417198092Srdivacky QualType Ty) { 5418198092Srdivacky // Get size info for this aggregate. 5419198092Srdivacky std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty); 5420198092Srdivacky unsigned long size = TypeInfo.first/8; 5421198092Srdivacky SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); 5422198092Srdivacky DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); 5423198092Srdivacky llvm::Value *N = llvm::ConstantInt::get(ObjCTypes.LongTy, size); 5424198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(), 5425198092Srdivacky DestPtr, SrcPtr, N); 5426198092Srdivacky return; 5427198092Srdivacky} 5428198092Srdivacky 5429193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak 5430193326Sed/// object: objc_read_weak (id *src) 5431193326Sed/// 5432193326Sedllvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( 5433198092Srdivacky CodeGen::CodeGenFunction &CGF, 5434198092Srdivacky llvm::Value *AddrWeakObj) { 5435193326Sed const llvm::Type* DestTy = 5436198092Srdivacky cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); 5437198092Srdivacky AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy); 5438193326Sed llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(), 5439193326Sed AddrWeakObj, "weakread"); 5440193326Sed read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); 5441193326Sed return read_weak; 5442193326Sed} 5443193326Sed 5444193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. 5445193326Sed/// objc_assign_weak (id src, id *dst) 5446193326Sed/// 5447193326Sedvoid CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 5448198092Srdivacky llvm::Value *src, llvm::Value *dst) { 5449193326Sed const llvm::Type * SrcTy = src->getType(); 5450193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5451193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5452193326Sed assert(Size <= 8 && "does not support size > 8"); 5453193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5454193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5455193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5456193326Sed } 5457193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5458193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5459193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(), 5460193326Sed src, dst, "weakassign"); 5461193326Sed return; 5462193326Sed} 5463193326Sed 5464193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. 5465193326Sed/// objc_assign_global (id src, id *dst) 5466193326Sed/// 5467193326Sedvoid CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 5468198092Srdivacky llvm::Value *src, llvm::Value *dst) { 5469193326Sed const llvm::Type * SrcTy = src->getType(); 5470193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5471193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5472193326Sed assert(Size <= 8 && "does not support size > 8"); 5473193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5474193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5475193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5476193326Sed } 5477193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5478193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5479193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(), 5480193326Sed src, dst, "globalassign"); 5481193326Sed return; 5482193326Sed} 5483193326Sed 5484198092Srdivackyvoid 5485193326SedCGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 5486193326Sed const Stmt &S) { 5487193326Sed bool isTry = isa<ObjCAtTryStmt>(S); 5488193326Sed llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); 5489193326Sed llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest(); 5490193326Sed llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); 5491193326Sed llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally"); 5492193326Sed llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); 5493193326Sed llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); 5494193326Sed 5495193326Sed // For @synchronized, call objc_sync_enter(sync.expr). The 5496193326Sed // evaluation of the expression must occur before we enter the 5497193326Sed // @synchronized. We can safely avoid a temp here because jumps into 5498193326Sed // @synchronized are illegal & this will dominate uses. 5499193326Sed llvm::Value *SyncArg = 0; 5500193326Sed if (!isTry) { 5501198092Srdivacky SyncArg = 5502193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 5503193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); 5504193326Sed CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg); 5505193326Sed } 5506193326Sed 5507193326Sed // Push an EH context entry, used for handling rethrows and jumps 5508193326Sed // through finally. 5509193326Sed CGF.PushCleanupBlock(FinallyBlock); 5510193326Sed 5511193326Sed CGF.setInvokeDest(TryHandler); 5512193326Sed 5513193326Sed CGF.EmitBlock(TryBlock); 5514198092Srdivacky CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() 5515198092Srdivacky : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); 5516193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 5517198092Srdivacky 5518193326Sed // Emit the exception handler. 5519193326Sed 5520193326Sed CGF.EmitBlock(TryHandler); 5521193326Sed 5522198092Srdivacky llvm::Value *llvm_eh_exception = 5523193326Sed CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 5524198092Srdivacky llvm::Value *llvm_eh_selector = 5525198092Srdivacky CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 5526198092Srdivacky llvm::Value *llvm_eh_typeid_for = 5527198092Srdivacky CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); 5528193326Sed llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 5529193326Sed llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow"); 5530193326Sed 5531193326Sed llvm::SmallVector<llvm::Value*, 8> SelectorArgs; 5532193326Sed SelectorArgs.push_back(Exc); 5533193326Sed SelectorArgs.push_back(ObjCTypes.getEHPersonalityPtr()); 5534193326Sed 5535193326Sed // Construct the lists of (type, catch body) to handle. 5536193326Sed llvm::SmallVector<std::pair<const ParmVarDecl*, const Stmt*>, 8> Handlers; 5537193326Sed bool HasCatchAll = false; 5538193326Sed if (isTry) { 5539193326Sed if (const ObjCAtCatchStmt* CatchStmt = 5540193326Sed cast<ObjCAtTryStmt>(S).getCatchStmts()) { 5541193326Sed for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) { 5542193326Sed const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); 5543193326Sed Handlers.push_back(std::make_pair(CatchDecl, CatchStmt->getCatchBody())); 5544193326Sed 5545193326Sed // catch(...) always matches. 5546193326Sed if (!CatchDecl) { 5547193326Sed // Use i8* null here to signal this is a catch all, not a cleanup. 5548193326Sed llvm::Value *Null = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 5549193326Sed SelectorArgs.push_back(Null); 5550193326Sed HasCatchAll = true; 5551193326Sed break; 5552193326Sed } 5553193326Sed 5554198092Srdivacky if (CatchDecl->getType()->isObjCIdType() || 5555193326Sed CatchDecl->getType()->isObjCQualifiedIdType()) { 5556198092Srdivacky llvm::Value *IDEHType = 5557193326Sed CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id"); 5558193326Sed if (!IDEHType) 5559198092Srdivacky IDEHType = 5560198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, 5561198092Srdivacky false, 5562193326Sed llvm::GlobalValue::ExternalLinkage, 5563198092Srdivacky 0, "OBJC_EHTYPE_id"); 5564193326Sed SelectorArgs.push_back(IDEHType); 5565198092Srdivacky } else { 5566198092Srdivacky // All other types should be Objective-C interface pointer types. 5567198092Srdivacky const ObjCObjectPointerType *PT = 5568198092Srdivacky CatchDecl->getType()->getAs<ObjCObjectPointerType>(); 5569198092Srdivacky assert(PT && "Invalid @catch type."); 5570198092Srdivacky const ObjCInterfaceType *IT = PT->getInterfaceType(); 5571198092Srdivacky assert(IT && "Invalid @catch type."); 5572198092Srdivacky llvm::Value *EHType = GetInterfaceEHType(IT->getDecl(), false); 5573198092Srdivacky SelectorArgs.push_back(EHType); 5574198092Srdivacky } 5575193326Sed } 5576193326Sed } 5577193326Sed } 5578193326Sed 5579193326Sed // We use a cleanup unless there was already a catch all. 5580193326Sed if (!HasCatchAll) { 5581198092Srdivacky // Even though this is a cleanup, treat it as a catch all to avoid the C++ 5582198092Srdivacky // personality behavior of terminating the process if only cleanups are 5583198092Srdivacky // found in the exception handling stack. 5584198092Srdivacky SelectorArgs.push_back(llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy)); 5585193326Sed Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0)); 5586193326Sed } 5587198092Srdivacky 5588198092Srdivacky llvm::Value *Selector = 5589198092Srdivacky CGF.Builder.CreateCall(llvm_eh_selector, 5590193326Sed SelectorArgs.begin(), SelectorArgs.end(), 5591193326Sed "selector"); 5592193326Sed for (unsigned i = 0, e = Handlers.size(); i != e; ++i) { 5593193326Sed const ParmVarDecl *CatchParam = Handlers[i].first; 5594193326Sed const Stmt *CatchBody = Handlers[i].second; 5595193326Sed 5596193326Sed llvm::BasicBlock *Next = 0; 5597193326Sed 5598193326Sed // The last handler always matches. 5599193326Sed if (i + 1 != e) { 5600193326Sed assert(CatchParam && "Only last handler can be a catch all."); 5601193326Sed 5602193326Sed llvm::BasicBlock *Match = CGF.createBasicBlock("match"); 5603193326Sed Next = CGF.createBasicBlock("catch.next"); 5604198092Srdivacky llvm::Value *Id = 5605198092Srdivacky CGF.Builder.CreateCall(llvm_eh_typeid_for, 5606193326Sed CGF.Builder.CreateBitCast(SelectorArgs[i+2], 5607193326Sed ObjCTypes.Int8PtrTy)); 5608193326Sed CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(Selector, Id), 5609193326Sed Match, Next); 5610193326Sed 5611193326Sed CGF.EmitBlock(Match); 5612193326Sed } 5613198092Srdivacky 5614193326Sed if (CatchBody) { 5615193326Sed llvm::BasicBlock *MatchEnd = CGF.createBasicBlock("match.end"); 5616193326Sed llvm::BasicBlock *MatchHandler = CGF.createBasicBlock("match.handler"); 5617193326Sed 5618193326Sed // Cleanups must call objc_end_catch. 5619198092Srdivacky // 5620193326Sed // FIXME: It seems incorrect for objc_begin_catch to be inside this 5621193326Sed // context, but this matches gcc. 5622193326Sed CGF.PushCleanupBlock(MatchEnd); 5623193326Sed CGF.setInvokeDest(MatchHandler); 5624198092Srdivacky 5625198092Srdivacky llvm::Value *ExcObject = 5626193326Sed CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), Exc); 5627193326Sed 5628193326Sed // Bind the catch parameter if it exists. 5629193326Sed if (CatchParam) { 5630198092Srdivacky ExcObject = 5631198092Srdivacky CGF.Builder.CreateBitCast(ExcObject, 5632193326Sed CGF.ConvertType(CatchParam->getType())); 5633193326Sed // CatchParam is a ParmVarDecl because of the grammar 5634193326Sed // construction used to handle this, but for codegen purposes 5635193326Sed // we treat this as a local decl. 5636193326Sed CGF.EmitLocalBlockVarDecl(*CatchParam); 5637193326Sed CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(CatchParam)); 5638193326Sed } 5639193326Sed 5640193326Sed CGF.ObjCEHValueStack.push_back(ExcObject); 5641193326Sed CGF.EmitStmt(CatchBody); 5642193326Sed CGF.ObjCEHValueStack.pop_back(); 5643193326Sed 5644193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 5645193326Sed 5646193326Sed CGF.EmitBlock(MatchHandler); 5647193326Sed 5648193326Sed llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 5649193326Sed // We are required to emit this call to satisfy LLVM, even 5650193326Sed // though we don't use the result. 5651193326Sed llvm::SmallVector<llvm::Value*, 8> Args; 5652193326Sed Args.push_back(Exc); 5653193326Sed Args.push_back(ObjCTypes.getEHPersonalityPtr()); 5654198092Srdivacky Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 5655193326Sed 0)); 5656198092Srdivacky CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end()); 5657193326Sed CGF.Builder.CreateStore(Exc, RethrowPtr); 5658193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 5659193326Sed 5660193326Sed CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); 5661198092Srdivacky 5662193326Sed CGF.EmitBlock(MatchEnd); 5663193326Sed 5664193326Sed // Unfortunately, we also have to generate another EH frame here 5665193326Sed // in case this throws. 5666198092Srdivacky llvm::BasicBlock *MatchEndHandler = 5667193326Sed CGF.createBasicBlock("match.end.handler"); 5668193326Sed llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); 5669198092Srdivacky CGF.Builder.CreateInvoke(ObjCTypes.getObjCEndCatchFn(), 5670193326Sed Cont, MatchEndHandler, 5671193326Sed Args.begin(), Args.begin()); 5672193326Sed 5673193326Sed CGF.EmitBlock(Cont); 5674193326Sed if (Info.SwitchBlock) 5675193326Sed CGF.EmitBlock(Info.SwitchBlock); 5676193326Sed if (Info.EndBlock) 5677193326Sed CGF.EmitBlock(Info.EndBlock); 5678193326Sed 5679193326Sed CGF.EmitBlock(MatchEndHandler); 5680193326Sed Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 5681193326Sed // We are required to emit this call to satisfy LLVM, even 5682193326Sed // though we don't use the result. 5683193326Sed Args.clear(); 5684193326Sed Args.push_back(Exc); 5685193326Sed Args.push_back(ObjCTypes.getEHPersonalityPtr()); 5686198092Srdivacky Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 5687193326Sed 0)); 5688198092Srdivacky CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end()); 5689193326Sed CGF.Builder.CreateStore(Exc, RethrowPtr); 5690193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 5691193326Sed 5692193326Sed if (Next) 5693193326Sed CGF.EmitBlock(Next); 5694193326Sed } else { 5695193326Sed assert(!Next && "catchup should be last handler."); 5696193326Sed 5697193326Sed CGF.Builder.CreateStore(Exc, RethrowPtr); 5698193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 5699193326Sed } 5700193326Sed } 5701193326Sed 5702193326Sed // Pop the cleanup entry, the @finally is outside this cleanup 5703193326Sed // scope. 5704193326Sed CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); 5705193326Sed CGF.setInvokeDest(PrevLandingPad); 5706193326Sed 5707193326Sed CGF.EmitBlock(FinallyBlock); 5708193326Sed 5709193326Sed if (isTry) { 5710198092Srdivacky if (const ObjCAtFinallyStmt* FinallyStmt = 5711193326Sed cast<ObjCAtTryStmt>(S).getFinallyStmt()) 5712193326Sed CGF.EmitStmt(FinallyStmt->getFinallyBody()); 5713193326Sed } else { 5714193326Sed // Emit 'objc_sync_exit(expr)' as finally's sole statement for 5715193326Sed // @synchronized. 5716193326Sed CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg); 5717193326Sed } 5718193326Sed 5719193326Sed if (Info.SwitchBlock) 5720193326Sed CGF.EmitBlock(Info.SwitchBlock); 5721193326Sed if (Info.EndBlock) 5722193326Sed CGF.EmitBlock(Info.EndBlock); 5723193326Sed 5724193326Sed // Branch around the rethrow code. 5725193326Sed CGF.EmitBranch(FinallyEnd); 5726193326Sed 5727193326Sed CGF.EmitBlock(FinallyRethrow); 5728198092Srdivacky CGF.Builder.CreateCall(ObjCTypes.getUnwindResumeOrRethrowFn(), 5729193326Sed CGF.Builder.CreateLoad(RethrowPtr)); 5730193326Sed CGF.Builder.CreateUnreachable(); 5731198092Srdivacky 5732193326Sed CGF.EmitBlock(FinallyEnd); 5733193326Sed} 5734193326Sed 5735193326Sed/// EmitThrowStmt - Generate code for a throw statement. 5736193326Sedvoid CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 5737193326Sed const ObjCAtThrowStmt &S) { 5738198092Srdivacky llvm::Value *Exception; 5739193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 5740193326Sed Exception = CGF.EmitScalarExpr(ThrowExpr); 5741193326Sed } else { 5742198092Srdivacky assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && 5743193326Sed "Unexpected rethrow outside @catch block."); 5744193326Sed Exception = CGF.ObjCEHValueStack.back(); 5745193326Sed } 5746193326Sed 5747198092Srdivacky llvm::Value *ExceptionAsObject = 5748193326Sed CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp"); 5749193326Sed llvm::BasicBlock *InvokeDest = CGF.getInvokeDest(); 5750193326Sed if (InvokeDest) { 5751193326Sed llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); 5752193326Sed CGF.Builder.CreateInvoke(ObjCTypes.getExceptionThrowFn(), 5753193326Sed Cont, InvokeDest, 5754193326Sed &ExceptionAsObject, &ExceptionAsObject + 1); 5755193326Sed CGF.EmitBlock(Cont); 5756193326Sed } else 5757198092Srdivacky CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject); 5758193326Sed CGF.Builder.CreateUnreachable(); 5759193326Sed 5760193326Sed // Clear the insertion point to indicate we are in unreachable code. 5761193326Sed CGF.Builder.ClearInsertionPoint(); 5762193326Sed} 5763193326Sed 5764193326Sedllvm::Value * 5765198092SrdivackyCGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, 5766193326Sed bool ForDefinition) { 5767193326Sed llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()]; 5768193326Sed 5769193326Sed // If we don't need a definition, return the entry if found or check 5770193326Sed // if we use an external reference. 5771193326Sed if (!ForDefinition) { 5772193326Sed if (Entry) 5773193326Sed return Entry; 5774193326Sed 5775193326Sed // If this type (or a super class) has the __objc_exception__ 5776193326Sed // attribute, emit an external reference. 5777194613Sed if (hasObjCExceptionAttribute(CGM.getContext(), ID)) 5778198092Srdivacky return Entry = 5779198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, 5780193326Sed llvm::GlobalValue::ExternalLinkage, 5781198092Srdivacky 0, 5782198398Srdivacky ("OBJC_EHTYPE_$_" + 5783198092Srdivacky ID->getIdentifier()->getName())); 5784193326Sed } 5785198092Srdivacky 5786193326Sed // Otherwise we need to either make a new entry or fill in the 5787193326Sed // initializer. 5788193326Sed assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition"); 5789193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5790193326Sed std::string VTableName = "objc_ehtype_vtable"; 5791198092Srdivacky llvm::GlobalVariable *VTableGV = 5792193326Sed CGM.getModule().getGlobalVariable(VTableName); 5793193326Sed if (!VTableGV) 5794198092Srdivacky VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, 5795198092Srdivacky false, 5796193326Sed llvm::GlobalValue::ExternalLinkage, 5797198092Srdivacky 0, VTableName); 5798193326Sed 5799198092Srdivacky llvm::Value *VTableIdx = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2); 5800193326Sed 5801193326Sed std::vector<llvm::Constant*> Values(3); 5802193326Sed Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1); 5803193326Sed Values[1] = GetClassName(ID->getIdentifier()); 5804193326Sed Values[2] = GetClassGlobal(ClassName); 5805198092Srdivacky llvm::Constant *Init = 5806198092Srdivacky llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values); 5807193326Sed 5808193326Sed if (Entry) { 5809193326Sed Entry->setInitializer(Init); 5810193326Sed } else { 5811198092Srdivacky Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, 5812193326Sed llvm::GlobalValue::WeakAnyLinkage, 5813198092Srdivacky Init, 5814198398Srdivacky ("OBJC_EHTYPE_$_" + 5815198092Srdivacky ID->getIdentifier()->getName())); 5816193326Sed } 5817193326Sed 5818193326Sed if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden) 5819193326Sed Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); 5820193326Sed Entry->setAlignment(8); 5821193326Sed 5822193326Sed if (ForDefinition) { 5823193326Sed Entry->setSection("__DATA,__objc_const"); 5824193326Sed Entry->setLinkage(llvm::GlobalValue::ExternalLinkage); 5825193326Sed } else { 5826193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 5827193326Sed } 5828193326Sed 5829193326Sed return Entry; 5830193326Sed} 5831198092Srdivacky 5832193326Sed/* *** */ 5833193326Sed 5834193326SedCodeGen::CGObjCRuntime * 5835193326SedCodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) { 5836193326Sed return new CGObjCMac(CGM); 5837193326Sed} 5838193326Sed 5839193326SedCodeGen::CGObjCRuntime * 5840193326SedCodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) { 5841193326Sed return new CGObjCNonFragileABIMac(CGM); 5842193326Sed} 5843