CGObjCMac.cpp revision 218893
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 16206084Srdivacky#include "CGRecordLayout.h" 17193326Sed#include "CodeGenModule.h" 18193326Sed#include "CodeGenFunction.h" 19218893Sdim#include "CGBlocks.h" 20218893Sdim#include "CGCleanup.h" 21193326Sed#include "clang/AST/ASTContext.h" 22193326Sed#include "clang/AST/Decl.h" 23193326Sed#include "clang/AST/DeclObjC.h" 24193326Sed#include "clang/AST/RecordLayout.h" 25193326Sed#include "clang/AST/StmtObjC.h" 26193326Sed#include "clang/Basic/LangOptions.h" 27210299Sed#include "clang/Frontend/CodeGenOptions.h" 28193326Sed 29212904Sdim#include "llvm/InlineAsm.h" 30212904Sdim#include "llvm/IntrinsicInst.h" 31198092Srdivacky#include "llvm/LLVMContext.h" 32193326Sed#include "llvm/Module.h" 33193326Sed#include "llvm/ADT/DenseSet.h" 34198092Srdivacky#include "llvm/ADT/SetVector.h" 35198092Srdivacky#include "llvm/ADT/SmallString.h" 36200583Srdivacky#include "llvm/ADT/SmallPtrSet.h" 37210299Sed#include "llvm/Support/CallSite.h" 38198092Srdivacky#include "llvm/Support/raw_ostream.h" 39193326Sed#include "llvm/Target/TargetData.h" 40198092Srdivacky#include <cstdio> 41193326Sed 42193326Sedusing namespace clang; 43193326Sedusing namespace CodeGen; 44193326Sed 45193326Sed// Common CGObjCRuntime functions, these don't belong here, but they 46193326Sed// don't belong in CGObjCRuntime either so we will live with it for 47193326Sed// now. 48193326Sed 49193326Sedstatic uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM, 50193326Sed const ObjCInterfaceDecl *OID, 51193326Sed const ObjCImplementationDecl *ID, 52193326Sed const ObjCIvarDecl *Ivar) { 53206125Srdivacky const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); 54193326Sed 55206125Srdivacky // FIXME: We should eliminate the need to have ObjCImplementationDecl passed 56206125Srdivacky // in here; it should never be necessary because that should be the lexical 57206125Srdivacky // decl context for the ivar. 58206125Srdivacky 59193326Sed // If we know have an implementation (and the ivar is in it) then 60193326Sed // look up in the implementation layout. 61198092Srdivacky const ASTRecordLayout *RL; 62193326Sed if (ID && ID->getClassInterface() == Container) 63193326Sed RL = &CGM.getContext().getASTObjCImplementationLayout(ID); 64193326Sed else 65193326Sed RL = &CGM.getContext().getASTObjCInterfaceLayout(Container); 66206125Srdivacky 67206125Srdivacky // Compute field index. 68206125Srdivacky // 69206125Srdivacky // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is 70206125Srdivacky // implemented. This should be fixed to get the information from the layout 71206125Srdivacky // directly. 72206125Srdivacky unsigned Index = 0; 73206125Srdivacky llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; 74206125Srdivacky CGM.getContext().ShallowCollectObjCIvars(Container, Ivars); 75206125Srdivacky for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { 76206125Srdivacky if (Ivar == Ivars[k]) 77206125Srdivacky break; 78206125Srdivacky ++Index; 79206125Srdivacky } 80206125Srdivacky assert(Index != Ivars.size() && "Ivar is not inside container!"); 81218893Sdim assert(Index < RL->getFieldCount() && "Ivar is not inside record layout!"); 82206125Srdivacky 83193326Sed return RL->getFieldOffset(Index); 84193326Sed} 85193326Sed 86193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, 87193326Sed const ObjCInterfaceDecl *OID, 88193326Sed const ObjCIvarDecl *Ivar) { 89193326Sed return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8; 90193326Sed} 91193326Sed 92193326Seduint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM, 93193326Sed const ObjCImplementationDecl *OID, 94193326Sed const ObjCIvarDecl *Ivar) { 95193326Sed return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8; 96193326Sed} 97193326Sed 98193326SedLValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, 99193326Sed const ObjCInterfaceDecl *OID, 100193326Sed llvm::Value *BaseValue, 101193326Sed const ObjCIvarDecl *Ivar, 102193326Sed unsigned CVRQualifiers, 103193326Sed llvm::Value *Offset) { 104193326Sed // Compute (type*) ( (char *) BaseValue + Offset) 105198092Srdivacky const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 106193326Sed QualType IvarTy = Ivar->getType(); 107193326Sed const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy); 108193326Sed llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr); 109193326Sed V = CGF.Builder.CreateGEP(V, Offset, "add.ptr"); 110193326Sed V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy)); 111198092Srdivacky 112212904Sdim if (!Ivar->isBitField()) { 113212904Sdim LValue LV = CGF.MakeAddrLValue(V, IvarTy); 114212904Sdim LV.getQuals().addCVRQualifiers(CVRQualifiers); 115212904Sdim return LV; 116212904Sdim } 117198092Srdivacky 118212904Sdim // We need to compute an access strategy for this bit-field. We are given the 119212904Sdim // offset to the first byte in the bit-field, the sub-byte offset is taken 120212904Sdim // from the original layout. We reuse the normal bit-field access strategy by 121212904Sdim // treating this as an access to a struct where the bit-field is in byte 0, 122212904Sdim // and adjust the containing type size as appropriate. 123212904Sdim // 124212904Sdim // FIXME: Note that currently we make a very conservative estimate of the 125212904Sdim // alignment of the bit-field, because (a) it is not clear what guarantees the 126212904Sdim // runtime makes us, and (b) we don't have a way to specify that the struct is 127212904Sdim // at an alignment plus offset. 128212904Sdim // 129212904Sdim // Note, there is a subtle invariant here: we can only call this routine on 130212904Sdim // non-synthesized ivars but we may be called for synthesized ivars. However, 131212904Sdim // a synthesized ivar can never be a bit-field, so this is safe. 132212904Sdim const ASTRecordLayout &RL = 133212904Sdim CGF.CGM.getContext().getASTObjCInterfaceLayout(OID); 134218893Sdim uint64_t TypeSizeInBits = CGF.CGM.getContext().toBits(RL.getSize()); 135212904Sdim uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar); 136212904Sdim uint64_t BitOffset = FieldBitOffset % 8; 137212904Sdim uint64_t ContainingTypeAlign = 8; 138212904Sdim uint64_t ContainingTypeSize = TypeSizeInBits - (FieldBitOffset - BitOffset); 139206275Srdivacky uint64_t BitFieldSize = 140206275Srdivacky Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue(); 141193326Sed 142206275Srdivacky // Allocate a new CGBitFieldInfo object to describe this access. 143206275Srdivacky // 144206275Srdivacky // FIXME: This is incredibly wasteful, these should be uniqued or part of some 145206275Srdivacky // layout object. However, this is blocked on other cleanups to the 146206275Srdivacky // Objective-C code, so for now we just live with allocating a bunch of these 147206275Srdivacky // objects. 148212904Sdim CGBitFieldInfo *Info = new (CGF.CGM.getContext()) CGBitFieldInfo( 149212904Sdim CGBitFieldInfo::MakeInfo(CGF.CGM.getTypes(), Ivar, BitOffset, BitFieldSize, 150212904Sdim ContainingTypeSize, ContainingTypeAlign)); 151207619Srdivacky 152212904Sdim return LValue::MakeBitfield(V, *Info, 153212904Sdim IvarTy.getCVRQualifiers() | CVRQualifiers); 154193326Sed} 155193326Sed 156193326Sed/// 157193326Sed 158193326Sednamespace { 159193326Sed 160198092Srdivackytypedef std::vector<llvm::Constant*> ConstantVector; 161193326Sed 162198092Srdivacky// FIXME: We should find a nicer way to make the labels for metadata, string 163198092Srdivacky// concatenation is lame. 164193326Sed 165193326Sedclass ObjCCommonTypesHelper { 166198092Srdivackyprotected: 167198092Srdivacky llvm::LLVMContext &VMContext; 168198092Srdivacky 169193326Sedprivate: 170193326Sed llvm::Constant *getMessageSendFn() const { 171193326Sed // id objc_msgSend (id, SEL, ...) 172193326Sed std::vector<const llvm::Type*> Params; 173193326Sed Params.push_back(ObjectPtrTy); 174193326Sed Params.push_back(SelectorPtrTy); 175193326Sed return 176198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 177198092Srdivacky Params, true), 178198092Srdivacky "objc_msgSend"); 179193326Sed } 180198092Srdivacky 181193326Sed llvm::Constant *getMessageSendStretFn() const { 182193326Sed // id objc_msgSend_stret (id, SEL, ...) 183193326Sed std::vector<const llvm::Type*> Params; 184193326Sed Params.push_back(ObjectPtrTy); 185193326Sed Params.push_back(SelectorPtrTy); 186193326Sed return 187198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 188198092Srdivacky Params, true), 189198092Srdivacky "objc_msgSend_stret"); 190198092Srdivacky 191193326Sed } 192198092Srdivacky 193193326Sed llvm::Constant *getMessageSendFpretFn() const { 194193326Sed // FIXME: This should be long double on x86_64? 195193326Sed // [double | long double] objc_msgSend_fpret(id self, SEL op, ...) 196193326Sed std::vector<const llvm::Type*> Params; 197193326Sed Params.push_back(ObjectPtrTy); 198193326Sed Params.push_back(SelectorPtrTy); 199193326Sed return 200198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get( 201198092Srdivacky llvm::Type::getDoubleTy(VMContext), 202198092Srdivacky Params, 203198092Srdivacky true), 204198092Srdivacky "objc_msgSend_fpret"); 205198092Srdivacky 206193326Sed } 207198092Srdivacky 208193326Sed llvm::Constant *getMessageSendSuperFn() const { 209193326Sed // id objc_msgSendSuper(struct objc_super *super, SEL op, ...) 210193326Sed const char *SuperName = "objc_msgSendSuper"; 211193326Sed std::vector<const llvm::Type*> Params; 212193326Sed Params.push_back(SuperPtrTy); 213193326Sed Params.push_back(SelectorPtrTy); 214193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 215193326Sed Params, true), 216193326Sed SuperName); 217193326Sed } 218198092Srdivacky 219193326Sed llvm::Constant *getMessageSendSuperFn2() const { 220193326Sed // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...) 221193326Sed const char *SuperName = "objc_msgSendSuper2"; 222193326Sed std::vector<const llvm::Type*> Params; 223193326Sed Params.push_back(SuperPtrTy); 224193326Sed Params.push_back(SelectorPtrTy); 225193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 226193326Sed Params, true), 227193326Sed SuperName); 228193326Sed } 229198092Srdivacky 230193326Sed llvm::Constant *getMessageSendSuperStretFn() const { 231193326Sed // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super, 232193326Sed // SEL op, ...) 233193326Sed std::vector<const llvm::Type*> Params; 234193326Sed Params.push_back(Int8PtrTy); 235193326Sed Params.push_back(SuperPtrTy); 236193326Sed Params.push_back(SelectorPtrTy); 237198092Srdivacky return CGM.CreateRuntimeFunction( 238198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 239198092Srdivacky Params, true), 240198092Srdivacky "objc_msgSendSuper_stret"); 241193326Sed } 242198092Srdivacky 243193326Sed llvm::Constant *getMessageSendSuperStretFn2() const { 244193326Sed // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super, 245193326Sed // SEL op, ...) 246193326Sed std::vector<const llvm::Type*> Params; 247193326Sed Params.push_back(Int8PtrTy); 248193326Sed Params.push_back(SuperPtrTy); 249193326Sed Params.push_back(SelectorPtrTy); 250198092Srdivacky return CGM.CreateRuntimeFunction( 251198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 252198092Srdivacky Params, true), 253198092Srdivacky "objc_msgSendSuper2_stret"); 254193326Sed } 255198092Srdivacky 256193326Sed llvm::Constant *getMessageSendSuperFpretFn() const { 257193326Sed // There is no objc_msgSendSuper_fpret? How can that work? 258193326Sed return getMessageSendSuperFn(); 259193326Sed } 260198092Srdivacky 261193326Sed llvm::Constant *getMessageSendSuperFpretFn2() const { 262193326Sed // There is no objc_msgSendSuper_fpret? How can that work? 263193326Sed return getMessageSendSuperFn2(); 264193326Sed } 265198092Srdivacky 266193326Sedprotected: 267193326Sed CodeGen::CodeGenModule &CGM; 268198092Srdivacky 269193326Sedpublic: 270193326Sed const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy; 271193326Sed const llvm::Type *Int8PtrTy; 272198092Srdivacky 273193326Sed /// ObjectPtrTy - LLVM type for object handles (typeof(id)) 274193326Sed const llvm::Type *ObjectPtrTy; 275198092Srdivacky 276193326Sed /// PtrObjectPtrTy - LLVM type for id * 277193326Sed const llvm::Type *PtrObjectPtrTy; 278198092Srdivacky 279193326Sed /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL)) 280193326Sed const llvm::Type *SelectorPtrTy; 281193326Sed /// ProtocolPtrTy - LLVM type for external protocol handles 282193326Sed /// (typeof(Protocol)) 283193326Sed const llvm::Type *ExternalProtocolPtrTy; 284198092Srdivacky 285193326Sed // SuperCTy - clang type for struct objc_super. 286193326Sed QualType SuperCTy; 287193326Sed // SuperPtrCTy - clang type for struct objc_super *. 288193326Sed QualType SuperPtrCTy; 289198092Srdivacky 290193326Sed /// SuperTy - LLVM type for struct objc_super. 291193326Sed const llvm::StructType *SuperTy; 292193326Sed /// SuperPtrTy - LLVM type for struct objc_super *. 293193326Sed const llvm::Type *SuperPtrTy; 294198092Srdivacky 295193326Sed /// PropertyTy - LLVM type for struct objc_property (struct _prop_t 296193326Sed /// in GCC parlance). 297193326Sed const llvm::StructType *PropertyTy; 298198092Srdivacky 299193326Sed /// PropertyListTy - LLVM type for struct objc_property_list 300193326Sed /// (_prop_list_t in GCC parlance). 301193326Sed const llvm::StructType *PropertyListTy; 302193326Sed /// PropertyListPtrTy - LLVM type for struct objc_property_list*. 303193326Sed const llvm::Type *PropertyListPtrTy; 304198092Srdivacky 305193326Sed // MethodTy - LLVM type for struct objc_method. 306193326Sed const llvm::StructType *MethodTy; 307198092Srdivacky 308193326Sed /// CacheTy - LLVM type for struct objc_cache. 309193326Sed const llvm::Type *CacheTy; 310193326Sed /// CachePtrTy - LLVM type for struct objc_cache *. 311193326Sed const llvm::Type *CachePtrTy; 312198092Srdivacky 313193326Sed llvm::Constant *getGetPropertyFn() { 314193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 315193326Sed ASTContext &Ctx = CGM.getContext(); 316193326Sed // id objc_getProperty (id, SEL, ptrdiff_t, bool) 317204643Srdivacky llvm::SmallVector<CanQualType,4> Params; 318204643Srdivacky CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); 319204643Srdivacky CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); 320193326Sed Params.push_back(IdType); 321193326Sed Params.push_back(SelType); 322193326Sed Params.push_back(Ctx.LongTy); 323193326Sed Params.push_back(Ctx.BoolTy); 324193326Sed const llvm::FunctionType *FTy = 325203955Srdivacky Types.GetFunctionType(Types.getFunctionInfo(IdType, Params, 326206084Srdivacky FunctionType::ExtInfo()), 327206084Srdivacky false); 328193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_getProperty"); 329193326Sed } 330198092Srdivacky 331193326Sed llvm::Constant *getSetPropertyFn() { 332193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 333193326Sed ASTContext &Ctx = CGM.getContext(); 334193326Sed // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) 335204643Srdivacky llvm::SmallVector<CanQualType,6> Params; 336204643Srdivacky CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); 337204643Srdivacky CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); 338193326Sed Params.push_back(IdType); 339193326Sed Params.push_back(SelType); 340193326Sed Params.push_back(Ctx.LongTy); 341193326Sed Params.push_back(IdType); 342193326Sed Params.push_back(Ctx.BoolTy); 343193326Sed Params.push_back(Ctx.BoolTy); 344193326Sed const llvm::FunctionType *FTy = 345203955Srdivacky Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params, 346206084Srdivacky FunctionType::ExtInfo()), 347206084Srdivacky false); 348193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_setProperty"); 349193326Sed } 350198092Srdivacky 351207619Srdivacky 352207619Srdivacky llvm::Constant *getCopyStructFn() { 353207619Srdivacky CodeGen::CodeGenTypes &Types = CGM.getTypes(); 354207619Srdivacky ASTContext &Ctx = CGM.getContext(); 355207619Srdivacky // void objc_copyStruct (void *, const void *, size_t, bool, bool) 356207619Srdivacky llvm::SmallVector<CanQualType,5> Params; 357207619Srdivacky Params.push_back(Ctx.VoidPtrTy); 358207619Srdivacky Params.push_back(Ctx.VoidPtrTy); 359207619Srdivacky Params.push_back(Ctx.LongTy); 360207619Srdivacky Params.push_back(Ctx.BoolTy); 361207619Srdivacky Params.push_back(Ctx.BoolTy); 362207619Srdivacky const llvm::FunctionType *FTy = 363207619Srdivacky Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params, 364207619Srdivacky FunctionType::ExtInfo()), 365207619Srdivacky false); 366207619Srdivacky return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct"); 367207619Srdivacky } 368207619Srdivacky 369193326Sed llvm::Constant *getEnumerationMutationFn() { 370198092Srdivacky CodeGen::CodeGenTypes &Types = CGM.getTypes(); 371198092Srdivacky ASTContext &Ctx = CGM.getContext(); 372193326Sed // void objc_enumerationMutation (id) 373204643Srdivacky llvm::SmallVector<CanQualType,1> Params; 374204643Srdivacky Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType())); 375198092Srdivacky const llvm::FunctionType *FTy = 376203955Srdivacky Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params, 377206084Srdivacky FunctionType::ExtInfo()), 378206084Srdivacky false); 379193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); 380193326Sed } 381198092Srdivacky 382193326Sed /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function. 383193326Sed llvm::Constant *getGcReadWeakFn() { 384193326Sed // id objc_read_weak (id *) 385193326Sed std::vector<const llvm::Type*> Args; 386193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 387198092Srdivacky llvm::FunctionType *FTy = 388198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 389193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); 390198092Srdivacky } 391198092Srdivacky 392193326Sed /// GcAssignWeakFn -- LLVM objc_assign_weak function. 393193326Sed llvm::Constant *getGcAssignWeakFn() { 394193326Sed // id objc_assign_weak (id, id *) 395193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 396193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 397193326Sed llvm::FunctionType *FTy = 398193326Sed llvm::FunctionType::get(ObjectPtrTy, Args, false); 399193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); 400193326Sed } 401198092Srdivacky 402193326Sed /// GcAssignGlobalFn -- LLVM objc_assign_global function. 403193326Sed llvm::Constant *getGcAssignGlobalFn() { 404193326Sed // id objc_assign_global(id, id *) 405193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 406193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 407198092Srdivacky llvm::FunctionType *FTy = 408198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 409193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); 410193326Sed } 411198092Srdivacky 412212904Sdim /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function. 413212904Sdim llvm::Constant *getGcAssignThreadLocalFn() { 414212904Sdim // id objc_assign_threadlocal(id src, id * dest) 415212904Sdim std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 416212904Sdim Args.push_back(ObjectPtrTy->getPointerTo()); 417212904Sdim llvm::FunctionType *FTy = 418212904Sdim llvm::FunctionType::get(ObjectPtrTy, Args, false); 419212904Sdim return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal"); 420212904Sdim } 421212904Sdim 422193326Sed /// GcAssignIvarFn -- LLVM objc_assign_ivar function. 423193326Sed llvm::Constant *getGcAssignIvarFn() { 424198092Srdivacky // id objc_assign_ivar(id, id *, ptrdiff_t) 425193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 426193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 427198092Srdivacky Args.push_back(LongTy); 428198092Srdivacky llvm::FunctionType *FTy = 429198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 430193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); 431193326Sed } 432198092Srdivacky 433198092Srdivacky /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function. 434198092Srdivacky llvm::Constant *GcMemmoveCollectableFn() { 435198092Srdivacky // void *objc_memmove_collectable(void *dst, const void *src, size_t size) 436198092Srdivacky std::vector<const llvm::Type*> Args(1, Int8PtrTy); 437198092Srdivacky Args.push_back(Int8PtrTy); 438198092Srdivacky Args.push_back(LongTy); 439198092Srdivacky llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false); 440198092Srdivacky return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); 441198092Srdivacky } 442198092Srdivacky 443193326Sed /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function. 444193326Sed llvm::Constant *getGcAssignStrongCastFn() { 445212904Sdim // id objc_assign_strongCast(id, id *) 446193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 447193326Sed Args.push_back(ObjectPtrTy->getPointerTo()); 448198092Srdivacky llvm::FunctionType *FTy = 449198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Args, false); 450193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); 451193326Sed } 452193326Sed 453193326Sed /// ExceptionThrowFn - LLVM objc_exception_throw function. 454193326Sed llvm::Constant *getExceptionThrowFn() { 455193326Sed // void objc_exception_throw(id) 456193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 457193326Sed llvm::FunctionType *FTy = 458198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 459193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); 460193326Sed } 461198092Srdivacky 462210299Sed /// ExceptionRethrowFn - LLVM objc_exception_rethrow function. 463210299Sed llvm::Constant *getExceptionRethrowFn() { 464210299Sed // void objc_exception_rethrow(void) 465210299Sed std::vector<const llvm::Type*> Args; 466210299Sed llvm::FunctionType *FTy = 467218893Sdim llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 468210299Sed return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow"); 469210299Sed } 470210299Sed 471193326Sed /// SyncEnterFn - LLVM object_sync_enter function. 472193326Sed llvm::Constant *getSyncEnterFn() { 473193326Sed // void objc_sync_enter (id) 474193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 475193326Sed llvm::FunctionType *FTy = 476198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 477193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); 478193326Sed } 479198092Srdivacky 480193326Sed /// SyncExitFn - LLVM object_sync_exit function. 481193326Sed llvm::Constant *getSyncExitFn() { 482193326Sed // void objc_sync_exit (id) 483193326Sed std::vector<const llvm::Type*> Args(1, ObjectPtrTy); 484193326Sed llvm::FunctionType *FTy = 485198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 486193326Sed return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); 487193326Sed } 488198092Srdivacky 489193326Sed llvm::Constant *getSendFn(bool IsSuper) const { 490193326Sed return IsSuper ? getMessageSendSuperFn() : getMessageSendFn(); 491193326Sed } 492198092Srdivacky 493193326Sed llvm::Constant *getSendFn2(bool IsSuper) const { 494193326Sed return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn(); 495193326Sed } 496198092Srdivacky 497193326Sed llvm::Constant *getSendStretFn(bool IsSuper) const { 498193326Sed return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn(); 499193326Sed } 500198092Srdivacky 501193326Sed llvm::Constant *getSendStretFn2(bool IsSuper) const { 502193326Sed return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn(); 503193326Sed } 504198092Srdivacky 505193326Sed llvm::Constant *getSendFpretFn(bool IsSuper) const { 506193326Sed return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn(); 507193326Sed } 508198092Srdivacky 509193326Sed llvm::Constant *getSendFpretFn2(bool IsSuper) const { 510193326Sed return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn(); 511193326Sed } 512198092Srdivacky 513193326Sed ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm); 514193326Sed ~ObjCCommonTypesHelper(){} 515193326Sed}; 516193326Sed 517193326Sed/// ObjCTypesHelper - Helper class that encapsulates lazy 518193326Sed/// construction of varies types used during ObjC generation. 519193326Sedclass ObjCTypesHelper : public ObjCCommonTypesHelper { 520193326Sedpublic: 521193326Sed /// SymtabTy - LLVM type for struct objc_symtab. 522193326Sed const llvm::StructType *SymtabTy; 523193326Sed /// SymtabPtrTy - LLVM type for struct objc_symtab *. 524193326Sed const llvm::Type *SymtabPtrTy; 525193326Sed /// ModuleTy - LLVM type for struct objc_module. 526193326Sed const llvm::StructType *ModuleTy; 527193326Sed 528193326Sed /// ProtocolTy - LLVM type for struct objc_protocol. 529193326Sed const llvm::StructType *ProtocolTy; 530193326Sed /// ProtocolPtrTy - LLVM type for struct objc_protocol *. 531193326Sed const llvm::Type *ProtocolPtrTy; 532193326Sed /// ProtocolExtensionTy - LLVM type for struct 533193326Sed /// objc_protocol_extension. 534193326Sed const llvm::StructType *ProtocolExtensionTy; 535193326Sed /// ProtocolExtensionTy - LLVM type for struct 536193326Sed /// objc_protocol_extension *. 537193326Sed const llvm::Type *ProtocolExtensionPtrTy; 538193326Sed /// MethodDescriptionTy - LLVM type for struct 539193326Sed /// objc_method_description. 540193326Sed const llvm::StructType *MethodDescriptionTy; 541193326Sed /// MethodDescriptionListTy - LLVM type for struct 542193326Sed /// objc_method_description_list. 543193326Sed const llvm::StructType *MethodDescriptionListTy; 544193326Sed /// MethodDescriptionListPtrTy - LLVM type for struct 545193326Sed /// objc_method_description_list *. 546193326Sed const llvm::Type *MethodDescriptionListPtrTy; 547193326Sed /// ProtocolListTy - LLVM type for struct objc_property_list. 548193326Sed const llvm::Type *ProtocolListTy; 549193326Sed /// ProtocolListPtrTy - LLVM type for struct objc_property_list*. 550193326Sed const llvm::Type *ProtocolListPtrTy; 551193326Sed /// CategoryTy - LLVM type for struct objc_category. 552193326Sed const llvm::StructType *CategoryTy; 553193326Sed /// ClassTy - LLVM type for struct objc_class. 554193326Sed const llvm::StructType *ClassTy; 555193326Sed /// ClassPtrTy - LLVM type for struct objc_class *. 556193326Sed const llvm::Type *ClassPtrTy; 557193326Sed /// ClassExtensionTy - LLVM type for struct objc_class_ext. 558193326Sed const llvm::StructType *ClassExtensionTy; 559193326Sed /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *. 560193326Sed const llvm::Type *ClassExtensionPtrTy; 561193326Sed // IvarTy - LLVM type for struct objc_ivar. 562193326Sed const llvm::StructType *IvarTy; 563193326Sed /// IvarListTy - LLVM type for struct objc_ivar_list. 564193326Sed const llvm::Type *IvarListTy; 565193326Sed /// IvarListPtrTy - LLVM type for struct objc_ivar_list *. 566193326Sed const llvm::Type *IvarListPtrTy; 567193326Sed /// MethodListTy - LLVM type for struct objc_method_list. 568193326Sed const llvm::Type *MethodListTy; 569193326Sed /// MethodListPtrTy - LLVM type for struct objc_method_list *. 570193326Sed const llvm::Type *MethodListPtrTy; 571198092Srdivacky 572193326Sed /// ExceptionDataTy - LLVM type for struct _objc_exception_data. 573193326Sed const llvm::Type *ExceptionDataTy; 574198092Srdivacky 575193326Sed /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function. 576193326Sed llvm::Constant *getExceptionTryEnterFn() { 577193326Sed std::vector<const llvm::Type*> Params; 578193326Sed Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); 579198092Srdivacky return CGM.CreateRuntimeFunction( 580198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 581198092Srdivacky Params, false), 582198092Srdivacky "objc_exception_try_enter"); 583193326Sed } 584193326Sed 585193326Sed /// ExceptionTryExitFn - LLVM objc_exception_try_exit function. 586193326Sed llvm::Constant *getExceptionTryExitFn() { 587193326Sed std::vector<const llvm::Type*> Params; 588193326Sed Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); 589198092Srdivacky return CGM.CreateRuntimeFunction( 590198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 591198092Srdivacky Params, false), 592198092Srdivacky "objc_exception_try_exit"); 593193326Sed } 594193326Sed 595193326Sed /// ExceptionExtractFn - LLVM objc_exception_extract function. 596193326Sed llvm::Constant *getExceptionExtractFn() { 597193326Sed std::vector<const llvm::Type*> Params; 598193326Sed Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy)); 599193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 600193326Sed Params, false), 601193326Sed "objc_exception_extract"); 602198092Srdivacky 603193326Sed } 604198092Srdivacky 605193326Sed /// ExceptionMatchFn - LLVM objc_exception_match function. 606193326Sed llvm::Constant *getExceptionMatchFn() { 607193326Sed std::vector<const llvm::Type*> Params; 608193326Sed Params.push_back(ClassPtrTy); 609193326Sed Params.push_back(ObjectPtrTy); 610198092Srdivacky return CGM.CreateRuntimeFunction( 611198092Srdivacky llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), 612198092Srdivacky Params, false), 613198092Srdivacky "objc_exception_match"); 614198092Srdivacky 615193326Sed } 616198092Srdivacky 617193326Sed /// SetJmpFn - LLVM _setjmp function. 618193326Sed llvm::Constant *getSetJmpFn() { 619193326Sed std::vector<const llvm::Type*> Params; 620198092Srdivacky Params.push_back(llvm::Type::getInt32PtrTy(VMContext)); 621193326Sed return 622198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), 623193326Sed Params, false), 624193326Sed "_setjmp"); 625198092Srdivacky 626193326Sed } 627198092Srdivacky 628193326Sedpublic: 629193326Sed ObjCTypesHelper(CodeGen::CodeGenModule &cgm); 630193326Sed ~ObjCTypesHelper() {} 631193326Sed}; 632193326Sed 633193326Sed/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's 634193326Sed/// modern abi 635193326Sedclass ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper { 636193326Sedpublic: 637198092Srdivacky 638193326Sed // MethodListnfABITy - LLVM for struct _method_list_t 639193326Sed const llvm::StructType *MethodListnfABITy; 640198092Srdivacky 641193326Sed // MethodListnfABIPtrTy - LLVM for struct _method_list_t* 642193326Sed const llvm::Type *MethodListnfABIPtrTy; 643198092Srdivacky 644193326Sed // ProtocolnfABITy = LLVM for struct _protocol_t 645193326Sed const llvm::StructType *ProtocolnfABITy; 646198092Srdivacky 647193326Sed // ProtocolnfABIPtrTy = LLVM for struct _protocol_t* 648193326Sed const llvm::Type *ProtocolnfABIPtrTy; 649193326Sed 650193326Sed // ProtocolListnfABITy - LLVM for struct _objc_protocol_list 651193326Sed const llvm::StructType *ProtocolListnfABITy; 652198092Srdivacky 653193326Sed // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list* 654193326Sed const llvm::Type *ProtocolListnfABIPtrTy; 655198092Srdivacky 656193326Sed // ClassnfABITy - LLVM for struct _class_t 657193326Sed const llvm::StructType *ClassnfABITy; 658198092Srdivacky 659193326Sed // ClassnfABIPtrTy - LLVM for struct _class_t* 660193326Sed const llvm::Type *ClassnfABIPtrTy; 661198092Srdivacky 662193326Sed // IvarnfABITy - LLVM for struct _ivar_t 663193326Sed const llvm::StructType *IvarnfABITy; 664198092Srdivacky 665193326Sed // IvarListnfABITy - LLVM for struct _ivar_list_t 666193326Sed const llvm::StructType *IvarListnfABITy; 667198092Srdivacky 668193326Sed // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t* 669193326Sed const llvm::Type *IvarListnfABIPtrTy; 670198092Srdivacky 671193326Sed // ClassRonfABITy - LLVM for struct _class_ro_t 672193326Sed const llvm::StructType *ClassRonfABITy; 673198092Srdivacky 674193326Sed // ImpnfABITy - LLVM for id (*)(id, SEL, ...) 675193326Sed const llvm::Type *ImpnfABITy; 676198092Srdivacky 677193326Sed // CategorynfABITy - LLVM for struct _category_t 678193326Sed const llvm::StructType *CategorynfABITy; 679198092Srdivacky 680193326Sed // New types for nonfragile abi messaging. 681198092Srdivacky 682193326Sed // MessageRefTy - LLVM for: 683193326Sed // struct _message_ref_t { 684193326Sed // IMP messenger; 685193326Sed // SEL name; 686193326Sed // }; 687193326Sed const llvm::StructType *MessageRefTy; 688193326Sed // MessageRefCTy - clang type for struct _message_ref_t 689193326Sed QualType MessageRefCTy; 690198092Srdivacky 691193326Sed // MessageRefPtrTy - LLVM for struct _message_ref_t* 692193326Sed const llvm::Type *MessageRefPtrTy; 693193326Sed // MessageRefCPtrTy - clang type for struct _message_ref_t* 694193326Sed QualType MessageRefCPtrTy; 695198092Srdivacky 696193326Sed // MessengerTy - Type of the messenger (shown as IMP above) 697193326Sed const llvm::FunctionType *MessengerTy; 698198092Srdivacky 699193326Sed // SuperMessageRefTy - LLVM for: 700193326Sed // struct _super_message_ref_t { 701193326Sed // SUPER_IMP messenger; 702193326Sed // SEL name; 703193326Sed // }; 704193326Sed const llvm::StructType *SuperMessageRefTy; 705198092Srdivacky 706193326Sed // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* 707193326Sed const llvm::Type *SuperMessageRefPtrTy; 708193326Sed 709193326Sed llvm::Constant *getMessageSendFixupFn() { 710193326Sed // id objc_msgSend_fixup(id, struct message_ref_t*, ...) 711193326Sed std::vector<const llvm::Type*> Params; 712193326Sed Params.push_back(ObjectPtrTy); 713193326Sed Params.push_back(MessageRefPtrTy); 714193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 715193326Sed Params, true), 716193326Sed "objc_msgSend_fixup"); 717193326Sed } 718198092Srdivacky 719193326Sed llvm::Constant *getMessageSendFpretFixupFn() { 720193326Sed // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...) 721193326Sed std::vector<const llvm::Type*> Params; 722193326Sed Params.push_back(ObjectPtrTy); 723193326Sed Params.push_back(MessageRefPtrTy); 724193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 725193326Sed Params, true), 726193326Sed "objc_msgSend_fpret_fixup"); 727193326Sed } 728198092Srdivacky 729193326Sed llvm::Constant *getMessageSendStretFixupFn() { 730193326Sed // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...) 731193326Sed std::vector<const llvm::Type*> Params; 732193326Sed Params.push_back(ObjectPtrTy); 733193326Sed Params.push_back(MessageRefPtrTy); 734193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 735193326Sed Params, true), 736193326Sed "objc_msgSend_stret_fixup"); 737193326Sed } 738198092Srdivacky 739193326Sed llvm::Constant *getMessageSendSuper2FixupFn() { 740198092Srdivacky // id objc_msgSendSuper2_fixup (struct objc_super *, 741193326Sed // struct _super_message_ref_t*, ...) 742193326Sed std::vector<const llvm::Type*> Params; 743193326Sed Params.push_back(SuperPtrTy); 744193326Sed Params.push_back(SuperMessageRefPtrTy); 745193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 746193326Sed Params, true), 747193326Sed "objc_msgSendSuper2_fixup"); 748193326Sed } 749198092Srdivacky 750193326Sed llvm::Constant *getMessageSendSuper2StretFixupFn() { 751198092Srdivacky // id objc_msgSendSuper2_stret_fixup(struct objc_super *, 752193326Sed // struct _super_message_ref_t*, ...) 753193326Sed std::vector<const llvm::Type*> Params; 754193326Sed Params.push_back(SuperPtrTy); 755193326Sed Params.push_back(SuperMessageRefPtrTy); 756193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, 757193326Sed Params, true), 758193326Sed "objc_msgSendSuper2_stret_fixup"); 759193326Sed } 760198092Srdivacky 761193326Sed llvm::Constant *getObjCEndCatchFn() { 762198092Srdivacky return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 763195341Sed false), 764193326Sed "objc_end_catch"); 765198092Srdivacky 766193326Sed } 767198092Srdivacky 768193326Sed llvm::Constant *getObjCBeginCatchFn() { 769193326Sed std::vector<const llvm::Type*> Params; 770193326Sed Params.push_back(Int8PtrTy); 771193326Sed return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy, 772193326Sed Params, false), 773193326Sed "objc_begin_catch"); 774193326Sed } 775193326Sed 776193326Sed const llvm::StructType *EHTypeTy; 777193326Sed const llvm::Type *EHTypePtrTy; 778193326Sed 779193326Sed ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm); 780193326Sed ~ObjCNonFragileABITypesHelper(){} 781193326Sed}; 782198092Srdivacky 783193326Sedclass CGObjCCommonMac : public CodeGen::CGObjCRuntime { 784193326Sedpublic: 785193326Sed // FIXME - accessibility 786193326Sed class GC_IVAR { 787193326Sed public: 788193326Sed unsigned ivar_bytepos; 789193326Sed unsigned ivar_size; 790193326Sed GC_IVAR(unsigned bytepos = 0, unsigned size = 0) 791198092Srdivacky : ivar_bytepos(bytepos), ivar_size(size) {} 792193326Sed 793193326Sed // Allow sorting based on byte pos. 794193326Sed bool operator<(const GC_IVAR &b) const { 795193326Sed return ivar_bytepos < b.ivar_bytepos; 796193326Sed } 797193326Sed }; 798198092Srdivacky 799193326Sed class SKIP_SCAN { 800193326Sed public: 801193326Sed unsigned skip; 802193326Sed unsigned scan; 803198092Srdivacky SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0) 804193326Sed : skip(_skip), scan(_scan) {} 805193326Sed }; 806198092Srdivacky 807193326Sedprotected: 808193326Sed CodeGen::CodeGenModule &CGM; 809198092Srdivacky llvm::LLVMContext &VMContext; 810193326Sed // FIXME! May not be needing this after all. 811193326Sed unsigned ObjCABI; 812198092Srdivacky 813193326Sed // gc ivar layout bitmap calculation helper caches. 814193326Sed llvm::SmallVector<GC_IVAR, 16> SkipIvars; 815193326Sed llvm::SmallVector<GC_IVAR, 16> IvarsInfo; 816198092Srdivacky 817193326Sed /// LazySymbols - Symbols to generate a lazy reference for. See 818193326Sed /// DefinedSymbols and FinishModule(). 819198092Srdivacky llvm::SetVector<IdentifierInfo*> LazySymbols; 820198092Srdivacky 821193326Sed /// DefinedSymbols - External symbols which are defined by this 822193326Sed /// module. The symbols in this list and LazySymbols are used to add 823193326Sed /// special linker symbols which ensure that Objective-C modules are 824193326Sed /// linked properly. 825198092Srdivacky llvm::SetVector<IdentifierInfo*> DefinedSymbols; 826198092Srdivacky 827193326Sed /// ClassNames - uniqued class names. 828193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames; 829198092Srdivacky 830193326Sed /// MethodVarNames - uniqued method variable names. 831193326Sed llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames; 832198092Srdivacky 833210299Sed /// DefinedCategoryNames - list of category names in form Class_Category. 834210299Sed llvm::SetVector<std::string> DefinedCategoryNames; 835210299Sed 836193326Sed /// MethodVarTypes - uniqued method type signatures. We have to use 837193326Sed /// a StringMap here because have no other unique reference. 838193326Sed llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes; 839198092Srdivacky 840193326Sed /// MethodDefinitions - map of methods which have been defined in 841193326Sed /// this translation unit. 842193326Sed llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions; 843198092Srdivacky 844193326Sed /// PropertyNames - uniqued method variable names. 845193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames; 846198092Srdivacky 847193326Sed /// ClassReferences - uniqued class references. 848193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences; 849198092Srdivacky 850193326Sed /// SelectorReferences - uniqued selector references. 851193326Sed llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences; 852198092Srdivacky 853193326Sed /// Protocols - Protocols for which an objc_protocol structure has 854193326Sed /// been emitted. Forward declarations are handled by creating an 855193326Sed /// empty structure whose initializer is filled in when/if defined. 856193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols; 857198092Srdivacky 858193326Sed /// DefinedProtocols - Protocols which have actually been 859193326Sed /// defined. We should not need this, see FIXME in GenerateProtocol. 860193326Sed llvm::DenseSet<IdentifierInfo*> DefinedProtocols; 861198092Srdivacky 862193326Sed /// DefinedClasses - List of defined classes. 863193326Sed std::vector<llvm::GlobalValue*> DefinedClasses; 864193326Sed 865193326Sed /// DefinedNonLazyClasses - List of defined "non-lazy" classes. 866193326Sed std::vector<llvm::GlobalValue*> DefinedNonLazyClasses; 867198092Srdivacky 868193326Sed /// DefinedCategories - List of defined categories. 869193326Sed std::vector<llvm::GlobalValue*> DefinedCategories; 870198092Srdivacky 871193326Sed /// DefinedNonLazyCategories - List of defined "non-lazy" categories. 872193326Sed std::vector<llvm::GlobalValue*> DefinedNonLazyCategories; 873193326Sed 874193326Sed /// GetNameForMethod - Return a name for the given method. 875193326Sed /// \param[out] NameOut - The return value. 876193326Sed void GetNameForMethod(const ObjCMethodDecl *OMD, 877193326Sed const ObjCContainerDecl *CD, 878198398Srdivacky llvm::SmallVectorImpl<char> &NameOut); 879198092Srdivacky 880193326Sed /// GetMethodVarName - Return a unique constant for the given 881193326Sed /// selector's name. The return value has type char *. 882193326Sed llvm::Constant *GetMethodVarName(Selector Sel); 883193326Sed llvm::Constant *GetMethodVarName(IdentifierInfo *Ident); 884198092Srdivacky 885193326Sed /// GetMethodVarType - Return a unique constant for the given 886193326Sed /// selector's name. The return value has type char *. 887198092Srdivacky 888193326Sed // FIXME: This is a horrible name. 889193326Sed llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D); 890193326Sed llvm::Constant *GetMethodVarType(const FieldDecl *D); 891198092Srdivacky 892193326Sed /// GetPropertyName - Return a unique constant for the given 893193326Sed /// name. The return value has type char *. 894193326Sed llvm::Constant *GetPropertyName(IdentifierInfo *Ident); 895198092Srdivacky 896193326Sed // FIXME: This can be dropped once string functions are unified. 897193326Sed llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD, 898193326Sed const Decl *Container); 899198092Srdivacky 900193326Sed /// GetClassName - Return a unique constant for the given selector's 901193326Sed /// name. The return value has type char *. 902193326Sed llvm::Constant *GetClassName(IdentifierInfo *Ident); 903198092Srdivacky 904212904Sdim llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD); 905212904Sdim 906193326Sed /// BuildIvarLayout - Builds ivar layout bitmap for the class 907193326Sed /// implementation for the __strong or __weak case. 908193326Sed /// 909193326Sed llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI, 910193326Sed bool ForStrongLayout); 911212904Sdim 912212904Sdim llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap); 913198092Srdivacky 914193326Sed void BuildAggrIvarRecordLayout(const RecordType *RT, 915198092Srdivacky unsigned int BytePos, bool ForStrongLayout, 916198092Srdivacky bool &HasUnion); 917193326Sed void BuildAggrIvarLayout(const ObjCImplementationDecl *OI, 918193326Sed const llvm::StructLayout *Layout, 919193326Sed const RecordDecl *RD, 920193326Sed const llvm::SmallVectorImpl<FieldDecl*> &RecFields, 921193326Sed unsigned int BytePos, bool ForStrongLayout, 922193326Sed bool &HasUnion); 923193326Sed 924193326Sed /// GetIvarLayoutName - Returns a unique constant for the given 925193326Sed /// ivar layout bitmap. 926193326Sed llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident, 927193326Sed const ObjCCommonTypesHelper &ObjCTypes); 928198092Srdivacky 929193326Sed /// EmitPropertyList - Emit the given property list. The return 930193326Sed /// value has type PropertyListPtrTy. 931198398Srdivacky llvm::Constant *EmitPropertyList(llvm::Twine Name, 932198092Srdivacky const Decl *Container, 933193326Sed const ObjCContainerDecl *OCD, 934193326Sed const ObjCCommonTypesHelper &ObjCTypes); 935198092Srdivacky 936200583Srdivacky /// PushProtocolProperties - Push protocol's property on the input stack. 937200583Srdivacky void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet, 938200583Srdivacky std::vector<llvm::Constant*> &Properties, 939200583Srdivacky const Decl *Container, 940200583Srdivacky const ObjCProtocolDecl *PROTO, 941200583Srdivacky const ObjCCommonTypesHelper &ObjCTypes); 942200583Srdivacky 943193326Sed /// GetProtocolRef - Return a reference to the internal protocol 944193326Sed /// description, creating an empty one if it has not been 945193326Sed /// defined. The return value has type ProtocolPtrTy. 946193326Sed llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD); 947193326Sed 948193326Sed /// CreateMetadataVar - Create a global variable with internal 949193326Sed /// linkage for use by the Objective-C runtime. 950193326Sed /// 951193326Sed /// This is a convenience wrapper which not only creates the 952193326Sed /// variable, but also sets the section and alignment and adds the 953198092Srdivacky /// global to the "llvm.used" list. 954193326Sed /// 955193326Sed /// \param Name - The variable name. 956193326Sed /// \param Init - The variable initializer; this is also used to 957193326Sed /// define the type of the variable. 958193326Sed /// \param Section - The section the variable should go into, or 0. 959193326Sed /// \param Align - The alignment for the variable, or 0. 960193326Sed /// \param AddToUsed - Whether the variable should be added to 961193326Sed /// "llvm.used". 962198398Srdivacky llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name, 963193326Sed llvm::Constant *Init, 964193326Sed const char *Section, 965193326Sed unsigned Align, 966193326Sed bool AddToUsed); 967193326Sed 968193326Sed CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, 969208600Srdivacky ReturnValueSlot Return, 970193326Sed QualType ResultType, 971193326Sed llvm::Value *Sel, 972193326Sed llvm::Value *Arg0, 973193326Sed QualType Arg0Ty, 974193326Sed bool IsSuper, 975193326Sed const CallArgList &CallArgs, 976198092Srdivacky const ObjCMethodDecl *OMD, 977193326Sed const ObjCCommonTypesHelper &ObjCTypes); 978193326Sed 979207619Srdivacky /// EmitImageInfo - Emit the image info marker used to encode some module 980207619Srdivacky /// level information. 981207619Srdivacky void EmitImageInfo(); 982207619Srdivacky 983198092Srdivackypublic: 984198092Srdivacky CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : 985198092Srdivacky CGM(cgm), VMContext(cgm.getLLVMContext()) { } 986195099Sed 987202879Srdivacky virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL); 988198092Srdivacky 989193326Sed virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, 990193326Sed const ObjCContainerDecl *CD=0); 991198092Srdivacky 992193326Sed virtual void GenerateProtocol(const ObjCProtocolDecl *PD); 993198092Srdivacky 994193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 995193326Sed /// declaration, emitting it if necessary. The return value has type 996193326Sed /// ProtocolPtrTy. 997193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0; 998198092Srdivacky 999193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1000193326Sed /// object for the given declaration, emitting it if needed. These 1001193326Sed /// forward references will be filled in with empty bodies if no 1002193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1003193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0; 1004218893Sdim virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, 1005218893Sdim const CGBlockInfo &blockInfo); 1006212904Sdim 1007193326Sed}; 1008198092Srdivacky 1009193326Sedclass CGObjCMac : public CGObjCCommonMac { 1010193326Sedprivate: 1011193326Sed ObjCTypesHelper ObjCTypes; 1012193326Sed 1013193326Sed /// EmitModuleInfo - Another marker encoding module level 1014198092Srdivacky /// information. 1015193326Sed void EmitModuleInfo(); 1016193326Sed 1017193326Sed /// EmitModuleSymols - Emit module symbols, the list of defined 1018193326Sed /// classes and categories. The result has type SymtabPtrTy. 1019193326Sed llvm::Constant *EmitModuleSymbols(); 1020193326Sed 1021193326Sed /// FinishModule - Write out global data structures at the end of 1022193326Sed /// processing a translation unit. 1023193326Sed void FinishModule(); 1024193326Sed 1025193326Sed /// EmitClassExtension - Generate the class extension structure used 1026193326Sed /// to store the weak ivar layout and properties. The return value 1027193326Sed /// has type ClassExtensionPtrTy. 1028193326Sed llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID); 1029193326Sed 1030193326Sed /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1031193326Sed /// for the given class. 1032198092Srdivacky llvm::Value *EmitClassRef(CGBuilderTy &Builder, 1033193326Sed const ObjCInterfaceDecl *ID); 1034199482Srdivacky 1035199482Srdivacky /// EmitSuperClassRef - Emits reference to class's main metadata class. 1036199482Srdivacky llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID); 1037193326Sed 1038193326Sed /// EmitIvarList - Emit the ivar list for the given 1039193326Sed /// implementation. If ForClass is true the list of class ivars 1040193326Sed /// (i.e. metaclass ivars) is emitted, otherwise the list of 1041193326Sed /// interface ivars will be emitted. The return value has type 1042193326Sed /// IvarListPtrTy. 1043193326Sed llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID, 1044193326Sed bool ForClass); 1045198092Srdivacky 1046193326Sed /// EmitMetaClass - Emit a forward reference to the class structure 1047193326Sed /// for the metaclass of the given interface. The return value has 1048193326Sed /// type ClassPtrTy. 1049193326Sed llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID); 1050193326Sed 1051193326Sed /// EmitMetaClass - Emit a class structure for the metaclass of the 1052193326Sed /// given implementation. The return value has type ClassPtrTy. 1053193326Sed llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID, 1054193326Sed llvm::Constant *Protocols, 1055193326Sed const ConstantVector &Methods); 1056198092Srdivacky 1057193326Sed llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); 1058198092Srdivacky 1059193326Sed llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD); 1060193326Sed 1061193326Sed /// EmitMethodList - Emit the method list for the given 1062193326Sed /// implementation. The return value has type MethodListPtrTy. 1063198398Srdivacky llvm::Constant *EmitMethodList(llvm::Twine Name, 1064193326Sed const char *Section, 1065193326Sed const ConstantVector &Methods); 1066193326Sed 1067193326Sed /// EmitMethodDescList - Emit a method description list for a list of 1068198092Srdivacky /// method declarations. 1069193326Sed /// - TypeName: The name for the type containing the methods. 1070193326Sed /// - IsProtocol: True iff these methods are for a protocol. 1071193326Sed /// - ClassMethds: True iff these are class methods. 1072193326Sed /// - Required: When true, only "required" methods are 1073193326Sed /// listed. Similarly, when false only "optional" methods are 1074193326Sed /// listed. For classes this should always be true. 1075193326Sed /// - begin, end: The method list to output. 1076193326Sed /// 1077193326Sed /// The return value has type MethodDescriptionListPtrTy. 1078198398Srdivacky llvm::Constant *EmitMethodDescList(llvm::Twine Name, 1079193326Sed const char *Section, 1080193326Sed const ConstantVector &Methods); 1081193326Sed 1082193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1083193326Sed /// declaration, emitting it if necessary. The return value has type 1084193326Sed /// ProtocolPtrTy. 1085193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD); 1086193326Sed 1087193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1088193326Sed /// object for the given declaration, emitting it if needed. These 1089193326Sed /// forward references will be filled in with empty bodies if no 1090193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1091193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD); 1092193326Sed 1093193326Sed /// EmitProtocolExtension - Generate the protocol extension 1094193326Sed /// structure used to store optional instance and class methods, and 1095193326Sed /// protocol properties. The return value has type 1096193326Sed /// ProtocolExtensionPtrTy. 1097193326Sed llvm::Constant * 1098193326Sed EmitProtocolExtension(const ObjCProtocolDecl *PD, 1099193326Sed const ConstantVector &OptInstanceMethods, 1100193326Sed const ConstantVector &OptClassMethods); 1101193326Sed 1102193326Sed /// EmitProtocolList - Generate the list of referenced 1103193326Sed /// protocols. The return value has type ProtocolListPtrTy. 1104198398Srdivacky llvm::Constant *EmitProtocolList(llvm::Twine Name, 1105193326Sed ObjCProtocolDecl::protocol_iterator begin, 1106193326Sed ObjCProtocolDecl::protocol_iterator end); 1107193326Sed 1108193326Sed /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, 1109193326Sed /// for the given selector. 1110210299Sed llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel, 1111210299Sed bool lval=false); 1112198092Srdivacky 1113198092Srdivackypublic: 1114193326Sed CGObjCMac(CodeGen::CodeGenModule &cgm); 1115193326Sed 1116193326Sed virtual llvm::Function *ModuleInitFunction(); 1117198092Srdivacky 1118193326Sed virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1119208600Srdivacky ReturnValueSlot Return, 1120193326Sed QualType ResultType, 1121193326Sed Selector Sel, 1122193326Sed llvm::Value *Receiver, 1123193326Sed const CallArgList &CallArgs, 1124207619Srdivacky const ObjCInterfaceDecl *Class, 1125193326Sed const ObjCMethodDecl *Method); 1126193326Sed 1127198092Srdivacky virtual CodeGen::RValue 1128193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1129208600Srdivacky ReturnValueSlot Return, 1130193326Sed QualType ResultType, 1131193326Sed Selector Sel, 1132193326Sed const ObjCInterfaceDecl *Class, 1133193326Sed bool isCategoryImpl, 1134193326Sed llvm::Value *Receiver, 1135193326Sed bool IsClassMessage, 1136198092Srdivacky const CallArgList &CallArgs, 1137198092Srdivacky const ObjCMethodDecl *Method); 1138198092Srdivacky 1139193326Sed virtual llvm::Value *GetClass(CGBuilderTy &Builder, 1140193326Sed const ObjCInterfaceDecl *ID); 1141193326Sed 1142210299Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel, 1143210299Sed bool lval = false); 1144193326Sed 1145193326Sed /// The NeXT/Apple runtimes do not support typed selectors; just emit an 1146193326Sed /// untyped one. 1147193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, 1148193326Sed const ObjCMethodDecl *Method); 1149193326Sed 1150212904Sdim virtual llvm::Constant *GetEHType(QualType T); 1151212904Sdim 1152193326Sed virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); 1153193326Sed 1154193326Sed virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); 1155193326Sed 1156193326Sed virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, 1157193326Sed const ObjCProtocolDecl *PD); 1158198092Srdivacky 1159193326Sed virtual llvm::Constant *GetPropertyGetFunction(); 1160193326Sed virtual llvm::Constant *GetPropertySetFunction(); 1161218893Sdim virtual llvm::Constant *GetGetStructFunction(); 1162218893Sdim virtual llvm::Constant *GetSetStructFunction(); 1163193326Sed virtual llvm::Constant *EnumerationMutationFunction(); 1164198092Srdivacky 1165210299Sed virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF, 1166210299Sed const ObjCAtTryStmt &S); 1167210299Sed virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1168210299Sed const ObjCAtSynchronizedStmt &S); 1169210299Sed void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S); 1170193326Sed virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 1171193326Sed const ObjCAtThrowStmt &S); 1172193326Sed virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1173198092Srdivacky llvm::Value *AddrWeakObj); 1174193326Sed virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1175198092Srdivacky llvm::Value *src, llvm::Value *dst); 1176193326Sed virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1177212904Sdim llvm::Value *src, llvm::Value *dest, 1178212904Sdim bool threadlocal = false); 1179193326Sed virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 1180198092Srdivacky llvm::Value *src, llvm::Value *dest, 1181198092Srdivacky llvm::Value *ivarOffset); 1182193326Sed virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 1183193326Sed llvm::Value *src, llvm::Value *dest); 1184198092Srdivacky virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 1185198092Srdivacky llvm::Value *dest, llvm::Value *src, 1186210299Sed llvm::Value *size); 1187198092Srdivacky 1188193326Sed virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 1189193326Sed QualType ObjectTy, 1190193326Sed llvm::Value *BaseValue, 1191193326Sed const ObjCIvarDecl *Ivar, 1192193326Sed unsigned CVRQualifiers); 1193193326Sed virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 1194193326Sed const ObjCInterfaceDecl *Interface, 1195193326Sed const ObjCIvarDecl *Ivar); 1196193326Sed}; 1197198092Srdivacky 1198193326Sedclass CGObjCNonFragileABIMac : public CGObjCCommonMac { 1199193326Sedprivate: 1200193326Sed ObjCNonFragileABITypesHelper ObjCTypes; 1201193326Sed llvm::GlobalVariable* ObjCEmptyCacheVar; 1202193326Sed llvm::GlobalVariable* ObjCEmptyVtableVar; 1203198092Srdivacky 1204193326Sed /// SuperClassReferences - uniqued super class references. 1205193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences; 1206198092Srdivacky 1207193326Sed /// MetaClassReferences - uniqued meta class references. 1208193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences; 1209193326Sed 1210193326Sed /// EHTypeReferences - uniqued class ehtype references. 1211193326Sed llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences; 1212198092Srdivacky 1213193326Sed /// NonLegacyDispatchMethods - List of methods for which we do *not* generate 1214193326Sed /// legacy messaging dispatch. 1215193326Sed llvm::DenseSet<Selector> NonLegacyDispatchMethods; 1216198092Srdivacky 1217199482Srdivacky /// DefinedMetaClasses - List of defined meta-classes. 1218199482Srdivacky std::vector<llvm::GlobalValue*> DefinedMetaClasses; 1219199482Srdivacky 1220193326Sed /// LegacyDispatchedSelector - Returns true if SEL is not in the list of 1221193326Sed /// NonLegacyDispatchMethods; false otherwise. 1222193326Sed bool LegacyDispatchedSelector(Selector Sel); 1223198092Srdivacky 1224193326Sed /// FinishNonFragileABIModule - Write out global data structures at the end of 1225193326Sed /// processing a translation unit. 1226193326Sed void FinishNonFragileABIModule(); 1227193326Sed 1228193326Sed /// AddModuleClassList - Add the given list of class pointers to the 1229193326Sed /// module with the provided symbol and section names. 1230193326Sed void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container, 1231193326Sed const char *SymbolName, 1232193326Sed const char *SectionName); 1233193326Sed 1234198092Srdivacky llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags, 1235198092Srdivacky unsigned InstanceStart, 1236198092Srdivacky unsigned InstanceSize, 1237198092Srdivacky const ObjCImplementationDecl *ID); 1238193326Sed llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName, 1239198092Srdivacky llvm::Constant *IsAGV, 1240193326Sed llvm::Constant *SuperClassGV, 1241193326Sed llvm::Constant *ClassRoGV, 1242193326Sed bool HiddenVisibility); 1243198092Srdivacky 1244193326Sed llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD); 1245198092Srdivacky 1246193326Sed llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD); 1247198092Srdivacky 1248193326Sed /// EmitMethodList - Emit the method list for the given 1249193326Sed /// implementation. The return value has type MethodListnfABITy. 1250198398Srdivacky llvm::Constant *EmitMethodList(llvm::Twine Name, 1251193326Sed const char *Section, 1252193326Sed const ConstantVector &Methods); 1253193326Sed /// EmitIvarList - Emit the ivar list for the given 1254193326Sed /// implementation. If ForClass is true the list of class ivars 1255193326Sed /// (i.e. metaclass ivars) is emitted, otherwise the list of 1256193326Sed /// interface ivars will be emitted. The return value has type 1257193326Sed /// IvarListnfABIPtrTy. 1258193326Sed llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID); 1259198092Srdivacky 1260193326Sed llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, 1261193326Sed const ObjCIvarDecl *Ivar, 1262193326Sed unsigned long int offset); 1263198092Srdivacky 1264193326Sed /// GetOrEmitProtocol - Get the protocol object for the given 1265193326Sed /// declaration, emitting it if necessary. The return value has type 1266193326Sed /// ProtocolPtrTy. 1267193326Sed virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD); 1268198092Srdivacky 1269193326Sed /// GetOrEmitProtocolRef - Get a forward reference to the protocol 1270193326Sed /// object for the given declaration, emitting it if needed. These 1271193326Sed /// forward references will be filled in with empty bodies if no 1272193326Sed /// definition is seen. The return value has type ProtocolPtrTy. 1273193326Sed virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD); 1274198092Srdivacky 1275193326Sed /// EmitProtocolList - Generate the list of referenced 1276193326Sed /// protocols. The return value has type ProtocolListPtrTy. 1277198398Srdivacky llvm::Constant *EmitProtocolList(llvm::Twine Name, 1278193326Sed ObjCProtocolDecl::protocol_iterator begin, 1279193326Sed ObjCProtocolDecl::protocol_iterator end); 1280198092Srdivacky 1281193326Sed CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, 1282208600Srdivacky ReturnValueSlot Return, 1283193326Sed QualType ResultType, 1284193326Sed Selector Sel, 1285193326Sed llvm::Value *Receiver, 1286193326Sed QualType Arg0Ty, 1287193326Sed bool IsSuper, 1288193326Sed const CallArgList &CallArgs); 1289193326Sed 1290193326Sed /// GetClassGlobal - Return the global variable for the Objective-C 1291193326Sed /// class of the given name. 1292193326Sed llvm::GlobalVariable *GetClassGlobal(const std::string &Name); 1293198092Srdivacky 1294193326Sed /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1295193326Sed /// for the given class reference. 1296198092Srdivacky llvm::Value *EmitClassRef(CGBuilderTy &Builder, 1297193326Sed const ObjCInterfaceDecl *ID); 1298198092Srdivacky 1299193326Sed /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, 1300193326Sed /// for the given super class reference. 1301198092Srdivacky llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder, 1302198092Srdivacky const ObjCInterfaceDecl *ID); 1303198092Srdivacky 1304193326Sed /// EmitMetaClassRef - Return a Value * of the address of _class_t 1305193326Sed /// meta-data 1306198092Srdivacky llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder, 1307193326Sed const ObjCInterfaceDecl *ID); 1308193326Sed 1309193326Sed /// ObjCIvarOffsetVariable - Returns the ivar offset variable for 1310193326Sed /// the given ivar. 1311193326Sed /// 1312193326Sed llvm::GlobalVariable * ObjCIvarOffsetVariable( 1313198092Srdivacky const ObjCInterfaceDecl *ID, 1314198092Srdivacky const ObjCIvarDecl *Ivar); 1315198092Srdivacky 1316193326Sed /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, 1317193326Sed /// for the given selector. 1318210299Sed llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel, 1319210299Sed bool lval=false); 1320193326Sed 1321193326Sed /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C 1322193326Sed /// interface. The return value has type EHTypePtrTy. 1323212904Sdim llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID, 1324193326Sed bool ForDefinition); 1325193326Sed 1326198092Srdivacky const char *getMetaclassSymbolPrefix() const { 1327193326Sed return "OBJC_METACLASS_$_"; 1328193326Sed } 1329198092Srdivacky 1330193326Sed const char *getClassSymbolPrefix() const { 1331193326Sed return "OBJC_CLASS_$_"; 1332193326Sed } 1333193326Sed 1334193326Sed void GetClassSizeInfo(const ObjCImplementationDecl *OID, 1335193326Sed uint32_t &InstanceStart, 1336193326Sed uint32_t &InstanceSize); 1337198092Srdivacky 1338193326Sed // Shamelessly stolen from Analysis/CFRefCount.cpp 1339193326Sed Selector GetNullarySelector(const char* name) const { 1340193326Sed IdentifierInfo* II = &CGM.getContext().Idents.get(name); 1341193326Sed return CGM.getContext().Selectors.getSelector(0, &II); 1342193326Sed } 1343198092Srdivacky 1344193326Sed Selector GetUnarySelector(const char* name) const { 1345193326Sed IdentifierInfo* II = &CGM.getContext().Idents.get(name); 1346193326Sed return CGM.getContext().Selectors.getSelector(1, &II); 1347193326Sed } 1348193326Sed 1349193326Sed /// ImplementationIsNonLazy - Check whether the given category or 1350193326Sed /// class implementation is "non-lazy". 1351193326Sed bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const; 1352193326Sed 1353193326Sedpublic: 1354193326Sed CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm); 1355193326Sed // FIXME. All stubs for now! 1356193326Sed virtual llvm::Function *ModuleInitFunction(); 1357198092Srdivacky 1358193326Sed virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1359208600Srdivacky ReturnValueSlot Return, 1360193326Sed QualType ResultType, 1361193326Sed Selector Sel, 1362193326Sed llvm::Value *Receiver, 1363193326Sed const CallArgList &CallArgs, 1364207619Srdivacky const ObjCInterfaceDecl *Class, 1365193326Sed const ObjCMethodDecl *Method); 1366198092Srdivacky 1367198092Srdivacky virtual CodeGen::RValue 1368193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1369208600Srdivacky ReturnValueSlot Return, 1370193326Sed QualType ResultType, 1371193326Sed Selector Sel, 1372193326Sed const ObjCInterfaceDecl *Class, 1373193326Sed bool isCategoryImpl, 1374193326Sed llvm::Value *Receiver, 1375193326Sed bool IsClassMessage, 1376198092Srdivacky const CallArgList &CallArgs, 1377198092Srdivacky const ObjCMethodDecl *Method); 1378198092Srdivacky 1379193326Sed virtual llvm::Value *GetClass(CGBuilderTy &Builder, 1380193326Sed const ObjCInterfaceDecl *ID); 1381198092Srdivacky 1382210299Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel, 1383210299Sed bool lvalue = false) 1384210299Sed { return EmitSelector(Builder, Sel, lvalue); } 1385193326Sed 1386193326Sed /// The NeXT/Apple runtimes do not support typed selectors; just emit an 1387193326Sed /// untyped one. 1388193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, 1389193326Sed const ObjCMethodDecl *Method) 1390193326Sed { return EmitSelector(Builder, Method->getSelector()); } 1391198092Srdivacky 1392193326Sed virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); 1393198092Srdivacky 1394193326Sed virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); 1395193326Sed virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, 1396193326Sed const ObjCProtocolDecl *PD); 1397198092Srdivacky 1398212904Sdim virtual llvm::Constant *GetEHType(QualType T); 1399212904Sdim 1400198092Srdivacky virtual llvm::Constant *GetPropertyGetFunction() { 1401193326Sed return ObjCTypes.getGetPropertyFn(); 1402193326Sed } 1403198092Srdivacky virtual llvm::Constant *GetPropertySetFunction() { 1404198092Srdivacky return ObjCTypes.getSetPropertyFn(); 1405193326Sed } 1406207619Srdivacky 1407218893Sdim virtual llvm::Constant *GetSetStructFunction() { 1408207619Srdivacky return ObjCTypes.getCopyStructFn(); 1409207619Srdivacky } 1410218893Sdim virtual llvm::Constant *GetGetStructFunction() { 1411218893Sdim return ObjCTypes.getCopyStructFn(); 1412218893Sdim } 1413207619Srdivacky 1414193326Sed virtual llvm::Constant *EnumerationMutationFunction() { 1415193326Sed return ObjCTypes.getEnumerationMutationFn(); 1416193326Sed } 1417198092Srdivacky 1418210299Sed virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF, 1419210299Sed const ObjCAtTryStmt &S); 1420210299Sed virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1421210299Sed const ObjCAtSynchronizedStmt &S); 1422193326Sed virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 1423193326Sed const ObjCAtThrowStmt &S); 1424193326Sed virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1425193326Sed llvm::Value *AddrWeakObj); 1426193326Sed virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1427193326Sed llvm::Value *src, llvm::Value *dst); 1428193326Sed virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1429212904Sdim llvm::Value *src, llvm::Value *dest, 1430212904Sdim bool threadlocal = false); 1431193326Sed virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 1432198092Srdivacky llvm::Value *src, llvm::Value *dest, 1433198092Srdivacky llvm::Value *ivarOffset); 1434193326Sed virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 1435193326Sed llvm::Value *src, llvm::Value *dest); 1436198092Srdivacky virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 1437198092Srdivacky llvm::Value *dest, llvm::Value *src, 1438210299Sed llvm::Value *size); 1439193326Sed virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 1440193326Sed QualType ObjectTy, 1441193326Sed llvm::Value *BaseValue, 1442193326Sed const ObjCIvarDecl *Ivar, 1443193326Sed unsigned CVRQualifiers); 1444193326Sed virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 1445193326Sed const ObjCInterfaceDecl *Interface, 1446193326Sed const ObjCIvarDecl *Ivar); 1447193326Sed}; 1448198092Srdivacky 1449193326Sed} // end anonymous namespace 1450193326Sed 1451193326Sed/* *** Helper Functions *** */ 1452193326Sed 1453193326Sed/// getConstantGEP() - Help routine to construct simple GEPs. 1454198092Srdivackystatic llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext, 1455198092Srdivacky llvm::Constant *C, 1456193326Sed unsigned idx0, 1457193326Sed unsigned idx1) { 1458193326Sed llvm::Value *Idxs[] = { 1459198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0), 1460198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1) 1461193326Sed }; 1462193326Sed return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2); 1463193326Sed} 1464193326Sed 1465193326Sed/// hasObjCExceptionAttribute - Return true if this class or any super 1466193326Sed/// class has the __objc_exception__ attribute. 1467198092Srdivackystatic bool hasObjCExceptionAttribute(ASTContext &Context, 1468194613Sed const ObjCInterfaceDecl *OID) { 1469195341Sed if (OID->hasAttr<ObjCExceptionAttr>()) 1470193326Sed return true; 1471193326Sed if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 1472194613Sed return hasObjCExceptionAttribute(Context, Super); 1473193326Sed return false; 1474193326Sed} 1475193326Sed 1476193326Sed/* *** CGObjCMac Public Interface *** */ 1477198092Srdivacky 1478193326SedCGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), 1479198092Srdivacky ObjCTypes(cgm) { 1480193326Sed ObjCABI = 1; 1481198092Srdivacky EmitImageInfo(); 1482193326Sed} 1483193326Sed 1484193326Sed/// GetClass - Return a reference to the class for the given interface 1485193326Sed/// decl. 1486193326Sedllvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder, 1487193326Sed const ObjCInterfaceDecl *ID) { 1488193326Sed return EmitClassRef(Builder, ID); 1489193326Sed} 1490193326Sed 1491193326Sed/// GetSelector - Return the pointer to the unique'd string for this selector. 1492210299Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel, 1493210299Sed bool lval) { 1494210299Sed return EmitSelector(Builder, Sel, lval); 1495193326Sed} 1496193326Sedllvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl 1497198092Srdivacky *Method) { 1498193326Sed return EmitSelector(Builder, Method->getSelector()); 1499193326Sed} 1500193326Sed 1501212904Sdimllvm::Constant *CGObjCMac::GetEHType(QualType T) { 1502212904Sdim llvm_unreachable("asking for catch type for ObjC type in fragile runtime"); 1503212904Sdim return 0; 1504212904Sdim} 1505212904Sdim 1506193326Sed/// Generate a constant CFString object. 1507198092Srdivacky/* 1508198092Srdivacky struct __builtin_CFString { 1509198092Srdivacky const int *isa; // point to __CFConstantStringClassReference 1510198092Srdivacky int flags; 1511198092Srdivacky const char *str; 1512198092Srdivacky long length; 1513198092Srdivacky }; 1514193326Sed*/ 1515193326Sed 1516207619Srdivacky/// or Generate a constant NSString object. 1517207619Srdivacky/* 1518207619Srdivacky struct __builtin_NSString { 1519207619Srdivacky const int *isa; // point to __NSConstantStringClassReference 1520207619Srdivacky const char *str; 1521207619Srdivacky unsigned int length; 1522207619Srdivacky }; 1523207619Srdivacky*/ 1524207619Srdivacky 1525193326Sedllvm::Constant *CGObjCCommonMac::GenerateConstantString( 1526202879Srdivacky const StringLiteral *SL) { 1527207619Srdivacky return (CGM.getLangOptions().NoConstantCFStrings == 0 ? 1528207619Srdivacky CGM.GetAddrOfConstantCFString(SL) : 1529218893Sdim CGM.GetAddrOfConstantString(SL)); 1530193326Sed} 1531193326Sed 1532193326Sed/// Generates a message send where the super is the receiver. This is 1533193326Sed/// a message send to self with special delivery semantics indicating 1534193326Sed/// which class's method should be called. 1535193326SedCodeGen::RValue 1536193326SedCGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 1537208600Srdivacky ReturnValueSlot Return, 1538193326Sed QualType ResultType, 1539193326Sed Selector Sel, 1540193326Sed const ObjCInterfaceDecl *Class, 1541193326Sed bool isCategoryImpl, 1542193326Sed llvm::Value *Receiver, 1543193326Sed bool IsClassMessage, 1544198092Srdivacky const CodeGen::CallArgList &CallArgs, 1545198092Srdivacky const ObjCMethodDecl *Method) { 1546193326Sed // Create and init a super structure; this is a (receiver, class) 1547193326Sed // pair we will pass to objc_msgSendSuper. 1548198092Srdivacky llvm::Value *ObjCSuper = 1549193326Sed CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); 1550198092Srdivacky llvm::Value *ReceiverAsObject = 1551193326Sed CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); 1552198092Srdivacky CGF.Builder.CreateStore(ReceiverAsObject, 1553193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 1554193326Sed 1555193326Sed // If this is a class message the metaclass is passed as the target. 1556193326Sed llvm::Value *Target; 1557193326Sed if (IsClassMessage) { 1558193326Sed if (isCategoryImpl) { 1559193326Sed // Message sent to 'super' in a class method defined in a category 1560193326Sed // implementation requires an odd treatment. 1561193326Sed // If we are in a class method, we must retrieve the 1562193326Sed // _metaclass_ for the current class, pointed at by 1563193326Sed // the class's "isa" pointer. The following assumes that 1564193326Sed // isa" is the first ivar in a class (which it must be). 1565193326Sed Target = EmitClassRef(CGF.Builder, Class->getSuperClass()); 1566193326Sed Target = CGF.Builder.CreateStructGEP(Target, 0); 1567193326Sed Target = CGF.Builder.CreateLoad(Target); 1568198092Srdivacky } else { 1569193326Sed llvm::Value *MetaClassPtr = EmitMetaClassRef(Class); 1570193326Sed llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1); 1571193326Sed llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr); 1572193326Sed Target = Super; 1573198092Srdivacky } 1574199482Srdivacky } 1575199482Srdivacky else if (isCategoryImpl) 1576193326Sed Target = EmitClassRef(CGF.Builder, Class->getSuperClass()); 1577199482Srdivacky else { 1578199482Srdivacky llvm::Value *ClassPtr = EmitSuperClassRef(Class); 1579199482Srdivacky ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1); 1580199482Srdivacky Target = CGF.Builder.CreateLoad(ClassPtr); 1581193326Sed } 1582193326Sed // FIXME: We shouldn't need to do this cast, rectify the ASTContext and 1583193326Sed // ObjCTypes types. 1584198092Srdivacky const llvm::Type *ClassTy = 1585193326Sed CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); 1586193326Sed Target = CGF.Builder.CreateBitCast(Target, ClassTy); 1587198092Srdivacky CGF.Builder.CreateStore(Target, 1588193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 1589208600Srdivacky return EmitLegacyMessageSend(CGF, Return, ResultType, 1590193326Sed EmitSelector(CGF.Builder, Sel), 1591193326Sed ObjCSuper, ObjCTypes.SuperPtrCTy, 1592198092Srdivacky true, CallArgs, Method, ObjCTypes); 1593193326Sed} 1594198092Srdivacky 1595198092Srdivacky/// Generate code for a message send expression. 1596193326SedCodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 1597208600Srdivacky ReturnValueSlot Return, 1598193326Sed QualType ResultType, 1599193326Sed Selector Sel, 1600193326Sed llvm::Value *Receiver, 1601193326Sed const CallArgList &CallArgs, 1602207619Srdivacky const ObjCInterfaceDecl *Class, 1603193326Sed const ObjCMethodDecl *Method) { 1604208600Srdivacky return EmitLegacyMessageSend(CGF, Return, ResultType, 1605193326Sed EmitSelector(CGF.Builder, Sel), 1606193326Sed Receiver, CGF.getContext().getObjCIdType(), 1607198092Srdivacky false, CallArgs, Method, ObjCTypes); 1608193326Sed} 1609193326Sed 1610198092SrdivackyCodeGen::RValue 1611198092SrdivackyCGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF, 1612208600Srdivacky ReturnValueSlot Return, 1613198092Srdivacky QualType ResultType, 1614198092Srdivacky llvm::Value *Sel, 1615198092Srdivacky llvm::Value *Arg0, 1616198092Srdivacky QualType Arg0Ty, 1617198092Srdivacky bool IsSuper, 1618198092Srdivacky const CallArgList &CallArgs, 1619198092Srdivacky const ObjCMethodDecl *Method, 1620198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 1621193326Sed CallArgList ActualArgs; 1622193326Sed if (!IsSuper) 1623193326Sed Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp"); 1624193326Sed ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty)); 1625193326Sed ActualArgs.push_back(std::make_pair(RValue::get(Sel), 1626193326Sed CGF.getContext().getObjCSelType())); 1627193326Sed ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); 1628198092Srdivacky 1629193326Sed CodeGenTypes &Types = CGM.getTypes(); 1630203955Srdivacky const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs, 1631206084Srdivacky FunctionType::ExtInfo()); 1632198092Srdivacky const llvm::FunctionType *FTy = 1633198092Srdivacky Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); 1634198092Srdivacky 1635210299Sed if (Method) 1636210299Sed assert(CGM.getContext().getCanonicalType(Method->getResultType()) == 1637210299Sed CGM.getContext().getCanonicalType(ResultType) && 1638210299Sed "Result type mismatch!"); 1639210299Sed 1640193326Sed llvm::Constant *Fn = NULL; 1641210299Sed if (CGM.ReturnTypeUsesSRet(FnInfo)) { 1642193326Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) 1643198092Srdivacky : ObjCTypes.getSendStretFn(IsSuper); 1644210299Sed } else if (CGM.ReturnTypeUsesFPRet(ResultType)) { 1645210299Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper) 1646210299Sed : ObjCTypes.getSendFpretFn(IsSuper); 1647193326Sed } else { 1648193326Sed Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper) 1649198092Srdivacky : ObjCTypes.getSendFn(IsSuper); 1650193326Sed } 1651210299Sed Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy)); 1652208600Srdivacky return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs); 1653193326Sed} 1654193326Sed 1655212904Sdimstatic Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) { 1656212904Sdim if (FQT.isObjCGCStrong()) 1657212904Sdim return Qualifiers::Strong; 1658212904Sdim 1659212904Sdim if (FQT.isObjCGCWeak()) 1660212904Sdim return Qualifiers::Weak; 1661212904Sdim 1662212904Sdim if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) 1663212904Sdim return Qualifiers::Strong; 1664212904Sdim 1665212904Sdim if (const PointerType *PT = FQT->getAs<PointerType>()) 1666212904Sdim return GetGCAttrTypeForType(Ctx, PT->getPointeeType()); 1667212904Sdim 1668212904Sdim return Qualifiers::GCNone; 1669212904Sdim} 1670212904Sdim 1671218893Sdimllvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, 1672218893Sdim const CGBlockInfo &blockInfo) { 1673218893Sdim llvm::Constant *nullPtr = 1674212904Sdim llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext)); 1675218893Sdim 1676218893Sdim if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) 1677218893Sdim return nullPtr; 1678218893Sdim 1679212904Sdim bool hasUnion = false; 1680212904Sdim SkipIvars.clear(); 1681212904Sdim IvarsInfo.clear(); 1682212904Sdim unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0); 1683212904Sdim unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth(); 1684212904Sdim 1685218893Sdim // __isa is the first field in block descriptor and must assume by runtime's 1686218893Sdim // convention that it is GC'able. 1687218893Sdim IvarsInfo.push_back(GC_IVAR(0, 1)); 1688218893Sdim 1689218893Sdim const BlockDecl *blockDecl = blockInfo.getBlockDecl(); 1690218893Sdim 1691218893Sdim // Calculate the basic layout of the block structure. 1692218893Sdim const llvm::StructLayout *layout = 1693218893Sdim CGM.getTargetData().getStructLayout(blockInfo.StructureType); 1694218893Sdim 1695218893Sdim // Ignore the optional 'this' capture: C++ objects are not assumed 1696218893Sdim // to be GC'ed. 1697218893Sdim 1698218893Sdim // Walk the captured variables. 1699218893Sdim for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), 1700218893Sdim ce = blockDecl->capture_end(); ci != ce; ++ci) { 1701218893Sdim const VarDecl *variable = ci->getVariable(); 1702218893Sdim QualType type = variable->getType(); 1703218893Sdim 1704218893Sdim const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); 1705218893Sdim 1706218893Sdim // Ignore constant captures. 1707218893Sdim if (capture.isConstant()) continue; 1708218893Sdim 1709218893Sdim uint64_t fieldOffset = layout->getElementOffset(capture.getIndex()); 1710218893Sdim 1711218893Sdim // __block variables are passed by their descriptor address. 1712218893Sdim if (ci->isByRef()) { 1713218893Sdim IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1)); 1714212904Sdim continue; 1715212904Sdim } 1716218893Sdim 1717218893Sdim assert(!type->isArrayType() && "array variable should not be caught"); 1718218893Sdim if (const RecordType *record = type->getAs<RecordType>()) { 1719218893Sdim BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion); 1720218893Sdim continue; 1721218893Sdim } 1722212904Sdim 1723218893Sdim Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type); 1724218893Sdim unsigned fieldSize = CGM.getContext().getTypeSize(type); 1725218893Sdim 1726218893Sdim if (GCAttr == Qualifiers::Strong) 1727218893Sdim IvarsInfo.push_back(GC_IVAR(fieldOffset, 1728218893Sdim fieldSize / WordSizeInBits)); 1729212904Sdim else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak) 1730218893Sdim SkipIvars.push_back(GC_IVAR(fieldOffset, 1731218893Sdim fieldSize / ByteSizeInBits)); 1732212904Sdim } 1733212904Sdim 1734212904Sdim if (IvarsInfo.empty()) 1735218893Sdim return nullPtr; 1736218893Sdim 1737218893Sdim // Sort on byte position; captures might not be allocated in order, 1738218893Sdim // and unions can do funny things. 1739218893Sdim llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end()); 1740218893Sdim llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end()); 1741212904Sdim 1742212904Sdim std::string BitMap; 1743212904Sdim llvm::Constant *C = BuildIvarLayoutBitmap(BitMap); 1744212904Sdim if (CGM.getLangOptions().ObjCGCBitmapPrint) { 1745212904Sdim printf("\n block variable layout for block: "); 1746212904Sdim const unsigned char *s = (unsigned char*)BitMap.c_str(); 1747212904Sdim for (unsigned i = 0; i < BitMap.size(); i++) 1748212904Sdim if (!(s[i] & 0xf0)) 1749212904Sdim printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); 1750212904Sdim else 1751212904Sdim printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); 1752212904Sdim printf("\n"); 1753212904Sdim } 1754212904Sdim 1755212904Sdim return C; 1756212904Sdim} 1757212904Sdim 1758198092Srdivackyllvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder, 1759193326Sed const ObjCProtocolDecl *PD) { 1760193326Sed // FIXME: I don't understand why gcc generates this, or where it is 1761193326Sed // resolved. Investigate. Its also wasteful to look this up over and over. 1762193326Sed LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); 1763193326Sed 1764193326Sed return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD), 1765193326Sed ObjCTypes.ExternalProtocolPtrTy); 1766193326Sed} 1767193326Sed 1768193326Sedvoid CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) { 1769193326Sed // FIXME: We shouldn't need this, the protocol decl should contain enough 1770193326Sed // information to tell us whether this was a declaration or a definition. 1771193326Sed DefinedProtocols.insert(PD->getIdentifier()); 1772193326Sed 1773193326Sed // If we have generated a forward reference to this protocol, emit 1774193326Sed // it now. Otherwise do nothing, the protocol objects are lazily 1775193326Sed // emitted. 1776198092Srdivacky if (Protocols.count(PD->getIdentifier())) 1777193326Sed GetOrEmitProtocol(PD); 1778193326Sed} 1779193326Sed 1780193326Sedllvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) { 1781193326Sed if (DefinedProtocols.count(PD->getIdentifier())) 1782193326Sed return GetOrEmitProtocol(PD); 1783193326Sed return GetOrEmitProtocolRef(PD); 1784193326Sed} 1785193326Sed 1786193326Sed/* 1787198092Srdivacky// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions 1788198092Srdivackystruct _objc_protocol { 1789198092Srdivackystruct _objc_protocol_extension *isa; 1790198092Srdivackychar *protocol_name; 1791198092Srdivackystruct _objc_protocol_list *protocol_list; 1792198092Srdivackystruct _objc__method_prototype_list *instance_methods; 1793198092Srdivackystruct _objc__method_prototype_list *class_methods 1794198092Srdivacky}; 1795193326Sed 1796198092SrdivackySee EmitProtocolExtension(). 1797193326Sed*/ 1798193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { 1799193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 1800193326Sed 1801193326Sed // Early exit if a defining object has already been generated. 1802193326Sed if (Entry && Entry->hasInitializer()) 1803193326Sed return Entry; 1804193326Sed 1805193326Sed // FIXME: I don't understand why gcc generates this, or where it is 1806193326Sed // resolved. Investigate. Its also wasteful to look this up over and over. 1807193326Sed LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); 1808193326Sed 1809193326Sed // Construct method lists. 1810193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 1811193326Sed std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; 1812198092Srdivacky for (ObjCProtocolDecl::instmeth_iterator 1813195341Sed i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { 1814193326Sed ObjCMethodDecl *MD = *i; 1815193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 1816193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 1817193326Sed OptInstanceMethods.push_back(C); 1818193326Sed } else { 1819193326Sed InstanceMethods.push_back(C); 1820198092Srdivacky } 1821193326Sed } 1822193326Sed 1823198092Srdivacky for (ObjCProtocolDecl::classmeth_iterator 1824195341Sed i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { 1825193326Sed ObjCMethodDecl *MD = *i; 1826193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 1827193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 1828193326Sed OptClassMethods.push_back(C); 1829193326Sed } else { 1830193326Sed ClassMethods.push_back(C); 1831198092Srdivacky } 1832193326Sed } 1833193326Sed 1834193326Sed std::vector<llvm::Constant*> Values(5); 1835193326Sed Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods); 1836193326Sed Values[1] = GetClassName(PD->getIdentifier()); 1837198092Srdivacky Values[2] = 1838198398Srdivacky EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(), 1839193326Sed PD->protocol_begin(), 1840193326Sed PD->protocol_end()); 1841198092Srdivacky Values[3] = 1842198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(), 1843193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 1844193326Sed InstanceMethods); 1845198092Srdivacky Values[4] = 1846198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(), 1847193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1848193326Sed ClassMethods); 1849193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, 1850193326Sed Values); 1851198092Srdivacky 1852193326Sed if (Entry) { 1853193326Sed // Already created, fix the linkage and update the initializer. 1854193326Sed Entry->setLinkage(llvm::GlobalValue::InternalLinkage); 1855193326Sed Entry->setInitializer(Init); 1856193326Sed } else { 1857198092Srdivacky Entry = 1858198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, 1859193326Sed llvm::GlobalValue::InternalLinkage, 1860198092Srdivacky Init, 1861198398Srdivacky "\01L_OBJC_PROTOCOL_" + PD->getName()); 1862193326Sed Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); 1863193326Sed // FIXME: Is this necessary? Why only for protocol? 1864193326Sed Entry->setAlignment(4); 1865193326Sed } 1866198092Srdivacky CGM.AddUsedGlobal(Entry); 1867193326Sed 1868193326Sed return Entry; 1869193326Sed} 1870193326Sed 1871193326Sedllvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { 1872193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 1873193326Sed 1874193326Sed if (!Entry) { 1875193326Sed // We use the initializer as a marker of whether this is a forward 1876193326Sed // reference or not. At module finalization we add the empty 1877193326Sed // contents for protocols which were referenced but never defined. 1878198092Srdivacky Entry = 1879198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false, 1880193326Sed llvm::GlobalValue::ExternalLinkage, 1881193326Sed 0, 1882198398Srdivacky "\01L_OBJC_PROTOCOL_" + PD->getName()); 1883193326Sed Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); 1884193326Sed // FIXME: Is this necessary? Why only for protocol? 1885193326Sed Entry->setAlignment(4); 1886193326Sed } 1887198092Srdivacky 1888193326Sed return Entry; 1889193326Sed} 1890193326Sed 1891193326Sed/* 1892193326Sed struct _objc_protocol_extension { 1893198092Srdivacky uint32_t size; 1894198092Srdivacky struct objc_method_description_list *optional_instance_methods; 1895198092Srdivacky struct objc_method_description_list *optional_class_methods; 1896198092Srdivacky struct objc_property_list *instance_properties; 1897193326Sed }; 1898193326Sed*/ 1899193326Sedllvm::Constant * 1900193326SedCGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, 1901193326Sed const ConstantVector &OptInstanceMethods, 1902193326Sed const ConstantVector &OptClassMethods) { 1903198092Srdivacky uint64_t Size = 1904193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); 1905193326Sed std::vector<llvm::Constant*> Values(4); 1906193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 1907198092Srdivacky Values[1] = 1908198092Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_" 1909198398Srdivacky + PD->getName(), 1910193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 1911193326Sed OptInstanceMethods); 1912198092Srdivacky Values[2] = 1913198398Srdivacky EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(), 1914193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1915193326Sed OptClassMethods); 1916198398Srdivacky Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 1917193326Sed 0, PD, ObjCTypes); 1918193326Sed 1919193326Sed // Return null if no extension bits are used. 1920198092Srdivacky if (Values[1]->isNullValue() && Values[2]->isNullValue() && 1921193326Sed Values[3]->isNullValue()) 1922193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); 1923193326Sed 1924198092Srdivacky llvm::Constant *Init = 1925193326Sed llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values); 1926193326Sed 1927193326Sed // No special section, but goes in llvm.used 1928198398Srdivacky return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(), 1929198092Srdivacky Init, 1930193326Sed 0, 0, true); 1931193326Sed} 1932193326Sed 1933193326Sed/* 1934193326Sed struct objc_protocol_list { 1935198092Srdivacky struct objc_protocol_list *next; 1936198092Srdivacky long count; 1937198092Srdivacky Protocol *list[]; 1938193326Sed }; 1939193326Sed*/ 1940193326Sedllvm::Constant * 1941198398SrdivackyCGObjCMac::EmitProtocolList(llvm::Twine Name, 1942193326Sed ObjCProtocolDecl::protocol_iterator begin, 1943193326Sed ObjCProtocolDecl::protocol_iterator end) { 1944193326Sed std::vector<llvm::Constant*> ProtocolRefs; 1945193326Sed 1946193326Sed for (; begin != end; ++begin) 1947193326Sed ProtocolRefs.push_back(GetProtocolRef(*begin)); 1948193326Sed 1949193326Sed // Just return null for empty protocol lists 1950198092Srdivacky if (ProtocolRefs.empty()) 1951193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 1952193326Sed 1953193326Sed // This list is null terminated. 1954193326Sed ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy)); 1955193326Sed 1956193326Sed std::vector<llvm::Constant*> Values(3); 1957193326Sed // This field is only used by the runtime. 1958193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 1959198092Srdivacky Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, 1960198092Srdivacky ProtocolRefs.size() - 1); 1961198092Srdivacky Values[2] = 1962198092Srdivacky llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy, 1963198092Srdivacky ProtocolRefs.size()), 1964193326Sed ProtocolRefs); 1965198092Srdivacky 1966198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 1967198092Srdivacky llvm::GlobalVariable *GV = 1968193326Sed CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip", 1969193326Sed 4, false); 1970193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy); 1971193326Sed} 1972193326Sed 1973200583Srdivackyvoid CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet, 1974200583Srdivacky std::vector<llvm::Constant*> &Properties, 1975200583Srdivacky const Decl *Container, 1976200583Srdivacky const ObjCProtocolDecl *PROTO, 1977200583Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 1978200583Srdivacky std::vector<llvm::Constant*> Prop(2); 1979200583Srdivacky for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(), 1980200583Srdivacky E = PROTO->protocol_end(); P != E; ++P) 1981200583Srdivacky PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes); 1982200583Srdivacky for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(), 1983200583Srdivacky E = PROTO->prop_end(); I != E; ++I) { 1984200583Srdivacky const ObjCPropertyDecl *PD = *I; 1985200583Srdivacky if (!PropertySet.insert(PD->getIdentifier())) 1986200583Srdivacky continue; 1987200583Srdivacky Prop[0] = GetPropertyName(PD->getIdentifier()); 1988200583Srdivacky Prop[1] = GetPropertyTypeString(PD, Container); 1989200583Srdivacky Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop)); 1990200583Srdivacky } 1991200583Srdivacky} 1992200583Srdivacky 1993193326Sed/* 1994193326Sed struct _objc_property { 1995198092Srdivacky const char * const name; 1996198092Srdivacky const char * const attributes; 1997193326Sed }; 1998193326Sed 1999193326Sed struct _objc_property_list { 2000198092Srdivacky uint32_t entsize; // sizeof (struct _objc_property) 2001198092Srdivacky uint32_t prop_count; 2002198092Srdivacky struct _objc_property[prop_count]; 2003193326Sed }; 2004193326Sed*/ 2005198398Srdivackyllvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name, 2006198092Srdivacky const Decl *Container, 2007198092Srdivacky const ObjCContainerDecl *OCD, 2008198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 2009193326Sed std::vector<llvm::Constant*> Properties, Prop(2); 2010200583Srdivacky llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet; 2011198092Srdivacky for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(), 2012198092Srdivacky E = OCD->prop_end(); I != E; ++I) { 2013193326Sed const ObjCPropertyDecl *PD = *I; 2014200583Srdivacky PropertySet.insert(PD->getIdentifier()); 2015193326Sed Prop[0] = GetPropertyName(PD->getIdentifier()); 2016193326Sed Prop[1] = GetPropertyTypeString(PD, Container); 2017193326Sed Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, 2018193326Sed Prop)); 2019193326Sed } 2020210299Sed if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) { 2021212904Sdim for (ObjCInterfaceDecl::all_protocol_iterator 2022212904Sdim P = OID->all_referenced_protocol_begin(), 2023212904Sdim E = OID->all_referenced_protocol_end(); P != E; ++P) 2024210299Sed PushProtocolProperties(PropertySet, Properties, Container, (*P), 2025210299Sed ObjCTypes); 2026210299Sed } 2027210299Sed else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) { 2028210299Sed for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(), 2029210299Sed E = CD->protocol_end(); P != E; ++P) 2030210299Sed PushProtocolProperties(PropertySet, Properties, Container, (*P), 2031210299Sed ObjCTypes); 2032210299Sed } 2033193326Sed 2034193326Sed // Return null for empty list. 2035193326Sed if (Properties.empty()) 2036193326Sed return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 2037193326Sed 2038198092Srdivacky unsigned PropertySize = 2039193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy); 2040193326Sed std::vector<llvm::Constant*> Values(3); 2041193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize); 2042193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size()); 2043198092Srdivacky llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy, 2044193326Sed Properties.size()); 2045193326Sed Values[2] = llvm::ConstantArray::get(AT, Properties); 2046198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 2047193326Sed 2048198092Srdivacky llvm::GlobalVariable *GV = 2049198092Srdivacky CreateMetadataVar(Name, Init, 2050198092Srdivacky (ObjCABI == 2) ? "__DATA, __objc_const" : 2051193326Sed "__OBJC,__property,regular,no_dead_strip", 2052198092Srdivacky (ObjCABI == 2) ? 8 : 4, 2053193326Sed true); 2054193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy); 2055193326Sed} 2056193326Sed 2057193326Sed/* 2058193326Sed struct objc_method_description_list { 2059198092Srdivacky int count; 2060198092Srdivacky struct objc_method_description list[]; 2061193326Sed }; 2062193326Sed*/ 2063193326Sedllvm::Constant * 2064193326SedCGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { 2065193326Sed std::vector<llvm::Constant*> Desc(2); 2066198092Srdivacky Desc[0] = 2067198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 2068198092Srdivacky ObjCTypes.SelectorPtrTy); 2069193326Sed Desc[1] = GetMethodVarType(MD); 2070193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy, 2071193326Sed Desc); 2072193326Sed} 2073193326Sed 2074198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name, 2075193326Sed const char *Section, 2076193326Sed const ConstantVector &Methods) { 2077193326Sed // Return null for empty list. 2078193326Sed if (Methods.empty()) 2079193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); 2080193326Sed 2081193326Sed std::vector<llvm::Constant*> Values(2); 2082193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 2083198092Srdivacky llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy, 2084193326Sed Methods.size()); 2085193326Sed Values[1] = llvm::ConstantArray::get(AT, Methods); 2086198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 2087193326Sed 2088193326Sed llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true); 2089198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, 2090193326Sed ObjCTypes.MethodDescriptionListPtrTy); 2091193326Sed} 2092193326Sed 2093193326Sed/* 2094193326Sed struct _objc_category { 2095198092Srdivacky char *category_name; 2096198092Srdivacky char *class_name; 2097198092Srdivacky struct _objc_method_list *instance_methods; 2098198092Srdivacky struct _objc_method_list *class_methods; 2099198092Srdivacky struct _objc_protocol_list *protocols; 2100198092Srdivacky uint32_t size; // <rdar://4585769> 2101198092Srdivacky struct _objc_property_list *instance_properties; 2102193326Sed }; 2103198092Srdivacky*/ 2104193326Sedvoid CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 2105193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy); 2106193326Sed 2107193326Sed // FIXME: This is poor design, the OCD should have a pointer to the category 2108193326Sed // decl. Additionally, note that Category can be null for the @implementation 2109193326Sed // w/o an @interface case. Sema should just create one for us as it does for 2110193326Sed // @implementation so everyone else can live life under a clear blue sky. 2111193326Sed const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); 2112198092Srdivacky const ObjCCategoryDecl *Category = 2113193326Sed Interface->FindCategoryDeclaration(OCD->getIdentifier()); 2114193326Sed 2115198398Srdivacky llvm::SmallString<256> ExtName; 2116198398Srdivacky llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_' 2117198398Srdivacky << OCD->getName(); 2118198398Srdivacky 2119193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 2120198092Srdivacky for (ObjCCategoryImplDecl::instmeth_iterator 2121195341Sed i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { 2122193326Sed // Instance methods should always be defined. 2123193326Sed InstanceMethods.push_back(GetMethodConstant(*i)); 2124193326Sed } 2125198092Srdivacky for (ObjCCategoryImplDecl::classmeth_iterator 2126195341Sed i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { 2127193326Sed // Class methods should always be defined. 2128193326Sed ClassMethods.push_back(GetMethodConstant(*i)); 2129193326Sed } 2130193326Sed 2131193326Sed std::vector<llvm::Constant*> Values(7); 2132193326Sed Values[0] = GetClassName(OCD->getIdentifier()); 2133193326Sed Values[1] = GetClassName(Interface->getIdentifier()); 2134193326Sed LazySymbols.insert(Interface->getIdentifier()); 2135198092Srdivacky Values[2] = 2136198398Srdivacky EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(), 2137193326Sed "__OBJC,__cat_inst_meth,regular,no_dead_strip", 2138193326Sed InstanceMethods); 2139198092Srdivacky Values[3] = 2140198398Srdivacky EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(), 2141193326Sed "__OBJC,__cat_cls_meth,regular,no_dead_strip", 2142193326Sed ClassMethods); 2143193326Sed if (Category) { 2144198092Srdivacky Values[4] = 2145198398Srdivacky EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(), 2146193326Sed Category->protocol_begin(), 2147193326Sed Category->protocol_end()); 2148193326Sed } else { 2149193326Sed Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 2150193326Sed } 2151193326Sed Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 2152193326Sed 2153193326Sed // If there is no category @interface then there can be no properties. 2154193326Sed if (Category) { 2155198398Srdivacky Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), 2156193326Sed OCD, Category, ObjCTypes); 2157193326Sed } else { 2158193326Sed Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 2159193326Sed } 2160198092Srdivacky 2161193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy, 2162193326Sed Values); 2163193326Sed 2164198092Srdivacky llvm::GlobalVariable *GV = 2165198398Srdivacky CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init, 2166193326Sed "__OBJC,__category,regular,no_dead_strip", 2167193326Sed 4, true); 2168193326Sed DefinedCategories.push_back(GV); 2169210299Sed DefinedCategoryNames.insert(ExtName.str()); 2170193326Sed} 2171193326Sed 2172193326Sed// FIXME: Get from somewhere? 2173193326Sedenum ClassFlags { 2174193326Sed eClassFlags_Factory = 0x00001, 2175193326Sed eClassFlags_Meta = 0x00002, 2176193326Sed // <rdr://5142207> 2177193326Sed eClassFlags_HasCXXStructors = 0x02000, 2178193326Sed eClassFlags_Hidden = 0x20000, 2179193326Sed eClassFlags_ABI2_Hidden = 0x00010, 2180193326Sed eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634> 2181193326Sed}; 2182193326Sed 2183193326Sed/* 2184193326Sed struct _objc_class { 2185198092Srdivacky Class isa; 2186198092Srdivacky Class super_class; 2187198092Srdivacky const char *name; 2188198092Srdivacky long version; 2189198092Srdivacky long info; 2190198092Srdivacky long instance_size; 2191198092Srdivacky struct _objc_ivar_list *ivars; 2192198092Srdivacky struct _objc_method_list *methods; 2193198092Srdivacky struct _objc_cache *cache; 2194198092Srdivacky struct _objc_protocol_list *protocols; 2195198092Srdivacky // Objective-C 1.0 extensions (<rdr://4585769>) 2196198092Srdivacky const char *ivar_layout; 2197198092Srdivacky struct _objc_class_ext *ext; 2198193326Sed }; 2199193326Sed 2200193326Sed See EmitClassExtension(); 2201198092Srdivacky*/ 2202193326Sedvoid CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { 2203193326Sed DefinedSymbols.insert(ID->getIdentifier()); 2204193326Sed 2205193326Sed std::string ClassName = ID->getNameAsString(); 2206193326Sed // FIXME: Gross 2207198092Srdivacky ObjCInterfaceDecl *Interface = 2208193326Sed const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); 2209198092Srdivacky llvm::Constant *Protocols = 2210198398Srdivacky EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(), 2211212904Sdim Interface->all_referenced_protocol_begin(), 2212212904Sdim Interface->all_referenced_protocol_end()); 2213193326Sed unsigned Flags = eClassFlags_Factory; 2214207619Srdivacky if (ID->getNumIvarInitializers()) 2215207619Srdivacky Flags |= eClassFlags_HasCXXStructors; 2216198092Srdivacky unsigned Size = 2217218893Sdim CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity(); 2218193326Sed 2219193326Sed // FIXME: Set CXX-structors flag. 2220218893Sdim if (ID->getClassInterface()->getVisibility() == HiddenVisibility) 2221193326Sed Flags |= eClassFlags_Hidden; 2222193326Sed 2223193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 2224198092Srdivacky for (ObjCImplementationDecl::instmeth_iterator 2225195341Sed i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { 2226193326Sed // Instance methods should always be defined. 2227193326Sed InstanceMethods.push_back(GetMethodConstant(*i)); 2228193326Sed } 2229198092Srdivacky for (ObjCImplementationDecl::classmeth_iterator 2230195341Sed i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { 2231193326Sed // Class methods should always be defined. 2232193326Sed ClassMethods.push_back(GetMethodConstant(*i)); 2233193326Sed } 2234193326Sed 2235198092Srdivacky for (ObjCImplementationDecl::propimpl_iterator 2236195341Sed i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { 2237193326Sed ObjCPropertyImplDecl *PID = *i; 2238193326Sed 2239193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { 2240193326Sed ObjCPropertyDecl *PD = PID->getPropertyDecl(); 2241193326Sed 2242193326Sed if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) 2243193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 2244193326Sed InstanceMethods.push_back(C); 2245193326Sed if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) 2246193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 2247193326Sed InstanceMethods.push_back(C); 2248193326Sed } 2249193326Sed } 2250193326Sed 2251193326Sed std::vector<llvm::Constant*> Values(12); 2252193326Sed Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods); 2253193326Sed if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) { 2254193326Sed // Record a reference to the super class. 2255193326Sed LazySymbols.insert(Super->getIdentifier()); 2256193326Sed 2257198092Srdivacky Values[ 1] = 2258193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), 2259193326Sed ObjCTypes.ClassPtrTy); 2260193326Sed } else { 2261193326Sed Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy); 2262193326Sed } 2263193326Sed Values[ 2] = GetClassName(ID->getIdentifier()); 2264193326Sed // Version is always 0. 2265193326Sed Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 2266193326Sed Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); 2267193326Sed Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 2268193326Sed Values[ 6] = EmitIvarList(ID, false); 2269198092Srdivacky Values[ 7] = 2270198398Srdivacky EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(), 2271193326Sed "__OBJC,__inst_meth,regular,no_dead_strip", 2272193326Sed InstanceMethods); 2273193326Sed // cache is always NULL. 2274193326Sed Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy); 2275193326Sed Values[ 9] = Protocols; 2276198092Srdivacky Values[10] = BuildIvarLayout(ID, true); 2277193326Sed Values[11] = EmitClassExtension(ID); 2278193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy, 2279193326Sed Values); 2280199482Srdivacky std::string Name("\01L_OBJC_CLASS_"); 2281199482Srdivacky Name += ClassName; 2282199482Srdivacky const char *Section = "__OBJC,__class,regular,no_dead_strip"; 2283199482Srdivacky // Check for a forward reference. 2284199482Srdivacky llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 2285199482Srdivacky if (GV) { 2286199482Srdivacky assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2287199482Srdivacky "Forward metaclass reference has incorrect type."); 2288199482Srdivacky GV->setLinkage(llvm::GlobalValue::InternalLinkage); 2289199482Srdivacky GV->setInitializer(Init); 2290199482Srdivacky GV->setSection(Section); 2291199482Srdivacky GV->setAlignment(4); 2292199482Srdivacky CGM.AddUsedGlobal(GV); 2293199482Srdivacky } 2294199482Srdivacky else 2295199482Srdivacky GV = CreateMetadataVar(Name, Init, Section, 4, true); 2296193326Sed DefinedClasses.push_back(GV); 2297193326Sed} 2298193326Sed 2299193326Sedllvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, 2300193326Sed llvm::Constant *Protocols, 2301193326Sed const ConstantVector &Methods) { 2302193326Sed unsigned Flags = eClassFlags_Meta; 2303193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy); 2304193326Sed 2305218893Sdim if (ID->getClassInterface()->getVisibility() == HiddenVisibility) 2306193326Sed Flags |= eClassFlags_Hidden; 2307198092Srdivacky 2308193326Sed std::vector<llvm::Constant*> Values(12); 2309193326Sed // The isa for the metaclass is the root of the hierarchy. 2310193326Sed const ObjCInterfaceDecl *Root = ID->getClassInterface(); 2311193326Sed while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) 2312193326Sed Root = Super; 2313198092Srdivacky Values[ 0] = 2314193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()), 2315193326Sed ObjCTypes.ClassPtrTy); 2316193326Sed // The super class for the metaclass is emitted as the name of the 2317193326Sed // super class. The runtime fixes this up to point to the 2318193326Sed // *metaclass* for the super class. 2319193326Sed if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) { 2320198092Srdivacky Values[ 1] = 2321193326Sed llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), 2322193326Sed ObjCTypes.ClassPtrTy); 2323193326Sed } else { 2324193326Sed Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy); 2325193326Sed } 2326193326Sed Values[ 2] = GetClassName(ID->getIdentifier()); 2327193326Sed // Version is always 0. 2328193326Sed Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 2329193326Sed Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); 2330193326Sed Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 2331193326Sed Values[ 6] = EmitIvarList(ID, true); 2332198092Srdivacky Values[ 7] = 2333193326Sed EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(), 2334193326Sed "__OBJC,__cls_meth,regular,no_dead_strip", 2335193326Sed Methods); 2336193326Sed // cache is always NULL. 2337193326Sed Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy); 2338193326Sed Values[ 9] = Protocols; 2339193326Sed // ivar_layout for metaclass is always NULL. 2340193326Sed Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 2341193326Sed // The class extension is always unused for metaclasses. 2342193326Sed Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); 2343193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy, 2344193326Sed Values); 2345193326Sed 2346193326Sed std::string Name("\01L_OBJC_METACLASS_"); 2347193326Sed Name += ID->getNameAsCString(); 2348193326Sed 2349193326Sed // Check for a forward reference. 2350193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 2351193326Sed if (GV) { 2352193326Sed assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2353193326Sed "Forward metaclass reference has incorrect type."); 2354193326Sed GV->setLinkage(llvm::GlobalValue::InternalLinkage); 2355193326Sed GV->setInitializer(Init); 2356193326Sed } else { 2357198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 2358193326Sed llvm::GlobalValue::InternalLinkage, 2359198092Srdivacky Init, Name); 2360193326Sed } 2361193326Sed GV->setSection("__OBJC,__meta_class,regular,no_dead_strip"); 2362193326Sed GV->setAlignment(4); 2363198092Srdivacky CGM.AddUsedGlobal(GV); 2364193326Sed 2365193326Sed return GV; 2366193326Sed} 2367193326Sed 2368198092Srdivackyllvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) { 2369193326Sed std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString(); 2370193326Sed 2371193326Sed // FIXME: Should we look these up somewhere other than the module. Its a bit 2372193326Sed // silly since we only generate these while processing an implementation, so 2373193326Sed // exactly one pointer would work if know when we entered/exitted an 2374193326Sed // implementation block. 2375193326Sed 2376193326Sed // Check for an existing forward reference. 2377193326Sed // Previously, metaclass with internal linkage may have been defined. 2378193326Sed // pass 'true' as 2nd argument so it is returned. 2379198092Srdivacky if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, 2380198092Srdivacky true)) { 2381193326Sed assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2382193326Sed "Forward metaclass reference has incorrect type."); 2383193326Sed return GV; 2384193326Sed } else { 2385193326Sed // Generate as an external reference to keep a consistent 2386193326Sed // module. This will be patched up when we emit the metaclass. 2387198092Srdivacky return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 2388193326Sed llvm::GlobalValue::ExternalLinkage, 2389193326Sed 0, 2390198092Srdivacky Name); 2391193326Sed } 2392193326Sed} 2393193326Sed 2394199482Srdivackyllvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) { 2395199482Srdivacky std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString(); 2396199482Srdivacky 2397199482Srdivacky if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, 2398199482Srdivacky true)) { 2399199482Srdivacky assert(GV->getType()->getElementType() == ObjCTypes.ClassTy && 2400199482Srdivacky "Forward class metadata reference has incorrect type."); 2401199482Srdivacky return GV; 2402199482Srdivacky } else { 2403199482Srdivacky return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false, 2404199482Srdivacky llvm::GlobalValue::ExternalLinkage, 2405199482Srdivacky 0, 2406199482Srdivacky Name); 2407199482Srdivacky } 2408199482Srdivacky} 2409199482Srdivacky 2410193326Sed/* 2411193326Sed struct objc_class_ext { 2412198092Srdivacky uint32_t size; 2413198092Srdivacky const char *weak_ivar_layout; 2414198092Srdivacky struct _objc_property_list *properties; 2415193326Sed }; 2416193326Sed*/ 2417193326Sedllvm::Constant * 2418193326SedCGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) { 2419198092Srdivacky uint64_t Size = 2420193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy); 2421193326Sed 2422193326Sed std::vector<llvm::Constant*> Values(3); 2423193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 2424193326Sed Values[1] = BuildIvarLayout(ID, false); 2425198398Srdivacky Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), 2426193326Sed ID, ID->getClassInterface(), ObjCTypes); 2427193326Sed 2428193326Sed // Return null if no extension bits are used. 2429193326Sed if (Values[1]->isNullValue() && Values[2]->isNullValue()) 2430193326Sed return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy); 2431193326Sed 2432198092Srdivacky llvm::Constant *Init = 2433193326Sed llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values); 2434198398Srdivacky return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(), 2435198092Srdivacky Init, "__OBJC,__class_ext,regular,no_dead_strip", 2436193326Sed 4, true); 2437193326Sed} 2438193326Sed 2439193326Sed/* 2440193326Sed struct objc_ivar { 2441198092Srdivacky char *ivar_name; 2442198092Srdivacky char *ivar_type; 2443198092Srdivacky int ivar_offset; 2444193326Sed }; 2445193326Sed 2446193326Sed struct objc_ivar_list { 2447198092Srdivacky int ivar_count; 2448198092Srdivacky struct objc_ivar list[count]; 2449193326Sed }; 2450198092Srdivacky*/ 2451193326Sedllvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, 2452193326Sed bool ForClass) { 2453193326Sed std::vector<llvm::Constant*> Ivars, Ivar(3); 2454193326Sed 2455193326Sed // When emitting the root class GCC emits ivar entries for the 2456193326Sed // actual class structure. It is not clear if we need to follow this 2457193326Sed // behavior; for now lets try and get away with not doing it. If so, 2458193326Sed // the cleanest solution would be to make up an ObjCInterfaceDecl 2459193326Sed // for the class. 2460193326Sed if (ForClass) 2461193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); 2462198092Srdivacky 2463198092Srdivacky ObjCInterfaceDecl *OID = 2464193326Sed const_cast<ObjCInterfaceDecl*>(ID->getClassInterface()); 2465198092Srdivacky 2466193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; 2467193576Sed CGM.getContext().ShallowCollectObjCIvars(OID, OIvars); 2468198092Srdivacky 2469193326Sed for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { 2470193326Sed ObjCIvarDecl *IVD = OIvars[i]; 2471193576Sed // Ignore unnamed bit-fields. 2472193576Sed if (!IVD->getDeclName()) 2473198092Srdivacky continue; 2474193326Sed Ivar[0] = GetMethodVarName(IVD->getIdentifier()); 2475193326Sed Ivar[1] = GetMethodVarType(IVD); 2476198092Srdivacky Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, 2477193326Sed ComputeIvarBaseOffset(CGM, OID, IVD)); 2478193326Sed Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar)); 2479193326Sed } 2480193326Sed 2481193326Sed // Return null for empty list. 2482193326Sed if (Ivars.empty()) 2483193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy); 2484193326Sed 2485193326Sed std::vector<llvm::Constant*> Values(2); 2486193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size()); 2487193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy, 2488193326Sed Ivars.size()); 2489193326Sed Values[1] = llvm::ConstantArray::get(AT, Ivars); 2490198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 2491193326Sed 2492193326Sed llvm::GlobalVariable *GV; 2493193326Sed if (ForClass) 2494198398Srdivacky GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(), 2495198092Srdivacky Init, "__OBJC,__class_vars,regular,no_dead_strip", 2496193326Sed 4, true); 2497193326Sed else 2498198398Srdivacky GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(), 2499193326Sed Init, "__OBJC,__instance_vars,regular,no_dead_strip", 2500193326Sed 4, true); 2501193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy); 2502193326Sed} 2503193326Sed 2504193326Sed/* 2505193326Sed struct objc_method { 2506198092Srdivacky SEL method_name; 2507198092Srdivacky char *method_types; 2508198092Srdivacky void *method; 2509193326Sed }; 2510198092Srdivacky 2511193326Sed struct objc_method_list { 2512198092Srdivacky struct objc_method_list *obsolete; 2513198092Srdivacky int count; 2514198092Srdivacky struct objc_method methods_list[count]; 2515193326Sed }; 2516193326Sed*/ 2517193326Sed 2518193326Sed/// GetMethodConstant - Return a struct objc_method constant for the 2519193326Sed/// given method if it has been defined. The result is null if the 2520193326Sed/// method has not been defined. The return value has type MethodPtrTy. 2521193326Sedllvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) { 2522212904Sdim llvm::Function *Fn = GetMethodDefinition(MD); 2523193326Sed if (!Fn) 2524193326Sed return 0; 2525198092Srdivacky 2526193326Sed std::vector<llvm::Constant*> Method(3); 2527198092Srdivacky Method[0] = 2528193326Sed llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 2529193326Sed ObjCTypes.SelectorPtrTy); 2530193326Sed Method[1] = GetMethodVarType(MD); 2531193326Sed Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy); 2532193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method); 2533193326Sed} 2534193326Sed 2535198398Srdivackyllvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name, 2536193326Sed const char *Section, 2537193326Sed const ConstantVector &Methods) { 2538193326Sed // Return null for empty list. 2539193326Sed if (Methods.empty()) 2540193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy); 2541193326Sed 2542193326Sed std::vector<llvm::Constant*> Values(3); 2543193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 2544193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 2545193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy, 2546193326Sed Methods.size()); 2547193326Sed Values[2] = llvm::ConstantArray::get(AT, Methods); 2548198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 2549193326Sed 2550193326Sed llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true); 2551193326Sed return llvm::ConstantExpr::getBitCast(GV, 2552193326Sed ObjCTypes.MethodListPtrTy); 2553193326Sed} 2554193326Sed 2555193326Sedllvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD, 2556198092Srdivacky const ObjCContainerDecl *CD) { 2557198398Srdivacky llvm::SmallString<256> Name; 2558193326Sed GetNameForMethod(OMD, CD, Name); 2559193326Sed 2560193326Sed CodeGenTypes &Types = CGM.getTypes(); 2561193326Sed const llvm::FunctionType *MethodTy = 2562193326Sed Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic()); 2563198092Srdivacky llvm::Function *Method = 2564193326Sed llvm::Function::Create(MethodTy, 2565193326Sed llvm::GlobalValue::InternalLinkage, 2566198398Srdivacky Name.str(), 2567193326Sed &CGM.getModule()); 2568193326Sed MethodDefinitions.insert(std::make_pair(OMD, Method)); 2569193326Sed 2570193326Sed return Method; 2571193326Sed} 2572193326Sed 2573193326Sedllvm::GlobalVariable * 2574198398SrdivackyCGObjCCommonMac::CreateMetadataVar(llvm::Twine Name, 2575193326Sed llvm::Constant *Init, 2576193326Sed const char *Section, 2577193326Sed unsigned Align, 2578193326Sed bool AddToUsed) { 2579193326Sed const llvm::Type *Ty = Init->getType(); 2580198092Srdivacky llvm::GlobalVariable *GV = 2581198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Ty, false, 2582198092Srdivacky llvm::GlobalValue::InternalLinkage, Init, Name); 2583193326Sed if (Section) 2584193326Sed GV->setSection(Section); 2585193326Sed if (Align) 2586193326Sed GV->setAlignment(Align); 2587193326Sed if (AddToUsed) 2588198092Srdivacky CGM.AddUsedGlobal(GV); 2589193326Sed return GV; 2590193326Sed} 2591193326Sed 2592198092Srdivackyllvm::Function *CGObjCMac::ModuleInitFunction() { 2593193326Sed // Abuse this interface function as a place to finalize. 2594193326Sed FinishModule(); 2595193326Sed return NULL; 2596193326Sed} 2597193326Sed 2598193326Sedllvm::Constant *CGObjCMac::GetPropertyGetFunction() { 2599193326Sed return ObjCTypes.getGetPropertyFn(); 2600193326Sed} 2601193326Sed 2602193326Sedllvm::Constant *CGObjCMac::GetPropertySetFunction() { 2603193326Sed return ObjCTypes.getSetPropertyFn(); 2604193326Sed} 2605193326Sed 2606218893Sdimllvm::Constant *CGObjCMac::GetGetStructFunction() { 2607207619Srdivacky return ObjCTypes.getCopyStructFn(); 2608207619Srdivacky} 2609218893Sdimllvm::Constant *CGObjCMac::GetSetStructFunction() { 2610218893Sdim return ObjCTypes.getCopyStructFn(); 2611218893Sdim} 2612207619Srdivacky 2613193326Sedllvm::Constant *CGObjCMac::EnumerationMutationFunction() { 2614193326Sed return ObjCTypes.getEnumerationMutationFn(); 2615193326Sed} 2616193326Sed 2617210299Sedvoid CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) { 2618210299Sed return EmitTryOrSynchronizedStmt(CGF, S); 2619210299Sed} 2620210299Sed 2621210299Sedvoid CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF, 2622210299Sed const ObjCAtSynchronizedStmt &S) { 2623210299Sed return EmitTryOrSynchronizedStmt(CGF, S); 2624210299Sed} 2625210299Sed 2626212904Sdimnamespace { 2627212904Sdim struct PerformFragileFinally : EHScopeStack::Cleanup { 2628212904Sdim const Stmt &S; 2629212904Sdim llvm::Value *SyncArgSlot; 2630212904Sdim llvm::Value *CallTryExitVar; 2631212904Sdim llvm::Value *ExceptionData; 2632212904Sdim ObjCTypesHelper &ObjCTypes; 2633212904Sdim PerformFragileFinally(const Stmt *S, 2634212904Sdim llvm::Value *SyncArgSlot, 2635212904Sdim llvm::Value *CallTryExitVar, 2636212904Sdim llvm::Value *ExceptionData, 2637212904Sdim ObjCTypesHelper *ObjCTypes) 2638212904Sdim : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar), 2639212904Sdim ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {} 2640212904Sdim 2641212904Sdim void Emit(CodeGenFunction &CGF, bool IsForEH) { 2642212904Sdim // Check whether we need to call objc_exception_try_exit. 2643212904Sdim // In optimized code, this branch will always be folded. 2644212904Sdim llvm::BasicBlock *FinallyCallExit = 2645212904Sdim CGF.createBasicBlock("finally.call_exit"); 2646212904Sdim llvm::BasicBlock *FinallyNoCallExit = 2647212904Sdim CGF.createBasicBlock("finally.no_call_exit"); 2648212904Sdim CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar), 2649212904Sdim FinallyCallExit, FinallyNoCallExit); 2650212904Sdim 2651212904Sdim CGF.EmitBlock(FinallyCallExit); 2652212904Sdim CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData) 2653212904Sdim ->setDoesNotThrow(); 2654212904Sdim 2655212904Sdim CGF.EmitBlock(FinallyNoCallExit); 2656212904Sdim 2657212904Sdim if (isa<ObjCAtTryStmt>(S)) { 2658212904Sdim if (const ObjCAtFinallyStmt* FinallyStmt = 2659212904Sdim cast<ObjCAtTryStmt>(S).getFinallyStmt()) { 2660212904Sdim // Save the current cleanup destination in case there's 2661212904Sdim // control flow inside the finally statement. 2662212904Sdim llvm::Value *CurCleanupDest = 2663212904Sdim CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot()); 2664212904Sdim 2665212904Sdim CGF.EmitStmt(FinallyStmt->getFinallyBody()); 2666212904Sdim 2667212904Sdim if (CGF.HaveInsertPoint()) { 2668212904Sdim CGF.Builder.CreateStore(CurCleanupDest, 2669212904Sdim CGF.getNormalCleanupDestSlot()); 2670212904Sdim } else { 2671212904Sdim // Currently, the end of the cleanup must always exist. 2672212904Sdim CGF.EnsureInsertPoint(); 2673212904Sdim } 2674212904Sdim } 2675212904Sdim } else { 2676212904Sdim // Emit objc_sync_exit(expr); as finally's sole statement for 2677212904Sdim // @synchronized. 2678212904Sdim llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot); 2679212904Sdim CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg) 2680212904Sdim ->setDoesNotThrow(); 2681212904Sdim } 2682212904Sdim } 2683212904Sdim }; 2684212904Sdim 2685212904Sdim class FragileHazards { 2686212904Sdim CodeGenFunction &CGF; 2687212904Sdim llvm::SmallVector<llvm::Value*, 20> Locals; 2688212904Sdim llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry; 2689212904Sdim 2690212904Sdim llvm::InlineAsm *ReadHazard; 2691212904Sdim llvm::InlineAsm *WriteHazard; 2692212904Sdim 2693212904Sdim llvm::FunctionType *GetAsmFnType(); 2694212904Sdim 2695212904Sdim void collectLocals(); 2696212904Sdim void emitReadHazard(CGBuilderTy &Builder); 2697212904Sdim 2698212904Sdim public: 2699212904Sdim FragileHazards(CodeGenFunction &CGF); 2700212904Sdim 2701212904Sdim void emitWriteHazard(); 2702212904Sdim void emitHazardsInNewBlocks(); 2703212904Sdim }; 2704212904Sdim} 2705212904Sdim 2706212904Sdim/// Create the fragile-ABI read and write hazards based on the current 2707212904Sdim/// state of the function, which is presumed to be immediately prior 2708212904Sdim/// to a @try block. These hazards are used to maintain correct 2709212904Sdim/// semantics in the face of optimization and the fragile ABI's 2710212904Sdim/// cavalier use of setjmp/longjmp. 2711212904SdimFragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) { 2712212904Sdim collectLocals(); 2713212904Sdim 2714212904Sdim if (Locals.empty()) return; 2715212904Sdim 2716212904Sdim // Collect all the blocks in the function. 2717212904Sdim for (llvm::Function::iterator 2718212904Sdim I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I) 2719212904Sdim BlocksBeforeTry.insert(&*I); 2720212904Sdim 2721212904Sdim llvm::FunctionType *AsmFnTy = GetAsmFnType(); 2722212904Sdim 2723212904Sdim // Create a read hazard for the allocas. This inhibits dead-store 2724212904Sdim // optimizations and forces the values to memory. This hazard is 2725212904Sdim // inserted before any 'throwing' calls in the protected scope to 2726212904Sdim // reflect the possibility that the variables might be read from the 2727212904Sdim // catch block if the call throws. 2728212904Sdim { 2729212904Sdim std::string Constraint; 2730212904Sdim for (unsigned I = 0, E = Locals.size(); I != E; ++I) { 2731212904Sdim if (I) Constraint += ','; 2732212904Sdim Constraint += "*m"; 2733212904Sdim } 2734212904Sdim 2735212904Sdim ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false); 2736212904Sdim } 2737212904Sdim 2738212904Sdim // Create a write hazard for the allocas. This inhibits folding 2739212904Sdim // loads across the hazard. This hazard is inserted at the 2740212904Sdim // beginning of the catch path to reflect the possibility that the 2741212904Sdim // variables might have been written within the protected scope. 2742212904Sdim { 2743212904Sdim std::string Constraint; 2744212904Sdim for (unsigned I = 0, E = Locals.size(); I != E; ++I) { 2745212904Sdim if (I) Constraint += ','; 2746212904Sdim Constraint += "=*m"; 2747212904Sdim } 2748212904Sdim 2749212904Sdim WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false); 2750212904Sdim } 2751212904Sdim} 2752212904Sdim 2753212904Sdim/// Emit a write hazard at the current location. 2754212904Sdimvoid FragileHazards::emitWriteHazard() { 2755212904Sdim if (Locals.empty()) return; 2756212904Sdim 2757212904Sdim CGF.Builder.CreateCall(WriteHazard, Locals.begin(), Locals.end()) 2758212904Sdim ->setDoesNotThrow(); 2759212904Sdim} 2760212904Sdim 2761212904Sdimvoid FragileHazards::emitReadHazard(CGBuilderTy &Builder) { 2762212904Sdim assert(!Locals.empty()); 2763212904Sdim Builder.CreateCall(ReadHazard, Locals.begin(), Locals.end()) 2764212904Sdim ->setDoesNotThrow(); 2765212904Sdim} 2766212904Sdim 2767212904Sdim/// Emit read hazards in all the protected blocks, i.e. all the blocks 2768212904Sdim/// which have been inserted since the beginning of the try. 2769212904Sdimvoid FragileHazards::emitHazardsInNewBlocks() { 2770212904Sdim if (Locals.empty()) return; 2771212904Sdim 2772212904Sdim CGBuilderTy Builder(CGF.getLLVMContext()); 2773212904Sdim 2774212904Sdim // Iterate through all blocks, skipping those prior to the try. 2775212904Sdim for (llvm::Function::iterator 2776212904Sdim FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) { 2777212904Sdim llvm::BasicBlock &BB = *FI; 2778212904Sdim if (BlocksBeforeTry.count(&BB)) continue; 2779212904Sdim 2780212904Sdim // Walk through all the calls in the block. 2781212904Sdim for (llvm::BasicBlock::iterator 2782212904Sdim BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) { 2783212904Sdim llvm::Instruction &I = *BI; 2784212904Sdim 2785212904Sdim // Ignore instructions that aren't non-intrinsic calls. 2786212904Sdim // These are the only calls that can possibly call longjmp. 2787212904Sdim if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue; 2788212904Sdim if (isa<llvm::IntrinsicInst>(I)) 2789212904Sdim continue; 2790212904Sdim 2791212904Sdim // Ignore call sites marked nounwind. This may be questionable, 2792212904Sdim // since 'nounwind' doesn't necessarily mean 'does not call longjmp'. 2793212904Sdim llvm::CallSite CS(&I); 2794212904Sdim if (CS.doesNotThrow()) continue; 2795212904Sdim 2796212904Sdim // Insert a read hazard before the call. This will ensure that 2797212904Sdim // any writes to the locals are performed before making the 2798212904Sdim // call. If the call throws, then this is sufficient to 2799212904Sdim // guarantee correctness as long as it doesn't also write to any 2800212904Sdim // locals. 2801212904Sdim Builder.SetInsertPoint(&BB, BI); 2802212904Sdim emitReadHazard(Builder); 2803212904Sdim } 2804212904Sdim } 2805212904Sdim} 2806212904Sdim 2807212904Sdimstatic void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) { 2808212904Sdim if (V) S.insert(V); 2809212904Sdim} 2810212904Sdim 2811212904Sdimvoid FragileHazards::collectLocals() { 2812212904Sdim // Compute a set of allocas to ignore. 2813212904Sdim llvm::DenseSet<llvm::Value*> AllocasToIgnore; 2814212904Sdim addIfPresent(AllocasToIgnore, CGF.ReturnValue); 2815212904Sdim addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest); 2816212904Sdim addIfPresent(AllocasToIgnore, CGF.EHCleanupDest); 2817212904Sdim 2818212904Sdim // Collect all the allocas currently in the function. This is 2819212904Sdim // probably way too aggressive. 2820212904Sdim llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock(); 2821212904Sdim for (llvm::BasicBlock::iterator 2822212904Sdim I = Entry.begin(), E = Entry.end(); I != E; ++I) 2823212904Sdim if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I)) 2824212904Sdim Locals.push_back(&*I); 2825212904Sdim} 2826212904Sdim 2827212904Sdimllvm::FunctionType *FragileHazards::GetAsmFnType() { 2828212904Sdim std::vector<const llvm::Type *> Tys(Locals.size()); 2829212904Sdim for (unsigned I = 0, E = Locals.size(); I != E; ++I) 2830212904Sdim Tys[I] = Locals[I]->getType(); 2831212904Sdim return llvm::FunctionType::get(CGF.Builder.getVoidTy(), Tys, false); 2832212904Sdim} 2833212904Sdim 2834198092Srdivacky/* 2835193326Sed 2836198092Srdivacky Objective-C setjmp-longjmp (sjlj) Exception Handling 2837198092Srdivacky -- 2838193326Sed 2839210299Sed A catch buffer is a setjmp buffer plus: 2840210299Sed - a pointer to the exception that was caught 2841210299Sed - a pointer to the previous exception data buffer 2842210299Sed - two pointers of reserved storage 2843210299Sed Therefore catch buffers form a stack, with a pointer to the top 2844210299Sed of the stack kept in thread-local storage. 2845210299Sed 2846210299Sed objc_exception_try_enter pushes a catch buffer onto the EH stack. 2847210299Sed objc_exception_try_exit pops the given catch buffer, which is 2848210299Sed required to be the top of the EH stack. 2849210299Sed objc_exception_throw pops the top of the EH stack, writes the 2850210299Sed thrown exception into the appropriate field, and longjmps 2851210299Sed to the setjmp buffer. It crashes the process (with a printf 2852210299Sed and an abort()) if there are no catch buffers on the stack. 2853210299Sed objc_exception_extract just reads the exception pointer out of the 2854210299Sed catch buffer. 2855210299Sed 2856210299Sed There's no reason an implementation couldn't use a light-weight 2857210299Sed setjmp here --- something like __builtin_setjmp, but API-compatible 2858210299Sed with the heavyweight setjmp. This will be more important if we ever 2859210299Sed want to implement correct ObjC/C++ exception interactions for the 2860210299Sed fragile ABI. 2861210299Sed 2862210299Sed Note that for this use of setjmp/longjmp to be correct, we may need 2863210299Sed to mark some local variables volatile: if a non-volatile local 2864210299Sed variable is modified between the setjmp and the longjmp, it has 2865210299Sed indeterminate value. For the purposes of LLVM IR, it may be 2866210299Sed sufficient to make loads and stores within the @try (to variables 2867210299Sed declared outside the @try) volatile. This is necessary for 2868210299Sed optimized correctness, but is not currently being done; this is 2869210299Sed being tracked as rdar://problem/8160285 2870210299Sed 2871198092Srdivacky The basic framework for a @try-catch-finally is as follows: 2872198092Srdivacky { 2873193326Sed objc_exception_data d; 2874193326Sed id _rethrow = null; 2875193326Sed bool _call_try_exit = true; 2876198092Srdivacky 2877193326Sed objc_exception_try_enter(&d); 2878193326Sed if (!setjmp(d.jmp_buf)) { 2879198092Srdivacky ... try body ... 2880193326Sed } else { 2881198092Srdivacky // exception path 2882198092Srdivacky id _caught = objc_exception_extract(&d); 2883198092Srdivacky 2884198092Srdivacky // enter new try scope for handlers 2885198092Srdivacky if (!setjmp(d.jmp_buf)) { 2886198092Srdivacky ... match exception and execute catch blocks ... 2887198092Srdivacky 2888198092Srdivacky // fell off end, rethrow. 2889198092Srdivacky _rethrow = _caught; 2890198092Srdivacky ... jump-through-finally to finally_rethrow ... 2891198092Srdivacky } else { 2892198092Srdivacky // exception in catch block 2893198092Srdivacky _rethrow = objc_exception_extract(&d); 2894198092Srdivacky _call_try_exit = false; 2895198092Srdivacky ... jump-through-finally to finally_rethrow ... 2896193326Sed } 2897198092Srdivacky } 2898193326Sed ... jump-through-finally to finally_end ... 2899193326Sed 2900198092Srdivacky finally: 2901193326Sed if (_call_try_exit) 2902198092Srdivacky objc_exception_try_exit(&d); 2903193326Sed 2904193326Sed ... finally block .... 2905193326Sed ... dispatch to finally destination ... 2906193326Sed 2907198092Srdivacky finally_rethrow: 2908193326Sed objc_exception_throw(_rethrow); 2909193326Sed 2910198092Srdivacky finally_end: 2911198092Srdivacky } 2912193326Sed 2913198092Srdivacky This framework differs slightly from the one gcc uses, in that gcc 2914198092Srdivacky uses _rethrow to determine if objc_exception_try_exit should be called 2915198092Srdivacky and if the object should be rethrown. This breaks in the face of 2916198092Srdivacky throwing nil and introduces unnecessary branches. 2917193326Sed 2918198092Srdivacky We specialize this framework for a few particular circumstances: 2919193326Sed 2920198092Srdivacky - If there are no catch blocks, then we avoid emitting the second 2921198092Srdivacky exception handling context. 2922193326Sed 2923198092Srdivacky - If there is a catch-all catch block (i.e. @catch(...) or @catch(id 2924198092Srdivacky e)) we avoid emitting the code to rethrow an uncaught exception. 2925193326Sed 2926198092Srdivacky - FIXME: If there is no @finally block we can do a few more 2927198092Srdivacky simplifications. 2928193326Sed 2929198092Srdivacky Rethrows and Jumps-Through-Finally 2930198092Srdivacky -- 2931193326Sed 2932210299Sed '@throw;' is supported by pushing the currently-caught exception 2933210299Sed onto ObjCEHStack while the @catch blocks are emitted. 2934193326Sed 2935210299Sed Branches through the @finally block are handled with an ordinary 2936210299Sed normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC 2937210299Sed exceptions are not compatible with C++ exceptions, and this is 2938210299Sed hardly the only place where this will go wrong. 2939193326Sed 2940210299Sed @synchronized(expr) { stmt; } is emitted as if it were: 2941210299Sed id synch_value = expr; 2942210299Sed objc_sync_enter(synch_value); 2943210299Sed @try { stmt; } @finally { objc_sync_exit(synch_value); } 2944193326Sed*/ 2945193326Sed 2946193326Sedvoid CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 2947193326Sed const Stmt &S) { 2948193326Sed bool isTry = isa<ObjCAtTryStmt>(S); 2949198092Srdivacky 2950210299Sed // A destination for the fall-through edges of the catch handlers to 2951210299Sed // jump to. 2952210299Sed CodeGenFunction::JumpDest FinallyEnd = 2953210299Sed CGF.getJumpDestInCurrentScope("finally.end"); 2954210299Sed 2955210299Sed // A destination for the rethrow edge of the catch handlers to jump 2956210299Sed // to. 2957210299Sed CodeGenFunction::JumpDest FinallyRethrow = 2958210299Sed CGF.getJumpDestInCurrentScope("finally.rethrow"); 2959210299Sed 2960193326Sed // For @synchronized, call objc_sync_enter(sync.expr). The 2961193326Sed // evaluation of the expression must occur before we enter the 2962212904Sdim // @synchronized. We can't avoid a temp here because we need the 2963212904Sdim // value to be preserved. If the backend ever does liveness 2964212904Sdim // correctly after setjmp, this will be unnecessary. 2965212904Sdim llvm::Value *SyncArgSlot = 0; 2966193326Sed if (!isTry) { 2967212904Sdim llvm::Value *SyncArg = 2968193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 2969193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); 2970210299Sed CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg) 2971210299Sed ->setDoesNotThrow(); 2972212904Sdim 2973212904Sdim SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg"); 2974212904Sdim CGF.Builder.CreateStore(SyncArg, SyncArgSlot); 2975193326Sed } 2976193326Sed 2977212904Sdim // Allocate memory for the setjmp buffer. This needs to be kept 2978212904Sdim // live throughout the try and catch blocks. 2979193326Sed llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy, 2980193326Sed "exceptiondata.ptr"); 2981210299Sed 2982212904Sdim // Create the fragile hazards. Note that this will not capture any 2983212904Sdim // of the allocas required for exception processing, but will 2984212904Sdim // capture the current basic block (which extends all the way to the 2985212904Sdim // setjmp call) as "before the @try". 2986212904Sdim FragileHazards Hazards(CGF); 2987212904Sdim 2988210299Sed // Create a flag indicating whether the cleanup needs to call 2989210299Sed // objc_exception_try_exit. This is true except when 2990210299Sed // - no catches match and we're branching through the cleanup 2991210299Sed // just to rethrow the exception, or 2992210299Sed // - a catch matched and we're falling out of the catch handler. 2993212904Sdim // The setjmp-safety rule here is that we should always store to this 2994212904Sdim // variable in a place that dominates the branch through the cleanup 2995212904Sdim // without passing through any setjmps. 2996210299Sed llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), 2997193326Sed "_call_try_exit"); 2998198092Srdivacky 2999218893Sdim // A slot containing the exception to rethrow. Only needed when we 3000218893Sdim // have both a @catch and a @finally. 3001218893Sdim llvm::Value *PropagatingExnVar = 0; 3002218893Sdim 3003210299Sed // Push a normal cleanup to leave the try scope. 3004212904Sdim CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S, 3005212904Sdim SyncArgSlot, 3006212904Sdim CallTryExitVar, 3007212904Sdim ExceptionData, 3008212904Sdim &ObjCTypes); 3009193326Sed 3010210299Sed // Enter a try block: 3011210299Sed // - Call objc_exception_try_enter to push ExceptionData on top of 3012210299Sed // the EH stack. 3013210299Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData) 3014210299Sed ->setDoesNotThrow(); 3015210299Sed 3016210299Sed // - Call setjmp on the exception data buffer. 3017210299Sed llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); 3018210299Sed llvm::Value *GEPIndexes[] = { Zero, Zero, Zero }; 3019210299Sed llvm::Value *SetJmpBuffer = 3020210299Sed CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, GEPIndexes+3, "setjmp_buffer"); 3021210299Sed llvm::CallInst *SetJmpResult = 3022210299Sed CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result"); 3023210299Sed SetJmpResult->setDoesNotThrow(); 3024210299Sed 3025210299Sed // If setjmp returned 0, enter the protected block; otherwise, 3026210299Sed // branch to the handler. 3027193326Sed llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); 3028193326Sed llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); 3029210299Sed llvm::Value *DidCatch = 3030212904Sdim CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); 3031212904Sdim CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock); 3032193326Sed 3033210299Sed // Emit the protected block. 3034193326Sed CGF.EmitBlock(TryBlock); 3035212904Sdim CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar); 3036198092Srdivacky CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() 3037210299Sed : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); 3038198092Srdivacky 3039212904Sdim CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP(); 3040212904Sdim 3041210299Sed // Emit the exception handler block. 3042193326Sed CGF.EmitBlock(TryHandler); 3043193326Sed 3044212904Sdim // Don't optimize loads of the in-scope locals across this point. 3045212904Sdim Hazards.emitWriteHazard(); 3046210299Sed 3047210299Sed // For a @synchronized (or a @try with no catches), just branch 3048210299Sed // through the cleanup to the rethrow block. 3049210299Sed if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) { 3050210299Sed // Tell the cleanup not to re-pop the exit. 3051212904Sdim CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar); 3052193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 3053210299Sed 3054210299Sed // Otherwise, we have to match against the caught exceptions. 3055210299Sed } else { 3056212904Sdim // Retrieve the exception object. We may emit multiple blocks but 3057212904Sdim // nothing can cross this so the value is already in SSA form. 3058212904Sdim llvm::CallInst *Caught = 3059212904Sdim CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(), 3060212904Sdim ExceptionData, "caught"); 3061212904Sdim Caught->setDoesNotThrow(); 3062212904Sdim 3063210299Sed // Push the exception to rethrow onto the EH value stack for the 3064210299Sed // benefit of any @throws in the handlers. 3065210299Sed CGF.ObjCEHValueStack.push_back(Caught); 3066210299Sed 3067207619Srdivacky const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S); 3068198092Srdivacky 3069212904Sdim bool HasFinally = (AtTryStmt->getFinallyStmt() != 0); 3070193326Sed 3071212904Sdim llvm::BasicBlock *CatchBlock = 0; 3072212904Sdim llvm::BasicBlock *CatchHandler = 0; 3073212904Sdim if (HasFinally) { 3074218893Sdim // Save the currently-propagating exception before 3075218893Sdim // objc_exception_try_enter clears the exception slot. 3076218893Sdim PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(), 3077218893Sdim "propagating_exception"); 3078218893Sdim CGF.Builder.CreateStore(Caught, PropagatingExnVar); 3079218893Sdim 3080212904Sdim // Enter a new exception try block (in case a @catch block 3081212904Sdim // throws an exception). 3082212904Sdim CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData) 3083212904Sdim ->setDoesNotThrow(); 3084210299Sed 3085212904Sdim llvm::CallInst *SetJmpResult = 3086212904Sdim CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, 3087212904Sdim "setjmp.result"); 3088212904Sdim SetJmpResult->setDoesNotThrow(); 3089198092Srdivacky 3090212904Sdim llvm::Value *Threw = 3091212904Sdim CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); 3092198092Srdivacky 3093212904Sdim CatchBlock = CGF.createBasicBlock("catch"); 3094212904Sdim CatchHandler = CGF.createBasicBlock("catch_for_catch"); 3095212904Sdim CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock); 3096212904Sdim 3097212904Sdim CGF.EmitBlock(CatchBlock); 3098212904Sdim } 3099212904Sdim 3100212904Sdim CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar); 3101212904Sdim 3102193326Sed // Handle catch list. As a special case we check if everything is 3103193326Sed // matched and avoid generating code for falling off the end if 3104193326Sed // so. 3105193326Sed bool AllMatched = false; 3106207619Srdivacky for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) { 3107207619Srdivacky const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I); 3108193326Sed 3109207619Srdivacky const VarDecl *CatchParam = CatchStmt->getCatchParamDecl(); 3110198092Srdivacky const ObjCObjectPointerType *OPT = 0; 3111193326Sed 3112193326Sed // catch(...) always matches. 3113193326Sed if (!CatchParam) { 3114193326Sed AllMatched = true; 3115193326Sed } else { 3116198092Srdivacky OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>(); 3117198092Srdivacky 3118210299Sed // catch(id e) always matches under this ABI, since only 3119210299Sed // ObjC exceptions end up here in the first place. 3120193326Sed // FIXME: For the time being we also match id<X>; this should 3121193326Sed // be rejected by Sema instead. 3122198092Srdivacky if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())) 3123193326Sed AllMatched = true; 3124193326Sed } 3125198092Srdivacky 3126210299Sed // If this is a catch-all, we don't need to test anything. 3127198092Srdivacky if (AllMatched) { 3128210299Sed CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF); 3129210299Sed 3130193326Sed if (CatchParam) { 3131218893Sdim CGF.EmitAutoVarDecl(*CatchParam); 3132193326Sed assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); 3133210299Sed 3134210299Sed // These types work out because ConvertType(id) == i8*. 3135193326Sed CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam)); 3136193326Sed } 3137198092Srdivacky 3138193326Sed CGF.EmitStmt(CatchStmt->getCatchBody()); 3139210299Sed 3140210299Sed // The scope of the catch variable ends right here. 3141210299Sed CatchVarCleanups.ForceCleanup(); 3142210299Sed 3143193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 3144193326Sed break; 3145193326Sed } 3146198092Srdivacky 3147198092Srdivacky assert(OPT && "Unexpected non-object pointer type in @catch"); 3148208600Srdivacky const ObjCObjectType *ObjTy = OPT->getObjectType(); 3149210299Sed 3150210299Sed // FIXME: @catch (Class c) ? 3151208600Srdivacky ObjCInterfaceDecl *IDecl = ObjTy->getInterface(); 3152208600Srdivacky assert(IDecl && "Catch parameter must have Objective-C type!"); 3153193326Sed 3154193326Sed // Check if the @catch block matches the exception object. 3155208600Srdivacky llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl); 3156198092Srdivacky 3157210299Sed llvm::CallInst *Match = 3158193326Sed CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(), 3159193326Sed Class, Caught, "match"); 3160210299Sed Match->setDoesNotThrow(); 3161198092Srdivacky 3162210299Sed llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match"); 3163210299Sed llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next"); 3164198092Srdivacky 3165198092Srdivacky CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"), 3166193326Sed MatchedBlock, NextCatchBlock); 3167198092Srdivacky 3168193326Sed // Emit the @catch block. 3169193326Sed CGF.EmitBlock(MatchedBlock); 3170210299Sed 3171210299Sed // Collect any cleanups for the catch variable. The scope lasts until 3172210299Sed // the end of the catch body. 3173212904Sdim CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF); 3174210299Sed 3175218893Sdim CGF.EmitAutoVarDecl(*CatchParam); 3176193326Sed assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); 3177193326Sed 3178210299Sed // Initialize the catch variable. 3179198092Srdivacky llvm::Value *Tmp = 3180198092Srdivacky CGF.Builder.CreateBitCast(Caught, 3181198092Srdivacky CGF.ConvertType(CatchParam->getType()), 3182193326Sed "tmp"); 3183193326Sed CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam)); 3184198092Srdivacky 3185193326Sed CGF.EmitStmt(CatchStmt->getCatchBody()); 3186210299Sed 3187210299Sed // We're done with the catch variable. 3188210299Sed CatchVarCleanups.ForceCleanup(); 3189210299Sed 3190193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 3191198092Srdivacky 3192193326Sed CGF.EmitBlock(NextCatchBlock); 3193193326Sed } 3194193326Sed 3195210299Sed CGF.ObjCEHValueStack.pop_back(); 3196210299Sed 3197212904Sdim // If nothing wanted anything to do with the caught exception, 3198212904Sdim // kill the extract call. 3199212904Sdim if (Caught->use_empty()) 3200212904Sdim Caught->eraseFromParent(); 3201212904Sdim 3202212904Sdim if (!AllMatched) 3203193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 3204198092Srdivacky 3205212904Sdim if (HasFinally) { 3206212904Sdim // Emit the exception handler for the @catch blocks. 3207212904Sdim CGF.EmitBlock(CatchHandler); 3208210299Sed 3209212904Sdim // In theory we might now need a write hazard, but actually it's 3210212904Sdim // unnecessary because there's no local-accessing code between 3211212904Sdim // the try's write hazard and here. 3212212904Sdim //Hazards.emitWriteHazard(); 3213210299Sed 3214218893Sdim // Extract the new exception and save it to the 3215218893Sdim // propagating-exception slot. 3216218893Sdim assert(PropagatingExnVar); 3217218893Sdim llvm::CallInst *NewCaught = 3218218893Sdim CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(), 3219218893Sdim ExceptionData, "caught"); 3220218893Sdim NewCaught->setDoesNotThrow(); 3221218893Sdim CGF.Builder.CreateStore(NewCaught, PropagatingExnVar); 3222218893Sdim 3223212904Sdim // Don't pop the catch handler; the throw already did. 3224212904Sdim CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar); 3225212904Sdim CGF.EmitBranchThroughCleanup(FinallyRethrow); 3226212904Sdim } 3227193326Sed } 3228198092Srdivacky 3229212904Sdim // Insert read hazards as required in the new blocks. 3230212904Sdim Hazards.emitHazardsInNewBlocks(); 3231212904Sdim 3232210299Sed // Pop the cleanup. 3233212904Sdim CGF.Builder.restoreIP(TryFallthroughIP); 3234212904Sdim if (CGF.HaveInsertPoint()) 3235212904Sdim CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar); 3236210299Sed CGF.PopCleanupBlock(); 3237212904Sdim CGF.EmitBlock(FinallyEnd.getBlock(), true); 3238193326Sed 3239210299Sed // Emit the rethrow block. 3240212904Sdim CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); 3241212904Sdim CGF.EmitBlock(FinallyRethrow.getBlock(), true); 3242210299Sed if (CGF.HaveInsertPoint()) { 3243218893Sdim // If we have a propagating-exception variable, check it. 3244218893Sdim llvm::Value *PropagatingExn; 3245218893Sdim if (PropagatingExnVar) { 3246218893Sdim PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar); 3247212904Sdim 3248218893Sdim // Otherwise, just look in the buffer for the exception to throw. 3249218893Sdim } else { 3250218893Sdim llvm::CallInst *Caught = 3251218893Sdim CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(), 3252218893Sdim ExceptionData); 3253218893Sdim Caught->setDoesNotThrow(); 3254218893Sdim PropagatingExn = Caught; 3255218893Sdim } 3256218893Sdim 3257218893Sdim CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn) 3258210299Sed ->setDoesNotThrow(); 3259210299Sed CGF.Builder.CreateUnreachable(); 3260193326Sed } 3261193326Sed 3262212904Sdim CGF.Builder.restoreIP(SavedIP); 3263193326Sed} 3264193326Sed 3265193326Sedvoid CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 3266193326Sed const ObjCAtThrowStmt &S) { 3267193326Sed llvm::Value *ExceptionAsObject; 3268198092Srdivacky 3269193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 3270193326Sed llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr); 3271198092Srdivacky ExceptionAsObject = 3272193326Sed CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp"); 3273193326Sed } else { 3274198092Srdivacky assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && 3275193326Sed "Unexpected rethrow outside @catch block."); 3276193326Sed ExceptionAsObject = CGF.ObjCEHValueStack.back(); 3277193326Sed } 3278198092Srdivacky 3279210299Sed CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject) 3280210299Sed ->setDoesNotReturn(); 3281193326Sed CGF.Builder.CreateUnreachable(); 3282193326Sed 3283193326Sed // Clear the insertion point to indicate we are in unreachable code. 3284193326Sed CGF.Builder.ClearInsertionPoint(); 3285193326Sed} 3286193326Sed 3287193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak 3288193326Sed/// object: objc_read_weak (id *src) 3289193326Sed/// 3290193326Sedllvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 3291198092Srdivacky llvm::Value *AddrWeakObj) { 3292193326Sed const llvm::Type* DestTy = 3293198092Srdivacky cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); 3294198092Srdivacky AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, 3295198092Srdivacky ObjCTypes.PtrObjectPtrTy); 3296193326Sed llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(), 3297193326Sed AddrWeakObj, "weakread"); 3298193326Sed read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); 3299193326Sed return read_weak; 3300193326Sed} 3301193326Sed 3302193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. 3303193326Sed/// objc_assign_weak (id src, id *dst) 3304193326Sed/// 3305193326Sedvoid CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 3306198092Srdivacky llvm::Value *src, llvm::Value *dst) { 3307193326Sed const llvm::Type * SrcTy = src->getType(); 3308193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 3309193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 3310193326Sed assert(Size <= 8 && "does not support size > 8"); 3311193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 3312198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 3313193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 3314193326Sed } 3315193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 3316193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 3317193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(), 3318193326Sed src, dst, "weakassign"); 3319193326Sed return; 3320193326Sed} 3321193326Sed 3322193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. 3323193326Sed/// objc_assign_global (id src, id *dst) 3324193326Sed/// 3325193326Sedvoid CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 3326212904Sdim llvm::Value *src, llvm::Value *dst, 3327212904Sdim bool threadlocal) { 3328193326Sed const llvm::Type * SrcTy = src->getType(); 3329193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 3330193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 3331193326Sed assert(Size <= 8 && "does not support size > 8"); 3332193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 3333198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 3334193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 3335193326Sed } 3336193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 3337193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 3338212904Sdim if (!threadlocal) 3339212904Sdim CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(), 3340212904Sdim src, dst, "globalassign"); 3341212904Sdim else 3342212904Sdim CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(), 3343212904Sdim src, dst, "threadlocalassign"); 3344193326Sed return; 3345193326Sed} 3346193326Sed 3347193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. 3348198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset) 3349193326Sed/// 3350193326Sedvoid CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 3351198092Srdivacky llvm::Value *src, llvm::Value *dst, 3352198092Srdivacky llvm::Value *ivarOffset) { 3353198092Srdivacky assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL"); 3354193326Sed const llvm::Type * SrcTy = src->getType(); 3355193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 3356193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 3357193326Sed assert(Size <= 8 && "does not support size > 8"); 3358193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 3359198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 3360193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 3361193326Sed } 3362193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 3363193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 3364198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(), 3365198092Srdivacky src, dst, ivarOffset); 3366193326Sed return; 3367193326Sed} 3368193326Sed 3369193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. 3370193326Sed/// objc_assign_strongCast (id src, id *dst) 3371193326Sed/// 3372193326Sedvoid CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 3373198092Srdivacky llvm::Value *src, llvm::Value *dst) { 3374193326Sed const llvm::Type * SrcTy = src->getType(); 3375193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 3376193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 3377193326Sed assert(Size <= 8 && "does not support size > 8"); 3378193326Sed src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 3379198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); 3380193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 3381193326Sed } 3382193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 3383193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 3384193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(), 3385193326Sed src, dst, "weakassign"); 3386193326Sed return; 3387193326Sed} 3388193326Sed 3389198092Srdivackyvoid CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 3390198092Srdivacky llvm::Value *DestPtr, 3391198092Srdivacky llvm::Value *SrcPtr, 3392210299Sed llvm::Value *size) { 3393198092Srdivacky SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); 3394198092Srdivacky DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); 3395198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(), 3396210299Sed DestPtr, SrcPtr, size); 3397198092Srdivacky return; 3398198092Srdivacky} 3399198092Srdivacky 3400193326Sed/// EmitObjCValueForIvar - Code Gen for ivar reference. 3401193326Sed/// 3402193326SedLValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 3403193326Sed QualType ObjectTy, 3404193326Sed llvm::Value *BaseValue, 3405193326Sed const ObjCIvarDecl *Ivar, 3406193326Sed unsigned CVRQualifiers) { 3407208600Srdivacky const ObjCInterfaceDecl *ID = 3408208600Srdivacky ObjectTy->getAs<ObjCObjectType>()->getInterface(); 3409193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 3410193326Sed EmitIvarOffset(CGF, ID, Ivar)); 3411193326Sed} 3412193326Sed 3413193326Sedllvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 3414193326Sed const ObjCInterfaceDecl *Interface, 3415193326Sed const ObjCIvarDecl *Ivar) { 3416193326Sed uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar); 3417193326Sed return llvm::ConstantInt::get( 3418198092Srdivacky CGM.getTypes().ConvertType(CGM.getContext().LongTy), 3419198092Srdivacky Offset); 3420193326Sed} 3421193326Sed 3422193326Sed/* *** Private Interface *** */ 3423193326Sed 3424193326Sed/// EmitImageInfo - Emit the image info marker used to encode some module 3425193326Sed/// level information. 3426193326Sed/// 3427193326Sed/// See: <rdr://4810609&4810587&4810587> 3428193326Sed/// struct IMAGE_INFO { 3429193326Sed/// unsigned version; 3430193326Sed/// unsigned flags; 3431193326Sed/// }; 3432193326Sedenum ImageInfoFlags { 3433207619Srdivacky eImageInfo_FixAndContinue = (1 << 0), 3434198092Srdivacky eImageInfo_GarbageCollected = (1 << 1), 3435198092Srdivacky eImageInfo_GCOnly = (1 << 2), 3436193326Sed eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set. 3437193326Sed 3438207619Srdivacky // A flag indicating that the module has no instances of a @synthesize of a 3439207619Srdivacky // superclass variable. <rdar://problem/6803242> 3440193326Sed eImageInfo_CorrectedSynthesize = (1 << 4) 3441193326Sed}; 3442193326Sed 3443207619Srdivackyvoid CGObjCCommonMac::EmitImageInfo() { 3444193326Sed unsigned version = 0; // Version is unused? 3445193326Sed unsigned flags = 0; 3446193326Sed 3447193326Sed // FIXME: Fix and continue? 3448193326Sed if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) 3449193326Sed flags |= eImageInfo_GarbageCollected; 3450193326Sed if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly) 3451193326Sed flags |= eImageInfo_GCOnly; 3452198092Srdivacky 3453193326Sed // We never allow @synthesize of a superclass property. 3454193326Sed flags |= eImageInfo_CorrectedSynthesize; 3455193326Sed 3456210299Sed const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext); 3457210299Sed 3458193326Sed // Emitted as int[2]; 3459193326Sed llvm::Constant *values[2] = { 3460210299Sed llvm::ConstantInt::get(Int32Ty, version), 3461210299Sed llvm::ConstantInt::get(Int32Ty, flags) 3462193326Sed }; 3463210299Sed llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2); 3464193326Sed 3465193326Sed const char *Section; 3466193326Sed if (ObjCABI == 1) 3467193326Sed Section = "__OBJC, __image_info,regular"; 3468193326Sed else 3469193326Sed Section = "__DATA, __objc_imageinfo, regular, no_dead_strip"; 3470198092Srdivacky llvm::GlobalVariable *GV = 3471193326Sed CreateMetadataVar("\01L_OBJC_IMAGE_INFO", 3472193326Sed llvm::ConstantArray::get(AT, values, 2), 3473193326Sed Section, 3474193326Sed 0, 3475193326Sed true); 3476193326Sed GV->setConstant(true); 3477193326Sed} 3478193326Sed 3479193326Sed 3480193326Sed// struct objc_module { 3481193326Sed// unsigned long version; 3482193326Sed// unsigned long size; 3483193326Sed// const char *name; 3484193326Sed// Symtab symtab; 3485193326Sed// }; 3486193326Sed 3487193326Sed// FIXME: Get from somewhere 3488193326Sedstatic const int ModuleVersion = 7; 3489193326Sed 3490193326Sedvoid CGObjCMac::EmitModuleInfo() { 3491193326Sed uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy); 3492198092Srdivacky 3493193326Sed std::vector<llvm::Constant*> Values(4); 3494193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion); 3495193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size); 3496193326Sed // This used to be the filename, now it is unused. <rdr://4327263> 3497193326Sed Values[2] = GetClassName(&CGM.getContext().Idents.get("")); 3498193326Sed Values[3] = EmitModuleSymbols(); 3499198092Srdivacky CreateMetadataVar("\01L_OBJC_MODULES", 3500193326Sed llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values), 3501193326Sed "__OBJC,__module_info,regular,no_dead_strip", 3502193326Sed 4, true); 3503193326Sed} 3504193326Sed 3505193326Sedllvm::Constant *CGObjCMac::EmitModuleSymbols() { 3506193326Sed unsigned NumClasses = DefinedClasses.size(); 3507193326Sed unsigned NumCategories = DefinedCategories.size(); 3508193326Sed 3509193326Sed // Return null if no symbols were defined. 3510193326Sed if (!NumClasses && !NumCategories) 3511193326Sed return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy); 3512193326Sed 3513193326Sed std::vector<llvm::Constant*> Values(5); 3514193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); 3515193326Sed Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy); 3516193326Sed Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses); 3517193326Sed Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories); 3518193326Sed 3519193326Sed // The runtime expects exactly the list of defined classes followed 3520193326Sed // by the list of defined categories, in a single array. 3521193326Sed std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories); 3522193326Sed for (unsigned i=0; i<NumClasses; i++) 3523193326Sed Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i], 3524193326Sed ObjCTypes.Int8PtrTy); 3525193326Sed for (unsigned i=0; i<NumCategories; i++) 3526198092Srdivacky Symbols[NumClasses + i] = 3527193326Sed llvm::ConstantExpr::getBitCast(DefinedCategories[i], 3528193326Sed ObjCTypes.Int8PtrTy); 3529193326Sed 3530198092Srdivacky Values[4] = 3531193326Sed llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 3532193326Sed NumClasses + NumCategories), 3533193326Sed Symbols); 3534193326Sed 3535198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 3536193326Sed 3537193326Sed llvm::GlobalVariable *GV = 3538193326Sed CreateMetadataVar("\01L_OBJC_SYMBOLS", Init, 3539193326Sed "__OBJC,__symbols,regular,no_dead_strip", 3540193326Sed 4, true); 3541193326Sed return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy); 3542193326Sed} 3543193326Sed 3544198092Srdivackyllvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder, 3545193326Sed const ObjCInterfaceDecl *ID) { 3546193326Sed LazySymbols.insert(ID->getIdentifier()); 3547193326Sed 3548193326Sed llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()]; 3549198092Srdivacky 3550193326Sed if (!Entry) { 3551198092Srdivacky llvm::Constant *Casted = 3552193326Sed llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()), 3553193326Sed ObjCTypes.ClassPtrTy); 3554198092Srdivacky Entry = 3555193326Sed CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted, 3556193326Sed "__OBJC,__cls_refs,literal_pointers,no_dead_strip", 3557193326Sed 4, true); 3558193326Sed } 3559193326Sed 3560199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 3561193326Sed} 3562193326Sed 3563210299Sedllvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel, 3564210299Sed bool lvalue) { 3565193326Sed llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; 3566198092Srdivacky 3567193326Sed if (!Entry) { 3568198092Srdivacky llvm::Constant *Casted = 3569193326Sed llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), 3570193326Sed ObjCTypes.SelectorPtrTy); 3571198092Srdivacky Entry = 3572193326Sed CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted, 3573193326Sed "__OBJC,__message_refs,literal_pointers,no_dead_strip", 3574193326Sed 4, true); 3575193326Sed } 3576193326Sed 3577210299Sed if (lvalue) 3578210299Sed return Entry; 3579199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 3580193326Sed} 3581193326Sed 3582193326Sedllvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) { 3583193326Sed llvm::GlobalVariable *&Entry = ClassNames[Ident]; 3584193326Sed 3585193326Sed if (!Entry) 3586198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", 3587198398Srdivacky llvm::ConstantArray::get(VMContext, 3588198398Srdivacky Ident->getNameStart()), 3589193326Sed "__TEXT,__cstring,cstring_literals", 3590193326Sed 1, true); 3591193326Sed 3592198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3593193326Sed} 3594193326Sed 3595212904Sdimllvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) { 3596212904Sdim llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator 3597212904Sdim I = MethodDefinitions.find(MD); 3598212904Sdim if (I != MethodDefinitions.end()) 3599212904Sdim return I->second; 3600212904Sdim 3601212904Sdim if (MD->hasBody() && MD->getPCHLevel() > 0) { 3602212904Sdim // MD isn't emitted yet because it comes from PCH. 3603212904Sdim CGM.EmitTopLevelDecl(const_cast<ObjCMethodDecl*>(MD)); 3604212904Sdim assert(MethodDefinitions[MD] && "EmitTopLevelDecl didn't emit the method!"); 3605212904Sdim return MethodDefinitions[MD]; 3606212904Sdim } 3607212904Sdim 3608212904Sdim return NULL; 3609212904Sdim} 3610212904Sdim 3611193326Sed/// GetIvarLayoutName - Returns a unique constant for the given 3612193326Sed/// ivar layout bitmap. 3613193326Sedllvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident, 3614198092Srdivacky const ObjCCommonTypesHelper &ObjCTypes) { 3615193326Sed return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 3616193326Sed} 3617193326Sed 3618193326Sedvoid CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT, 3619198092Srdivacky unsigned int BytePos, 3620193326Sed bool ForStrongLayout, 3621193326Sed bool &HasUnion) { 3622193326Sed const RecordDecl *RD = RT->getDecl(); 3623193326Sed // FIXME - Use iterator. 3624195341Sed llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end()); 3625193326Sed const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); 3626198092Srdivacky const llvm::StructLayout *RecLayout = 3627193326Sed CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty)); 3628198092Srdivacky 3629193326Sed BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos, 3630193326Sed ForStrongLayout, HasUnion); 3631193326Sed} 3632193326Sed 3633193326Sedvoid CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, 3634198092Srdivacky const llvm::StructLayout *Layout, 3635198092Srdivacky const RecordDecl *RD, 3636193326Sed const llvm::SmallVectorImpl<FieldDecl*> &RecFields, 3637198092Srdivacky unsigned int BytePos, bool ForStrongLayout, 3638198092Srdivacky bool &HasUnion) { 3639193326Sed bool IsUnion = (RD && RD->isUnion()); 3640193326Sed uint64_t MaxUnionIvarSize = 0; 3641193326Sed uint64_t MaxSkippedUnionIvarSize = 0; 3642193326Sed FieldDecl *MaxField = 0; 3643193326Sed FieldDecl *MaxSkippedField = 0; 3644218893Sdim FieldDecl *LastFieldBitfieldOrUnnamed = 0; 3645193326Sed uint64_t MaxFieldOffset = 0; 3646193326Sed uint64_t MaxSkippedFieldOffset = 0; 3647218893Sdim uint64_t LastBitfieldOrUnnamedOffset = 0; 3648198092Srdivacky 3649193326Sed if (RecFields.empty()) 3650193326Sed return; 3651193326Sed unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0); 3652193326Sed unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth(); 3653193326Sed 3654193326Sed for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { 3655193326Sed FieldDecl *Field = RecFields[i]; 3656193326Sed uint64_t FieldOffset; 3657198092Srdivacky if (RD) { 3658207619Srdivacky // Note that 'i' here is actually the field index inside RD of Field, 3659207619Srdivacky // although this dependency is hidden. 3660207619Srdivacky const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); 3661207619Srdivacky FieldOffset = RL.getFieldOffset(i) / 8; 3662198092Srdivacky } else 3663193326Sed FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)); 3664193326Sed 3665193326Sed // Skip over unnamed or bitfields 3666193326Sed if (!Field->getIdentifier() || Field->isBitField()) { 3667218893Sdim LastFieldBitfieldOrUnnamed = Field; 3668218893Sdim LastBitfieldOrUnnamedOffset = FieldOffset; 3669193326Sed continue; 3670193326Sed } 3671193326Sed 3672218893Sdim LastFieldBitfieldOrUnnamed = 0; 3673193326Sed QualType FQT = Field->getType(); 3674193326Sed if (FQT->isRecordType() || FQT->isUnionType()) { 3675193326Sed if (FQT->isUnionType()) 3676193326Sed HasUnion = true; 3677193326Sed 3678198092Srdivacky BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(), 3679193326Sed BytePos + FieldOffset, 3680193326Sed ForStrongLayout, HasUnion); 3681193326Sed continue; 3682193326Sed } 3683198092Srdivacky 3684193326Sed if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 3685198092Srdivacky const ConstantArrayType *CArray = 3686193326Sed dyn_cast_or_null<ConstantArrayType>(Array); 3687193326Sed uint64_t ElCount = CArray->getSize().getZExtValue(); 3688193326Sed assert(CArray && "only array with known element size is supported"); 3689193326Sed FQT = CArray->getElementType(); 3690193326Sed while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { 3691193326Sed const ConstantArrayType *CArray = 3692193326Sed dyn_cast_or_null<ConstantArrayType>(Array); 3693193326Sed ElCount *= CArray->getSize().getZExtValue(); 3694193326Sed FQT = CArray->getElementType(); 3695193326Sed } 3696198092Srdivacky 3697198092Srdivacky assert(!FQT->isUnionType() && 3698193326Sed "layout for array of unions not supported"); 3699218893Sdim if (FQT->isRecordType() && ElCount) { 3700193326Sed int OldIndex = IvarsInfo.size() - 1; 3701193326Sed int OldSkIndex = SkipIvars.size() -1; 3702198092Srdivacky 3703198092Srdivacky const RecordType *RT = FQT->getAs<RecordType>(); 3704193326Sed BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset, 3705193326Sed ForStrongLayout, HasUnion); 3706198092Srdivacky 3707193326Sed // Replicate layout information for each array element. Note that 3708193326Sed // one element is already done. 3709193326Sed uint64_t ElIx = 1; 3710198092Srdivacky for (int FirstIndex = IvarsInfo.size() - 1, 3711198092Srdivacky FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) { 3712193326Sed uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits; 3713193326Sed for (int i = OldIndex+1; i <= FirstIndex; ++i) 3714193326Sed IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx, 3715193326Sed IvarsInfo[i].ivar_size)); 3716193326Sed for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i) 3717193326Sed SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx, 3718193326Sed SkipIvars[i].ivar_size)); 3719193326Sed } 3720193326Sed continue; 3721193326Sed } 3722193326Sed } 3723193326Sed // At this point, we are done with Record/Union and array there of. 3724193326Sed // For other arrays we are down to its element type. 3725198092Srdivacky Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT); 3726193326Sed 3727193326Sed unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType()); 3728198092Srdivacky if ((ForStrongLayout && GCAttr == Qualifiers::Strong) 3729198092Srdivacky || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) { 3730193326Sed if (IsUnion) { 3731193326Sed uint64_t UnionIvarSize = FieldSize / WordSizeInBits; 3732193326Sed if (UnionIvarSize > MaxUnionIvarSize) { 3733193326Sed MaxUnionIvarSize = UnionIvarSize; 3734193326Sed MaxField = Field; 3735193326Sed MaxFieldOffset = FieldOffset; 3736193326Sed } 3737193326Sed } else { 3738193326Sed IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset, 3739193326Sed FieldSize / WordSizeInBits)); 3740193326Sed } 3741198092Srdivacky } else if ((ForStrongLayout && 3742198092Srdivacky (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)) 3743198092Srdivacky || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) { 3744193326Sed if (IsUnion) { 3745193326Sed // FIXME: Why the asymmetry? We divide by word size in bits on other 3746193326Sed // side. 3747193326Sed uint64_t UnionIvarSize = FieldSize; 3748193326Sed if (UnionIvarSize > MaxSkippedUnionIvarSize) { 3749193326Sed MaxSkippedUnionIvarSize = UnionIvarSize; 3750193326Sed MaxSkippedField = Field; 3751193326Sed MaxSkippedFieldOffset = FieldOffset; 3752193326Sed } 3753193326Sed } else { 3754193326Sed // FIXME: Why the asymmetry, we divide by byte size in bits here? 3755193326Sed SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset, 3756193326Sed FieldSize / ByteSizeInBits)); 3757193326Sed } 3758193326Sed } 3759193326Sed } 3760193326Sed 3761218893Sdim if (LastFieldBitfieldOrUnnamed) { 3762218893Sdim if (LastFieldBitfieldOrUnnamed->isBitField()) { 3763218893Sdim // Last field was a bitfield. Must update skip info. 3764218893Sdim Expr *BitWidth = LastFieldBitfieldOrUnnamed->getBitWidth(); 3765218893Sdim uint64_t BitFieldSize = 3766218893Sdim BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); 3767218893Sdim GC_IVAR skivar; 3768218893Sdim skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset; 3769218893Sdim skivar.ivar_size = (BitFieldSize / ByteSizeInBits) 3770218893Sdim + ((BitFieldSize % ByteSizeInBits) != 0); 3771218893Sdim SkipIvars.push_back(skivar); 3772218893Sdim } else { 3773218893Sdim assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed"); 3774218893Sdim // Last field was unnamed. Must update skip info. 3775218893Sdim unsigned FieldSize 3776218893Sdim = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType()); 3777218893Sdim SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset, 3778218893Sdim FieldSize / ByteSizeInBits)); 3779218893Sdim } 3780193326Sed } 3781198092Srdivacky 3782193326Sed if (MaxField) 3783198092Srdivacky IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset, 3784193326Sed MaxUnionIvarSize)); 3785193326Sed if (MaxSkippedField) 3786193326Sed SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset, 3787193326Sed MaxSkippedUnionIvarSize)); 3788193326Sed} 3789193326Sed 3790212904Sdim/// BuildIvarLayoutBitmap - This routine is the horsework for doing all 3791212904Sdim/// the computations and returning the layout bitmap (for ivar or blocks) in 3792212904Sdim/// the given argument BitMap string container. Routine reads 3793212904Sdim/// two containers, IvarsInfo and SkipIvars which are assumed to be 3794212904Sdim/// filled already by the caller. 3795212904Sdimllvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) { 3796193326Sed unsigned int WordsToScan, WordsToSkip; 3797198092Srdivacky const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext); 3798212904Sdim 3799193326Sed // Build the string of skip/scan nibbles 3800193326Sed llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars; 3801198092Srdivacky unsigned int WordSize = 3802212904Sdim CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy); 3803193326Sed if (IvarsInfo[0].ivar_bytepos == 0) { 3804193326Sed WordsToSkip = 0; 3805193326Sed WordsToScan = IvarsInfo[0].ivar_size; 3806193326Sed } else { 3807193326Sed WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize; 3808193326Sed WordsToScan = IvarsInfo[0].ivar_size; 3809193326Sed } 3810193326Sed for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) { 3811198092Srdivacky unsigned int TailPrevGCObjC = 3812212904Sdim IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize; 3813193326Sed if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) { 3814193326Sed // consecutive 'scanned' object pointers. 3815193326Sed WordsToScan += IvarsInfo[i].ivar_size; 3816193326Sed } else { 3817193326Sed // Skip over 'gc'able object pointer which lay over each other. 3818193326Sed if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos) 3819193326Sed continue; 3820193326Sed // Must skip over 1 or more words. We save current skip/scan values 3821193326Sed // and start a new pair. 3822193326Sed SKIP_SCAN SkScan; 3823193326Sed SkScan.skip = WordsToSkip; 3824193326Sed SkScan.scan = WordsToScan; 3825193326Sed SkipScanIvars.push_back(SkScan); 3826212904Sdim 3827193326Sed // Skip the hole. 3828193326Sed SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize; 3829193326Sed SkScan.scan = 0; 3830193326Sed SkipScanIvars.push_back(SkScan); 3831193326Sed WordsToSkip = 0; 3832193326Sed WordsToScan = IvarsInfo[i].ivar_size; 3833193326Sed } 3834193326Sed } 3835193326Sed if (WordsToScan > 0) { 3836193326Sed SKIP_SCAN SkScan; 3837193326Sed SkScan.skip = WordsToSkip; 3838193326Sed SkScan.scan = WordsToScan; 3839193326Sed SkipScanIvars.push_back(SkScan); 3840193326Sed } 3841212904Sdim 3842193326Sed if (!SkipIvars.empty()) { 3843193326Sed unsigned int LastIndex = SkipIvars.size()-1; 3844198092Srdivacky int LastByteSkipped = 3845212904Sdim SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size; 3846193326Sed LastIndex = IvarsInfo.size()-1; 3847198092Srdivacky int LastByteScanned = 3848212904Sdim IvarsInfo[LastIndex].ivar_bytepos + 3849212904Sdim IvarsInfo[LastIndex].ivar_size * WordSize; 3850193326Sed // Compute number of bytes to skip at the tail end of the last ivar scanned. 3851201361Srdivacky if (LastByteSkipped > LastByteScanned) { 3852193326Sed unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize; 3853193326Sed SKIP_SCAN SkScan; 3854193326Sed SkScan.skip = TotalWords - (LastByteScanned/WordSize); 3855193326Sed SkScan.scan = 0; 3856193326Sed SkipScanIvars.push_back(SkScan); 3857193326Sed } 3858193326Sed } 3859193326Sed // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced 3860193326Sed // as 0xMN. 3861193326Sed int SkipScan = SkipScanIvars.size()-1; 3862193326Sed for (int i = 0; i <= SkipScan; i++) { 3863193326Sed if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0 3864193326Sed && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) { 3865193326Sed // 0xM0 followed by 0x0N detected. 3866193326Sed SkipScanIvars[i].scan = SkipScanIvars[i+1].scan; 3867193326Sed for (int j = i+1; j < SkipScan; j++) 3868193326Sed SkipScanIvars[j] = SkipScanIvars[j+1]; 3869193326Sed --SkipScan; 3870193326Sed } 3871193326Sed } 3872212904Sdim 3873193326Sed // Generate the string. 3874193326Sed for (int i = 0; i <= SkipScan; i++) { 3875193326Sed unsigned char byte; 3876193326Sed unsigned int skip_small = SkipScanIvars[i].skip % 0xf; 3877193326Sed unsigned int scan_small = SkipScanIvars[i].scan % 0xf; 3878193326Sed unsigned int skip_big = SkipScanIvars[i].skip / 0xf; 3879193326Sed unsigned int scan_big = SkipScanIvars[i].scan / 0xf; 3880212904Sdim 3881193326Sed // first skip big. 3882193326Sed for (unsigned int ix = 0; ix < skip_big; ix++) 3883193326Sed BitMap += (unsigned char)(0xf0); 3884212904Sdim 3885193326Sed // next (skip small, scan) 3886193326Sed if (skip_small) { 3887193326Sed byte = skip_small << 4; 3888193326Sed if (scan_big > 0) { 3889193326Sed byte |= 0xf; 3890193326Sed --scan_big; 3891193326Sed } else if (scan_small) { 3892193326Sed byte |= scan_small; 3893193326Sed scan_small = 0; 3894193326Sed } 3895193326Sed BitMap += byte; 3896193326Sed } 3897193326Sed // next scan big 3898193326Sed for (unsigned int ix = 0; ix < scan_big; ix++) 3899193326Sed BitMap += (unsigned char)(0x0f); 3900193326Sed // last scan small 3901193326Sed if (scan_small) { 3902193326Sed byte = scan_small; 3903193326Sed BitMap += byte; 3904193326Sed } 3905193326Sed } 3906193326Sed // null terminate string. 3907193326Sed unsigned char zero = 0; 3908193326Sed BitMap += zero; 3909212904Sdim 3910212904Sdim llvm::GlobalVariable * Entry = 3911212904Sdim CreateMetadataVar("\01L_OBJC_CLASS_NAME_", 3912212904Sdim llvm::ConstantArray::get(VMContext, BitMap.c_str()), 3913212904Sdim "__TEXT,__cstring,cstring_literals", 3914212904Sdim 1, true); 3915212904Sdim return getConstantGEP(VMContext, Entry, 0, 0); 3916212904Sdim} 3917198092Srdivacky 3918212904Sdim/// BuildIvarLayout - Builds ivar layout bitmap for the class 3919212904Sdim/// implementation for the __strong or __weak case. 3920212904Sdim/// The layout map displays which words in ivar list must be skipped 3921212904Sdim/// and which must be scanned by GC (see below). String is built of bytes. 3922212904Sdim/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count 3923212904Sdim/// of words to skip and right nibble is count of words to scan. So, each 3924212904Sdim/// nibble represents up to 15 workds to skip or scan. Skipping the rest is 3925212904Sdim/// represented by a 0x00 byte which also ends the string. 3926212904Sdim/// 1. when ForStrongLayout is true, following ivars are scanned: 3927212904Sdim/// - id, Class 3928212904Sdim/// - object * 3929212904Sdim/// - __strong anything 3930212904Sdim/// 3931212904Sdim/// 2. When ForStrongLayout is false, following ivars are scanned: 3932212904Sdim/// - __weak anything 3933212904Sdim/// 3934212904Sdimllvm::Constant *CGObjCCommonMac::BuildIvarLayout( 3935212904Sdim const ObjCImplementationDecl *OMD, 3936212904Sdim bool ForStrongLayout) { 3937212904Sdim bool hasUnion = false; 3938212904Sdim 3939212904Sdim const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext); 3940212904Sdim if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) 3941212904Sdim return llvm::Constant::getNullValue(PtrTy); 3942212904Sdim 3943212904Sdim llvm::SmallVector<ObjCIvarDecl*, 32> Ivars; 3944212904Sdim const ObjCInterfaceDecl *OI = OMD->getClassInterface(); 3945212904Sdim CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars); 3946212904Sdim 3947212904Sdim llvm::SmallVector<FieldDecl*, 32> RecFields; 3948212904Sdim for (unsigned k = 0, e = Ivars.size(); k != e; ++k) 3949212904Sdim RecFields.push_back(cast<FieldDecl>(Ivars[k])); 3950212904Sdim 3951212904Sdim if (RecFields.empty()) 3952212904Sdim return llvm::Constant::getNullValue(PtrTy); 3953212904Sdim 3954212904Sdim SkipIvars.clear(); 3955212904Sdim IvarsInfo.clear(); 3956212904Sdim 3957212904Sdim BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion); 3958212904Sdim if (IvarsInfo.empty()) 3959212904Sdim return llvm::Constant::getNullValue(PtrTy); 3960212904Sdim // Sort on byte position in case we encounterred a union nested in 3961212904Sdim // the ivar list. 3962212904Sdim if (hasUnion && !IvarsInfo.empty()) 3963212904Sdim std::sort(IvarsInfo.begin(), IvarsInfo.end()); 3964212904Sdim if (hasUnion && !SkipIvars.empty()) 3965212904Sdim std::sort(SkipIvars.begin(), SkipIvars.end()); 3966212904Sdim 3967212904Sdim std::string BitMap; 3968212904Sdim llvm::Constant *C = BuildIvarLayoutBitmap(BitMap); 3969212904Sdim 3970212904Sdim if (CGM.getLangOptions().ObjCGCBitmapPrint) { 3971198092Srdivacky printf("\n%s ivar layout for class '%s': ", 3972193326Sed ForStrongLayout ? "strong" : "weak", 3973212904Sdim OMD->getClassInterface()->getName().data()); 3974193326Sed const unsigned char *s = (unsigned char*)BitMap.c_str(); 3975193326Sed for (unsigned i = 0; i < BitMap.size(); i++) 3976193326Sed if (!(s[i] & 0xf0)) 3977193326Sed printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); 3978193326Sed else 3979193326Sed printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); 3980193326Sed printf("\n"); 3981193326Sed } 3982212904Sdim return C; 3983193326Sed} 3984193326Sed 3985193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) { 3986193326Sed llvm::GlobalVariable *&Entry = MethodVarNames[Sel]; 3987193326Sed 3988193326Sed // FIXME: Avoid std::string copying. 3989193326Sed if (!Entry) 3990198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_", 3991198092Srdivacky llvm::ConstantArray::get(VMContext, Sel.getAsString()), 3992193326Sed "__TEXT,__cstring,cstring_literals", 3993193326Sed 1, true); 3994193326Sed 3995198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 3996193326Sed} 3997193326Sed 3998193326Sed// FIXME: Merge into a single cstring creation function. 3999193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) { 4000193326Sed return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID)); 4001193326Sed} 4002193326Sed 4003193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) { 4004193326Sed std::string TypeStr; 4005193326Sed CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field); 4006193326Sed 4007193326Sed llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; 4008193326Sed 4009193326Sed if (!Entry) 4010193326Sed Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", 4011198092Srdivacky llvm::ConstantArray::get(VMContext, TypeStr), 4012193326Sed "__TEXT,__cstring,cstring_literals", 4013193326Sed 1, true); 4014198092Srdivacky 4015198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 4016193326Sed} 4017193326Sed 4018193326Sedllvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) { 4019193326Sed std::string TypeStr; 4020193326Sed CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D), 4021193326Sed TypeStr); 4022193326Sed 4023193326Sed llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; 4024193326Sed 4025193326Sed if (!Entry) 4026193326Sed Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_", 4027198092Srdivacky llvm::ConstantArray::get(VMContext, TypeStr), 4028193326Sed "__TEXT,__cstring,cstring_literals", 4029193326Sed 1, true); 4030193326Sed 4031198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 4032193326Sed} 4033193326Sed 4034193326Sed// FIXME: Merge into a single cstring creation function. 4035193326Sedllvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) { 4036193326Sed llvm::GlobalVariable *&Entry = PropertyNames[Ident]; 4037198092Srdivacky 4038193326Sed if (!Entry) 4039198092Srdivacky Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_", 4040198398Srdivacky llvm::ConstantArray::get(VMContext, 4041198398Srdivacky Ident->getNameStart()), 4042193326Sed "__TEXT,__cstring,cstring_literals", 4043193326Sed 1, true); 4044193326Sed 4045198092Srdivacky return getConstantGEP(VMContext, Entry, 0, 0); 4046193326Sed} 4047193326Sed 4048193326Sed// FIXME: Merge into a single cstring creation function. 4049193326Sed// FIXME: This Decl should be more precise. 4050193326Sedllvm::Constant * 4051198092SrdivackyCGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD, 4052198092Srdivacky const Decl *Container) { 4053193326Sed std::string TypeStr; 4054193326Sed CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr); 4055193326Sed return GetPropertyName(&CGM.getContext().Idents.get(TypeStr)); 4056193326Sed} 4057193326Sed 4058198092Srdivackyvoid CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D, 4059193326Sed const ObjCContainerDecl *CD, 4060198398Srdivacky llvm::SmallVectorImpl<char> &Name) { 4061198398Srdivacky llvm::raw_svector_ostream OS(Name); 4062193326Sed assert (CD && "Missing container decl in GetNameForMethod"); 4063198398Srdivacky OS << '\01' << (D->isInstanceMethod() ? '-' : '+') 4064198398Srdivacky << '[' << CD->getName(); 4065198092Srdivacky if (const ObjCCategoryImplDecl *CID = 4066198398Srdivacky dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) 4067207619Srdivacky OS << '(' << CID << ')'; 4068198398Srdivacky OS << ' ' << D->getSelector().getAsString() << ']'; 4069193326Sed} 4070193326Sed 4071193326Sedvoid CGObjCMac::FinishModule() { 4072193326Sed EmitModuleInfo(); 4073193326Sed 4074193326Sed // Emit the dummy bodies for any protocols which were referenced but 4075193326Sed // never defined. 4076198092Srdivacky for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator 4077198092Srdivacky I = Protocols.begin(), e = Protocols.end(); I != e; ++I) { 4078198092Srdivacky if (I->second->hasInitializer()) 4079193326Sed continue; 4080193326Sed 4081193326Sed std::vector<llvm::Constant*> Values(5); 4082193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); 4083198092Srdivacky Values[1] = GetClassName(I->first); 4084193326Sed Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); 4085193326Sed Values[3] = Values[4] = 4086193326Sed llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); 4087198092Srdivacky I->second->setLinkage(llvm::GlobalValue::InternalLinkage); 4088198092Srdivacky I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, 4089193326Sed Values)); 4090198092Srdivacky CGM.AddUsedGlobal(I->second); 4091193326Sed } 4092193326Sed 4093193326Sed // Add assembler directives to add lazy undefined symbol references 4094193326Sed // for classes which are referenced but not defined. This is 4095193326Sed // important for correct linker interaction. 4096198092Srdivacky // 4097198092Srdivacky // FIXME: It would be nice if we had an LLVM construct for this. 4098198092Srdivacky if (!LazySymbols.empty() || !DefinedSymbols.empty()) { 4099198092Srdivacky llvm::SmallString<256> Asm; 4100198092Srdivacky Asm += CGM.getModule().getModuleInlineAsm(); 4101198092Srdivacky if (!Asm.empty() && Asm.back() != '\n') 4102198092Srdivacky Asm += '\n'; 4103193326Sed 4104198092Srdivacky llvm::raw_svector_ostream OS(Asm); 4105198092Srdivacky for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(), 4106198092Srdivacky e = DefinedSymbols.end(); I != e; ++I) 4107198092Srdivacky OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n" 4108198092Srdivacky << "\t.globl .objc_class_name_" << (*I)->getName() << "\n"; 4109207619Srdivacky for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(), 4110210299Sed e = LazySymbols.end(); I != e; ++I) { 4111207619Srdivacky OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n"; 4112210299Sed } 4113210299Sed 4114210299Sed for (size_t i = 0; i < DefinedCategoryNames.size(); ++i) { 4115210299Sed OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n" 4116210299Sed << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n"; 4117210299Sed } 4118207619Srdivacky 4119198092Srdivacky CGM.getModule().setModuleInlineAsm(OS.str()); 4120193326Sed } 4121193326Sed} 4122193326Sed 4123198092SrdivackyCGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm) 4124193326Sed : CGObjCCommonMac(cgm), 4125198092Srdivacky ObjCTypes(cgm) { 4126193326Sed ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL; 4127193326Sed ObjCABI = 2; 4128193326Sed} 4129193326Sed 4130193326Sed/* *** */ 4131193326Sed 4132193326SedObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) 4133198092Srdivacky : VMContext(cgm.getLLVMContext()), CGM(cgm) { 4134193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 4135193326Sed ASTContext &Ctx = CGM.getContext(); 4136198092Srdivacky 4137193326Sed ShortTy = Types.ConvertType(Ctx.ShortTy); 4138193326Sed IntTy = Types.ConvertType(Ctx.IntTy); 4139193326Sed LongTy = Types.ConvertType(Ctx.LongTy); 4140193326Sed LongLongTy = Types.ConvertType(Ctx.LongLongTy); 4141198092Srdivacky Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); 4142198092Srdivacky 4143193326Sed ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType()); 4144193326Sed PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy); 4145193326Sed SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType()); 4146198092Srdivacky 4147193326Sed // FIXME: It would be nice to unify this with the opaque type, so that the IR 4148193326Sed // comes out a bit cleaner. 4149193326Sed const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType()); 4150193326Sed ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T); 4151198092Srdivacky 4152193326Sed // I'm not sure I like this. The implicit coordination is a bit 4153193326Sed // gross. We should solve this in a reasonable fashion because this 4154193326Sed // is a pretty common task (match some runtime data structure with 4155193326Sed // an LLVM data structure). 4156198092Srdivacky 4157193326Sed // FIXME: This is leaked. 4158193326Sed // FIXME: Merge with rewriter code? 4159198092Srdivacky 4160193326Sed // struct _objc_super { 4161193326Sed // id self; 4162193326Sed // Class cls; 4163193326Sed // } 4164208600Srdivacky RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, 4165207619Srdivacky Ctx.getTranslationUnitDecl(), 4166193326Sed SourceLocation(), 4167198092Srdivacky &Ctx.Idents.get("_objc_super")); 4168195341Sed RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 4169198092Srdivacky Ctx.getObjCIdType(), 0, 0, false)); 4170198092Srdivacky RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 4171198092Srdivacky Ctx.getObjCClassType(), 0, 0, false)); 4172203955Srdivacky RD->completeDefinition(); 4173198092Srdivacky 4174193326Sed SuperCTy = Ctx.getTagDeclType(RD); 4175193326Sed SuperPtrCTy = Ctx.getPointerType(SuperCTy); 4176198092Srdivacky 4177193326Sed SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy)); 4178198092Srdivacky SuperPtrTy = llvm::PointerType::getUnqual(SuperTy); 4179198092Srdivacky 4180193326Sed // struct _prop_t { 4181193326Sed // char *name; 4182198092Srdivacky // char *attributes; 4183193326Sed // } 4184198092Srdivacky PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL); 4185198092Srdivacky CGM.getModule().addTypeName("struct._prop_t", 4186193326Sed PropertyTy); 4187198092Srdivacky 4188193326Sed // struct _prop_list_t { 4189193326Sed // uint32_t entsize; // sizeof(struct _prop_t) 4190193326Sed // uint32_t count_of_properties; 4191193326Sed // struct _prop_t prop_list[count_of_properties]; 4192193326Sed // } 4193198092Srdivacky PropertyListTy = llvm::StructType::get(VMContext, IntTy, 4194193326Sed IntTy, 4195193326Sed llvm::ArrayType::get(PropertyTy, 0), 4196193326Sed NULL); 4197198092Srdivacky CGM.getModule().addTypeName("struct._prop_list_t", 4198193326Sed PropertyListTy); 4199193326Sed // struct _prop_list_t * 4200193326Sed PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy); 4201198092Srdivacky 4202193326Sed // struct _objc_method { 4203193326Sed // SEL _cmd; 4204193326Sed // char *method_type; 4205193326Sed // char *_imp; 4206193326Sed // } 4207198092Srdivacky MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy, 4208193326Sed Int8PtrTy, 4209193326Sed Int8PtrTy, 4210193326Sed NULL); 4211193326Sed CGM.getModule().addTypeName("struct._objc_method", MethodTy); 4212198092Srdivacky 4213193326Sed // struct _objc_cache * 4214198092Srdivacky CacheTy = llvm::OpaqueType::get(VMContext); 4215193326Sed CGM.getModule().addTypeName("struct._objc_cache", CacheTy); 4216193326Sed CachePtrTy = llvm::PointerType::getUnqual(CacheTy); 4217193326Sed} 4218193326Sed 4219198092SrdivackyObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) 4220198092Srdivacky : ObjCCommonTypesHelper(cgm) { 4221193326Sed // struct _objc_method_description { 4222193326Sed // SEL name; 4223193326Sed // char *types; 4224193326Sed // } 4225198092Srdivacky MethodDescriptionTy = 4226198092Srdivacky llvm::StructType::get(VMContext, SelectorPtrTy, 4227193326Sed Int8PtrTy, 4228193326Sed NULL); 4229198092Srdivacky CGM.getModule().addTypeName("struct._objc_method_description", 4230193326Sed MethodDescriptionTy); 4231193326Sed 4232193326Sed // struct _objc_method_description_list { 4233193326Sed // int count; 4234193326Sed // struct _objc_method_description[1]; 4235193326Sed // } 4236198092Srdivacky MethodDescriptionListTy = 4237198092Srdivacky llvm::StructType::get(VMContext, IntTy, 4238193326Sed llvm::ArrayType::get(MethodDescriptionTy, 0), 4239193326Sed NULL); 4240198092Srdivacky CGM.getModule().addTypeName("struct._objc_method_description_list", 4241193326Sed MethodDescriptionListTy); 4242198092Srdivacky 4243193326Sed // struct _objc_method_description_list * 4244198092Srdivacky MethodDescriptionListPtrTy = 4245193326Sed llvm::PointerType::getUnqual(MethodDescriptionListTy); 4246193326Sed 4247193326Sed // Protocol description structures 4248193326Sed 4249193326Sed // struct _objc_protocol_extension { 4250193326Sed // uint32_t size; // sizeof(struct _objc_protocol_extension) 4251193326Sed // struct _objc_method_description_list *optional_instance_methods; 4252193326Sed // struct _objc_method_description_list *optional_class_methods; 4253193326Sed // struct _objc_property_list *instance_properties; 4254193326Sed // } 4255198092Srdivacky ProtocolExtensionTy = 4256198092Srdivacky llvm::StructType::get(VMContext, IntTy, 4257193326Sed MethodDescriptionListPtrTy, 4258193326Sed MethodDescriptionListPtrTy, 4259193326Sed PropertyListPtrTy, 4260193326Sed NULL); 4261198092Srdivacky CGM.getModule().addTypeName("struct._objc_protocol_extension", 4262193326Sed ProtocolExtensionTy); 4263198092Srdivacky 4264193326Sed // struct _objc_protocol_extension * 4265193326Sed ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy); 4266193326Sed 4267193326Sed // Handle recursive construction of Protocol and ProtocolList types 4268193326Sed 4269198092Srdivacky llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext); 4270198092Srdivacky llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext); 4271193326Sed 4272198092Srdivacky const llvm::Type *T = 4273198092Srdivacky llvm::StructType::get(VMContext, 4274198092Srdivacky llvm::PointerType::getUnqual(ProtocolListTyHolder), 4275193326Sed LongTy, 4276193326Sed llvm::ArrayType::get(ProtocolTyHolder, 0), 4277193326Sed NULL); 4278193326Sed cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T); 4279193326Sed 4280193326Sed // struct _objc_protocol { 4281193326Sed // struct _objc_protocol_extension *isa; 4282193326Sed // char *protocol_name; 4283193326Sed // struct _objc_protocol **_objc_protocol_list; 4284193326Sed // struct _objc_method_description_list *instance_methods; 4285193326Sed // struct _objc_method_description_list *class_methods; 4286193326Sed // } 4287198092Srdivacky T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy, 4288193326Sed Int8PtrTy, 4289193326Sed llvm::PointerType::getUnqual(ProtocolListTyHolder), 4290193326Sed MethodDescriptionListPtrTy, 4291193326Sed MethodDescriptionListPtrTy, 4292193326Sed NULL); 4293193326Sed cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T); 4294193326Sed 4295193326Sed ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get()); 4296198092Srdivacky CGM.getModule().addTypeName("struct._objc_protocol_list", 4297193326Sed ProtocolListTy); 4298193326Sed // struct _objc_protocol_list * 4299193326Sed ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy); 4300193326Sed 4301193326Sed ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get()); 4302193326Sed CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy); 4303193326Sed ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy); 4304193326Sed 4305193326Sed // Class description structures 4306193326Sed 4307193326Sed // struct _objc_ivar { 4308193326Sed // char *ivar_name; 4309193326Sed // char *ivar_type; 4310193326Sed // int ivar_offset; 4311193326Sed // } 4312198092Srdivacky IvarTy = llvm::StructType::get(VMContext, Int8PtrTy, 4313198092Srdivacky Int8PtrTy, 4314198092Srdivacky IntTy, 4315193326Sed NULL); 4316193326Sed CGM.getModule().addTypeName("struct._objc_ivar", IvarTy); 4317193326Sed 4318193326Sed // struct _objc_ivar_list * 4319198092Srdivacky IvarListTy = llvm::OpaqueType::get(VMContext); 4320193326Sed CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy); 4321193326Sed IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy); 4322193326Sed 4323193326Sed // struct _objc_method_list * 4324198092Srdivacky MethodListTy = llvm::OpaqueType::get(VMContext); 4325193326Sed CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy); 4326193326Sed MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy); 4327193326Sed 4328193326Sed // struct _objc_class_extension * 4329198092Srdivacky ClassExtensionTy = 4330198092Srdivacky llvm::StructType::get(VMContext, IntTy, 4331193326Sed Int8PtrTy, 4332193326Sed PropertyListPtrTy, 4333193326Sed NULL); 4334193326Sed CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy); 4335193326Sed ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy); 4336193326Sed 4337198092Srdivacky llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext); 4338193326Sed 4339193326Sed // struct _objc_class { 4340193326Sed // Class isa; 4341193326Sed // Class super_class; 4342193326Sed // char *name; 4343193326Sed // long version; 4344193326Sed // long info; 4345193326Sed // long instance_size; 4346193326Sed // struct _objc_ivar_list *ivars; 4347193326Sed // struct _objc_method_list *methods; 4348193326Sed // struct _objc_cache *cache; 4349193326Sed // struct _objc_protocol_list *protocols; 4350193326Sed // char *ivar_layout; 4351193326Sed // struct _objc_class_ext *ext; 4352193326Sed // }; 4353198092Srdivacky T = llvm::StructType::get(VMContext, 4354193326Sed llvm::PointerType::getUnqual(ClassTyHolder), 4355198092Srdivacky llvm::PointerType::getUnqual(ClassTyHolder), 4356193326Sed Int8PtrTy, 4357193326Sed LongTy, 4358193326Sed LongTy, 4359193326Sed LongTy, 4360193326Sed IvarListPtrTy, 4361193326Sed MethodListPtrTy, 4362193326Sed CachePtrTy, 4363193326Sed ProtocolListPtrTy, 4364193326Sed Int8PtrTy, 4365193326Sed ClassExtensionPtrTy, 4366193326Sed NULL); 4367193326Sed cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T); 4368198092Srdivacky 4369193326Sed ClassTy = cast<llvm::StructType>(ClassTyHolder.get()); 4370193326Sed CGM.getModule().addTypeName("struct._objc_class", ClassTy); 4371193326Sed ClassPtrTy = llvm::PointerType::getUnqual(ClassTy); 4372193326Sed 4373193326Sed // struct _objc_category { 4374193326Sed // char *category_name; 4375193326Sed // char *class_name; 4376193326Sed // struct _objc_method_list *instance_method; 4377193326Sed // struct _objc_method_list *class_method; 4378193326Sed // uint32_t size; // sizeof(struct _objc_category) 4379193326Sed // struct _objc_property_list *instance_properties;// category's @property 4380193326Sed // } 4381198092Srdivacky CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy, 4382193326Sed Int8PtrTy, 4383193326Sed MethodListPtrTy, 4384193326Sed MethodListPtrTy, 4385193326Sed ProtocolListPtrTy, 4386193326Sed IntTy, 4387193326Sed PropertyListPtrTy, 4388193326Sed NULL); 4389193326Sed CGM.getModule().addTypeName("struct._objc_category", CategoryTy); 4390193326Sed 4391193326Sed // Global metadata structures 4392193326Sed 4393193326Sed // struct _objc_symtab { 4394193326Sed // long sel_ref_cnt; 4395193326Sed // SEL *refs; 4396193326Sed // short cls_def_cnt; 4397193326Sed // short cat_def_cnt; 4398193326Sed // char *defs[cls_def_cnt + cat_def_cnt]; 4399193326Sed // } 4400198092Srdivacky SymtabTy = llvm::StructType::get(VMContext, LongTy, 4401193326Sed SelectorPtrTy, 4402193326Sed ShortTy, 4403193326Sed ShortTy, 4404193326Sed llvm::ArrayType::get(Int8PtrTy, 0), 4405193326Sed NULL); 4406193326Sed CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy); 4407193326Sed SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy); 4408193326Sed 4409193326Sed // struct _objc_module { 4410193326Sed // long version; 4411193326Sed // long size; // sizeof(struct _objc_module) 4412193326Sed // char *name; 4413193326Sed // struct _objc_symtab* symtab; 4414193326Sed // } 4415198092Srdivacky ModuleTy = 4416198092Srdivacky llvm::StructType::get(VMContext, LongTy, 4417193326Sed LongTy, 4418193326Sed Int8PtrTy, 4419193326Sed SymtabPtrTy, 4420193326Sed NULL); 4421193326Sed CGM.getModule().addTypeName("struct._objc_module", ModuleTy); 4422193326Sed 4423198092Srdivacky 4424193326Sed // FIXME: This is the size of the setjmp buffer and should be target 4425193326Sed // specific. 18 is what's used on 32-bit X86. 4426193326Sed uint64_t SetJmpBufferSize = 18; 4427198092Srdivacky 4428193326Sed // Exceptions 4429198092Srdivacky const llvm::Type *StackPtrTy = llvm::ArrayType::get( 4430198092Srdivacky llvm::Type::getInt8PtrTy(VMContext), 4); 4431198092Srdivacky 4432198092Srdivacky ExceptionDataTy = 4433210299Sed llvm::StructType::get(VMContext, 4434210299Sed llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext), 4435210299Sed SetJmpBufferSize), 4436193326Sed StackPtrTy, NULL); 4437198092Srdivacky CGM.getModule().addTypeName("struct._objc_exception_data", 4438193326Sed ExceptionDataTy); 4439193326Sed 4440193326Sed} 4441193326Sed 4442198092SrdivackyObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm) 4443198092Srdivacky : ObjCCommonTypesHelper(cgm) { 4444193326Sed // struct _method_list_t { 4445193326Sed // uint32_t entsize; // sizeof(struct _objc_method) 4446193326Sed // uint32_t method_count; 4447193326Sed // struct _objc_method method_list[method_count]; 4448193326Sed // } 4449198092Srdivacky MethodListnfABITy = llvm::StructType::get(VMContext, IntTy, 4450193326Sed IntTy, 4451193326Sed llvm::ArrayType::get(MethodTy, 0), 4452193326Sed NULL); 4453193326Sed CGM.getModule().addTypeName("struct.__method_list_t", 4454193326Sed MethodListnfABITy); 4455193326Sed // struct method_list_t * 4456193326Sed MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy); 4457198092Srdivacky 4458193326Sed // struct _protocol_t { 4459193326Sed // id isa; // NULL 4460193326Sed // const char * const protocol_name; 4461193326Sed // const struct _protocol_list_t * protocol_list; // super protocols 4462193326Sed // const struct method_list_t * const instance_methods; 4463193326Sed // const struct method_list_t * const class_methods; 4464193326Sed // const struct method_list_t *optionalInstanceMethods; 4465193326Sed // const struct method_list_t *optionalClassMethods; 4466193326Sed // const struct _prop_list_t * properties; 4467193326Sed // const uint32_t size; // sizeof(struct _protocol_t) 4468193326Sed // const uint32_t flags; // = 0 4469193326Sed // } 4470198092Srdivacky 4471193326Sed // Holder for struct _protocol_list_t * 4472198092Srdivacky llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext); 4473198092Srdivacky 4474198092Srdivacky ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy, 4475193326Sed Int8PtrTy, 4476193326Sed llvm::PointerType::getUnqual( 4477193326Sed ProtocolListTyHolder), 4478193326Sed MethodListnfABIPtrTy, 4479193326Sed MethodListnfABIPtrTy, 4480193326Sed MethodListnfABIPtrTy, 4481193326Sed MethodListnfABIPtrTy, 4482193326Sed PropertyListPtrTy, 4483193326Sed IntTy, 4484193326Sed IntTy, 4485193326Sed NULL); 4486193326Sed CGM.getModule().addTypeName("struct._protocol_t", 4487193326Sed ProtocolnfABITy); 4488193326Sed 4489193326Sed // struct _protocol_t* 4490193326Sed ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy); 4491198092Srdivacky 4492193326Sed // struct _protocol_list_t { 4493193326Sed // long protocol_count; // Note, this is 32/64 bit 4494193326Sed // struct _protocol_t *[protocol_count]; 4495193326Sed // } 4496198092Srdivacky ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy, 4497193326Sed llvm::ArrayType::get( 4498193326Sed ProtocolnfABIPtrTy, 0), 4499193326Sed NULL); 4500193326Sed CGM.getModule().addTypeName("struct._objc_protocol_list", 4501193326Sed ProtocolListnfABITy); 4502193326Sed cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo( 4503198092Srdivacky ProtocolListnfABITy); 4504198092Srdivacky 4505193326Sed // struct _objc_protocol_list* 4506193326Sed ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy); 4507198092Srdivacky 4508193326Sed // struct _ivar_t { 4509193326Sed // unsigned long int *offset; // pointer to ivar offset location 4510193326Sed // char *name; 4511193326Sed // char *type; 4512193326Sed // uint32_t alignment; 4513193326Sed // uint32_t size; 4514193326Sed // } 4515198092Srdivacky IvarnfABITy = llvm::StructType::get(VMContext, 4516198092Srdivacky llvm::PointerType::getUnqual(LongTy), 4517193326Sed Int8PtrTy, 4518193326Sed Int8PtrTy, 4519193326Sed IntTy, 4520193326Sed IntTy, 4521193326Sed NULL); 4522193326Sed CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy); 4523198092Srdivacky 4524193326Sed // struct _ivar_list_t { 4525193326Sed // uint32 entsize; // sizeof(struct _ivar_t) 4526193326Sed // uint32 count; 4527193326Sed // struct _iver_t list[count]; 4528193326Sed // } 4529198092Srdivacky IvarListnfABITy = llvm::StructType::get(VMContext, IntTy, 4530193326Sed IntTy, 4531193326Sed llvm::ArrayType::get( 4532198092Srdivacky IvarnfABITy, 0), 4533193326Sed NULL); 4534193326Sed CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy); 4535198092Srdivacky 4536193326Sed IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy); 4537198092Srdivacky 4538193326Sed // struct _class_ro_t { 4539193326Sed // uint32_t const flags; 4540193326Sed // uint32_t const instanceStart; 4541193326Sed // uint32_t const instanceSize; 4542193326Sed // uint32_t const reserved; // only when building for 64bit targets 4543193326Sed // const uint8_t * const ivarLayout; 4544193326Sed // const char *const name; 4545193326Sed // const struct _method_list_t * const baseMethods; 4546193326Sed // const struct _objc_protocol_list *const baseProtocols; 4547193326Sed // const struct _ivar_list_t *const ivars; 4548193326Sed // const uint8_t * const weakIvarLayout; 4549193326Sed // const struct _prop_list_t * const properties; 4550193326Sed // } 4551198092Srdivacky 4552193326Sed // FIXME. Add 'reserved' field in 64bit abi mode! 4553198092Srdivacky ClassRonfABITy = llvm::StructType::get(VMContext, IntTy, 4554193326Sed IntTy, 4555193326Sed IntTy, 4556193326Sed Int8PtrTy, 4557193326Sed Int8PtrTy, 4558193326Sed MethodListnfABIPtrTy, 4559193326Sed ProtocolListnfABIPtrTy, 4560193326Sed IvarListnfABIPtrTy, 4561193326Sed Int8PtrTy, 4562193326Sed PropertyListPtrTy, 4563193326Sed NULL); 4564193326Sed CGM.getModule().addTypeName("struct._class_ro_t", 4565193326Sed ClassRonfABITy); 4566198092Srdivacky 4567193326Sed // ImpnfABITy - LLVM for id (*)(id, SEL, ...) 4568193326Sed std::vector<const llvm::Type*> Params; 4569193326Sed Params.push_back(ObjectPtrTy); 4570193326Sed Params.push_back(SelectorPtrTy); 4571193326Sed ImpnfABITy = llvm::PointerType::getUnqual( 4572198092Srdivacky llvm::FunctionType::get(ObjectPtrTy, Params, false)); 4573198092Srdivacky 4574193326Sed // struct _class_t { 4575193326Sed // struct _class_t *isa; 4576193326Sed // struct _class_t * const superclass; 4577193326Sed // void *cache; 4578193326Sed // IMP *vtable; 4579193326Sed // struct class_ro_t *ro; 4580193326Sed // } 4581198092Srdivacky 4582198092Srdivacky llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext); 4583198092Srdivacky ClassnfABITy = 4584198092Srdivacky llvm::StructType::get(VMContext, 4585198092Srdivacky llvm::PointerType::getUnqual(ClassTyHolder), 4586198092Srdivacky llvm::PointerType::getUnqual(ClassTyHolder), 4587198092Srdivacky CachePtrTy, 4588198092Srdivacky llvm::PointerType::getUnqual(ImpnfABITy), 4589198092Srdivacky llvm::PointerType::getUnqual(ClassRonfABITy), 4590198092Srdivacky NULL); 4591193326Sed CGM.getModule().addTypeName("struct._class_t", ClassnfABITy); 4592193326Sed 4593193326Sed cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo( 4594198092Srdivacky ClassnfABITy); 4595198092Srdivacky 4596193326Sed // LLVM for struct _class_t * 4597193326Sed ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy); 4598198092Srdivacky 4599193326Sed // struct _category_t { 4600193326Sed // const char * const name; 4601193326Sed // struct _class_t *const cls; 4602193326Sed // const struct _method_list_t * const instance_methods; 4603193326Sed // const struct _method_list_t * const class_methods; 4604193326Sed // const struct _protocol_list_t * const protocols; 4605193326Sed // const struct _prop_list_t * const properties; 4606193326Sed // } 4607198092Srdivacky CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy, 4608193326Sed ClassnfABIPtrTy, 4609193326Sed MethodListnfABIPtrTy, 4610193326Sed MethodListnfABIPtrTy, 4611193326Sed ProtocolListnfABIPtrTy, 4612193326Sed PropertyListPtrTy, 4613193326Sed NULL); 4614193326Sed CGM.getModule().addTypeName("struct._category_t", CategorynfABITy); 4615198092Srdivacky 4616193326Sed // New types for nonfragile abi messaging. 4617193326Sed CodeGen::CodeGenTypes &Types = CGM.getTypes(); 4618193326Sed ASTContext &Ctx = CGM.getContext(); 4619198092Srdivacky 4620193326Sed // MessageRefTy - LLVM for: 4621193326Sed // struct _message_ref_t { 4622193326Sed // IMP messenger; 4623193326Sed // SEL name; 4624193326Sed // }; 4625198092Srdivacky 4626193326Sed // First the clang type for struct _message_ref_t 4627208600Srdivacky RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct, 4628207619Srdivacky Ctx.getTranslationUnitDecl(), 4629193326Sed SourceLocation(), 4630193326Sed &Ctx.Idents.get("_message_ref_t")); 4631195341Sed RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 4632198092Srdivacky Ctx.VoidPtrTy, 0, 0, false)); 4633195341Sed RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, 4634198092Srdivacky Ctx.getObjCSelType(), 0, 0, false)); 4635203955Srdivacky RD->completeDefinition(); 4636198092Srdivacky 4637193326Sed MessageRefCTy = Ctx.getTagDeclType(RD); 4638193326Sed MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy); 4639193326Sed MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy)); 4640198092Srdivacky 4641193326Sed // MessageRefPtrTy - LLVM for struct _message_ref_t* 4642193326Sed MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy); 4643198092Srdivacky 4644193326Sed // SuperMessageRefTy - LLVM for: 4645193326Sed // struct _super_message_ref_t { 4646193326Sed // SUPER_IMP messenger; 4647193326Sed // SEL name; 4648193326Sed // }; 4649198092Srdivacky SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy, 4650193326Sed SelectorPtrTy, 4651193326Sed NULL); 4652193326Sed CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy); 4653198092Srdivacky 4654193326Sed // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* 4655198092Srdivacky SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); 4656193326Sed 4657198092Srdivacky 4658193326Sed // struct objc_typeinfo { 4659193326Sed // const void** vtable; // objc_ehtype_vtable + 2 4660193326Sed // const char* name; // c++ typeinfo string 4661193326Sed // Class cls; 4662193326Sed // }; 4663198092Srdivacky EHTypeTy = llvm::StructType::get(VMContext, 4664198092Srdivacky llvm::PointerType::getUnqual(Int8PtrTy), 4665193326Sed Int8PtrTy, 4666193326Sed ClassnfABIPtrTy, 4667193326Sed NULL); 4668193326Sed CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy); 4669193326Sed EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy); 4670193326Sed} 4671193326Sed 4672198092Srdivackyllvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() { 4673193326Sed FinishNonFragileABIModule(); 4674198092Srdivacky 4675193326Sed return NULL; 4676193326Sed} 4677193326Sed 4678198092Srdivackyvoid CGObjCNonFragileABIMac::AddModuleClassList(const 4679198092Srdivacky std::vector<llvm::GlobalValue*> 4680198092Srdivacky &Container, 4681193326Sed const char *SymbolName, 4682193326Sed const char *SectionName) { 4683193326Sed unsigned NumClasses = Container.size(); 4684198092Srdivacky 4685193326Sed if (!NumClasses) 4686193326Sed return; 4687198092Srdivacky 4688193326Sed std::vector<llvm::Constant*> Symbols(NumClasses); 4689193326Sed for (unsigned i=0; i<NumClasses; i++) 4690193326Sed Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i], 4691193326Sed ObjCTypes.Int8PtrTy); 4692198092Srdivacky llvm::Constant* Init = 4693193326Sed llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, 4694193326Sed NumClasses), 4695193326Sed Symbols); 4696198092Srdivacky 4697193326Sed llvm::GlobalVariable *GV = 4698198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 4699193326Sed llvm::GlobalValue::InternalLinkage, 4700193326Sed Init, 4701198092Srdivacky SymbolName); 4702207619Srdivacky GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType())); 4703193326Sed GV->setSection(SectionName); 4704198092Srdivacky CGM.AddUsedGlobal(GV); 4705193326Sed} 4706198092Srdivacky 4707193326Sedvoid CGObjCNonFragileABIMac::FinishNonFragileABIModule() { 4708193326Sed // nonfragile abi has no module definition. 4709198092Srdivacky 4710193326Sed // Build list of all implemented class addresses in array 4711193326Sed // L_OBJC_LABEL_CLASS_$. 4712198092Srdivacky AddModuleClassList(DefinedClasses, 4713193326Sed "\01L_OBJC_LABEL_CLASS_$", 4714193326Sed "__DATA, __objc_classlist, regular, no_dead_strip"); 4715199482Srdivacky 4716199482Srdivacky for (unsigned i = 0; i < DefinedClasses.size(); i++) { 4717199482Srdivacky llvm::GlobalValue *IMPLGV = DefinedClasses[i]; 4718199482Srdivacky if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) 4719199482Srdivacky continue; 4720199482Srdivacky IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage); 4721199482Srdivacky } 4722199482Srdivacky 4723200583Srdivacky for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) { 4724200583Srdivacky llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i]; 4725200583Srdivacky if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage) 4726200583Srdivacky continue; 4727200583Srdivacky IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage); 4728200583Srdivacky } 4729199482Srdivacky 4730198092Srdivacky AddModuleClassList(DefinedNonLazyClasses, 4731193326Sed "\01L_OBJC_LABEL_NONLAZY_CLASS_$", 4732193326Sed "__DATA, __objc_nlclslist, regular, no_dead_strip"); 4733198092Srdivacky 4734193326Sed // Build list of all implemented category addresses in array 4735193326Sed // L_OBJC_LABEL_CATEGORY_$. 4736198092Srdivacky AddModuleClassList(DefinedCategories, 4737193326Sed "\01L_OBJC_LABEL_CATEGORY_$", 4738193326Sed "__DATA, __objc_catlist, regular, no_dead_strip"); 4739198092Srdivacky AddModuleClassList(DefinedNonLazyCategories, 4740193326Sed "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$", 4741193326Sed "__DATA, __objc_nlcatlist, regular, no_dead_strip"); 4742198092Srdivacky 4743207619Srdivacky EmitImageInfo(); 4744193326Sed} 4745193326Sed 4746193326Sed/// LegacyDispatchedSelector - Returns true if SEL is not in the list of 4747193326Sed/// NonLegacyDispatchMethods; false otherwise. What this means is that 4748198092Srdivacky/// except for the 19 selectors in the list, we generate 32bit-style 4749193326Sed/// message dispatch call for all the rest. 4750193326Sed/// 4751193326Sedbool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) { 4752207619Srdivacky switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) { 4753207619Srdivacky default: 4754207619Srdivacky assert(0 && "Invalid dispatch method!"); 4755207619Srdivacky case CodeGenOptions::Legacy: 4756203955Srdivacky return true; 4757207619Srdivacky case CodeGenOptions::NonLegacy: 4758207619Srdivacky return false; 4759207619Srdivacky case CodeGenOptions::Mixed: 4760207619Srdivacky break; 4761207619Srdivacky } 4762203955Srdivacky 4763207619Srdivacky // If so, see whether this selector is in the white-list of things which must 4764207619Srdivacky // use the new dispatch convention. We lazily build a dense set for this. 4765193326Sed if (NonLegacyDispatchMethods.empty()) { 4766193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("alloc")); 4767193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("class")); 4768193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("self")); 4769193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("isFlipped")); 4770193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("length")); 4771193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("count")); 4772193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("retain")); 4773193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("release")); 4774193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("autorelease")); 4775193326Sed NonLegacyDispatchMethods.insert(GetNullarySelector("hash")); 4776198092Srdivacky 4777193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("allocWithZone")); 4778193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("isKindOfClass")); 4779193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("respondsToSelector")); 4780193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("objectForKey")); 4781193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("objectAtIndex")); 4782193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("isEqualToString")); 4783193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("isEqual")); 4784193326Sed NonLegacyDispatchMethods.insert(GetUnarySelector("addObject")); 4785198092Srdivacky // "countByEnumeratingWithState:objects:count" 4786193326Sed IdentifierInfo *KeyIdents[] = { 4787198092Srdivacky &CGM.getContext().Idents.get("countByEnumeratingWithState"), 4788198092Srdivacky &CGM.getContext().Idents.get("objects"), 4789198092Srdivacky &CGM.getContext().Idents.get("count") 4790193326Sed }; 4791193326Sed NonLegacyDispatchMethods.insert( 4792193326Sed CGM.getContext().Selectors.getSelector(3, KeyIdents)); 4793193326Sed } 4794207619Srdivacky 4795193326Sed return (NonLegacyDispatchMethods.count(Sel) == 0); 4796193326Sed} 4797193326Sed 4798193326Sed// Metadata flags 4799193326Sedenum MetaDataDlags { 4800193326Sed CLS = 0x0, 4801193326Sed CLS_META = 0x1, 4802193326Sed CLS_ROOT = 0x2, 4803193326Sed OBJC2_CLS_HIDDEN = 0x10, 4804193326Sed CLS_EXCEPTION = 0x20 4805193326Sed}; 4806193326Sed/// BuildClassRoTInitializer - generate meta-data for: 4807193326Sed/// struct _class_ro_t { 4808193326Sed/// uint32_t const flags; 4809193326Sed/// uint32_t const instanceStart; 4810193326Sed/// uint32_t const instanceSize; 4811193326Sed/// uint32_t const reserved; // only when building for 64bit targets 4812193326Sed/// const uint8_t * const ivarLayout; 4813193326Sed/// const char *const name; 4814193326Sed/// const struct _method_list_t * const baseMethods; 4815193326Sed/// const struct _protocol_list_t *const baseProtocols; 4816193326Sed/// const struct _ivar_list_t *const ivars; 4817193326Sed/// const uint8_t * const weakIvarLayout; 4818193326Sed/// const struct _prop_list_t * const properties; 4819193326Sed/// } 4820193326Sed/// 4821193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( 4822198092Srdivacky unsigned flags, 4823198092Srdivacky unsigned InstanceStart, 4824198092Srdivacky unsigned InstanceSize, 4825198092Srdivacky const ObjCImplementationDecl *ID) { 4826193326Sed std::string ClassName = ID->getNameAsString(); 4827193326Sed std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets! 4828193326Sed Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags); 4829193326Sed Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart); 4830193326Sed Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize); 4831193326Sed // FIXME. For 64bit targets add 0 here. 4832198092Srdivacky Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) 4833198092Srdivacky : BuildIvarLayout(ID, true); 4834193326Sed Values[ 4] = GetClassName(ID->getIdentifier()); 4835193326Sed // const struct _method_list_t * const baseMethods; 4836193326Sed std::vector<llvm::Constant*> Methods; 4837193326Sed std::string MethodListName("\01l_OBJC_$_"); 4838193326Sed if (flags & CLS_META) { 4839193326Sed MethodListName += "CLASS_METHODS_" + ID->getNameAsString(); 4840198092Srdivacky for (ObjCImplementationDecl::classmeth_iterator 4841195341Sed i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { 4842193326Sed // Class methods should always be defined. 4843193326Sed Methods.push_back(GetMethodConstant(*i)); 4844193326Sed } 4845193326Sed } else { 4846193326Sed MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString(); 4847198092Srdivacky for (ObjCImplementationDecl::instmeth_iterator 4848195341Sed i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { 4849193326Sed // Instance methods should always be defined. 4850193326Sed Methods.push_back(GetMethodConstant(*i)); 4851193326Sed } 4852198092Srdivacky for (ObjCImplementationDecl::propimpl_iterator 4853195341Sed i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { 4854193326Sed ObjCPropertyImplDecl *PID = *i; 4855198092Srdivacky 4856193326Sed if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){ 4857193326Sed ObjCPropertyDecl *PD = PID->getPropertyDecl(); 4858198092Srdivacky 4859193326Sed if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) 4860193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 4861193326Sed Methods.push_back(C); 4862193326Sed if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) 4863193326Sed if (llvm::Constant *C = GetMethodConstant(MD)) 4864193326Sed Methods.push_back(C); 4865193326Sed } 4866193326Sed } 4867193326Sed } 4868198092Srdivacky Values[ 5] = EmitMethodList(MethodListName, 4869198092Srdivacky "__DATA, __objc_const", Methods); 4870198092Srdivacky 4871193326Sed const ObjCInterfaceDecl *OID = ID->getClassInterface(); 4872193326Sed assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer"); 4873198092Srdivacky Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_" 4874198398Srdivacky + OID->getName(), 4875212904Sdim OID->all_referenced_protocol_begin(), 4876212904Sdim OID->all_referenced_protocol_end()); 4877198092Srdivacky 4878193326Sed if (flags & CLS_META) 4879193326Sed Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); 4880193326Sed else 4881193326Sed Values[ 7] = EmitIvarList(ID); 4882198092Srdivacky Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) 4883198092Srdivacky : BuildIvarLayout(ID, false); 4884193326Sed if (flags & CLS_META) 4885193326Sed Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 4886193326Sed else 4887198398Srdivacky Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), 4888198398Srdivacky ID, ID->getClassInterface(), ObjCTypes); 4889193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy, 4890193326Sed Values); 4891193326Sed llvm::GlobalVariable *CLASS_RO_GV = 4892198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false, 4893198092Srdivacky llvm::GlobalValue::InternalLinkage, 4894198092Srdivacky Init, 4895198092Srdivacky (flags & CLS_META) ? 4896198092Srdivacky std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName : 4897198092Srdivacky std::string("\01l_OBJC_CLASS_RO_$_")+ClassName); 4898193326Sed CLASS_RO_GV->setAlignment( 4899207619Srdivacky CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy)); 4900193326Sed CLASS_RO_GV->setSection("__DATA, __objc_const"); 4901193326Sed return CLASS_RO_GV; 4902193326Sed 4903193326Sed} 4904193326Sed 4905193326Sed/// BuildClassMetaData - This routine defines that to-level meta-data 4906193326Sed/// for the given ClassName for: 4907193326Sed/// struct _class_t { 4908193326Sed/// struct _class_t *isa; 4909193326Sed/// struct _class_t * const superclass; 4910193326Sed/// void *cache; 4911193326Sed/// IMP *vtable; 4912193326Sed/// struct class_ro_t *ro; 4913193326Sed/// } 4914193326Sed/// 4915193326Sedllvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( 4916198092Srdivacky std::string &ClassName, 4917198092Srdivacky llvm::Constant *IsAGV, 4918198092Srdivacky llvm::Constant *SuperClassGV, 4919198092Srdivacky llvm::Constant *ClassRoGV, 4920198092Srdivacky bool HiddenVisibility) { 4921193326Sed std::vector<llvm::Constant*> Values(5); 4922193326Sed Values[0] = IsAGV; 4923198092Srdivacky Values[1] = SuperClassGV; 4924198092Srdivacky if (!Values[1]) 4925198092Srdivacky Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy); 4926193326Sed Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar 4927193326Sed Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar 4928193326Sed Values[4] = ClassRoGV; // &CLASS_RO_GV 4929198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy, 4930193326Sed Values); 4931193326Sed llvm::GlobalVariable *GV = GetClassGlobal(ClassName); 4932193326Sed GV->setInitializer(Init); 4933193326Sed GV->setSection("__DATA, __objc_data"); 4934193326Sed GV->setAlignment( 4935207619Srdivacky CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy)); 4936193326Sed if (HiddenVisibility) 4937193326Sed GV->setVisibility(llvm::GlobalValue::HiddenVisibility); 4938193326Sed return GV; 4939193326Sed} 4940193326Sed 4941198092Srdivackybool 4942193326SedCGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const { 4943195341Sed return OD->getClassMethod(GetNullarySelector("load")) != 0; 4944193326Sed} 4945193326Sed 4946193326Sedvoid CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, 4947193326Sed uint32_t &InstanceStart, 4948193326Sed uint32_t &InstanceSize) { 4949198092Srdivacky const ASTRecordLayout &RL = 4950193326Sed CGM.getContext().getASTObjCImplementationLayout(OID); 4951198092Srdivacky 4952193326Sed // InstanceSize is really instance end. 4953218893Sdim InstanceSize = RL.getDataSize().getQuantity(); 4954193326Sed 4955193326Sed // If there are no fields, the start is the same as the end. 4956193326Sed if (!RL.getFieldCount()) 4957193326Sed InstanceStart = InstanceSize; 4958193326Sed else 4959193326Sed InstanceStart = RL.getFieldOffset(0) / 8; 4960193326Sed} 4961193326Sed 4962193326Sedvoid CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { 4963193326Sed std::string ClassName = ID->getNameAsString(); 4964193326Sed if (!ObjCEmptyCacheVar) { 4965193326Sed ObjCEmptyCacheVar = new llvm::GlobalVariable( 4966198092Srdivacky CGM.getModule(), 4967198092Srdivacky ObjCTypes.CacheTy, 4968198092Srdivacky false, 4969198092Srdivacky llvm::GlobalValue::ExternalLinkage, 4970198092Srdivacky 0, 4971198092Srdivacky "_objc_empty_cache"); 4972198092Srdivacky 4973193326Sed ObjCEmptyVtableVar = new llvm::GlobalVariable( 4974198092Srdivacky CGM.getModule(), 4975198092Srdivacky ObjCTypes.ImpnfABITy, 4976198092Srdivacky false, 4977198092Srdivacky llvm::GlobalValue::ExternalLinkage, 4978198092Srdivacky 0, 4979198092Srdivacky "_objc_empty_vtable"); 4980193326Sed } 4981198092Srdivacky assert(ID->getClassInterface() && 4982193326Sed "CGObjCNonFragileABIMac::GenerateClass - class is 0"); 4983193326Sed // FIXME: Is this correct (that meta class size is never computed)? 4984198092Srdivacky uint32_t InstanceStart = 4985193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy); 4986193326Sed uint32_t InstanceSize = InstanceStart; 4987193326Sed uint32_t flags = CLS_META; 4988193326Sed std::string ObjCMetaClassName(getMetaclassSymbolPrefix()); 4989193326Sed std::string ObjCClassName(getClassSymbolPrefix()); 4990198092Srdivacky 4991193326Sed llvm::GlobalVariable *SuperClassGV, *IsAGV; 4992198092Srdivacky 4993198092Srdivacky bool classIsHidden = 4994218893Sdim ID->getClassInterface()->getVisibility() == HiddenVisibility; 4995193326Sed if (classIsHidden) 4996193326Sed flags |= OBJC2_CLS_HIDDEN; 4997207619Srdivacky if (ID->getNumIvarInitializers()) 4998207619Srdivacky flags |= eClassFlags_ABI2_HasCXXStructors; 4999193326Sed if (!ID->getClassInterface()->getSuperClass()) { 5000193326Sed // class is root 5001193326Sed flags |= CLS_ROOT; 5002193326Sed SuperClassGV = GetClassGlobal(ObjCClassName + ClassName); 5003193326Sed IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName); 5004193326Sed } else { 5005193326Sed // Has a root. Current class is not a root. 5006193326Sed const ObjCInterfaceDecl *Root = ID->getClassInterface(); 5007193326Sed while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) 5008193326Sed Root = Super; 5009193326Sed IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString()); 5010200583Srdivacky if (Root->hasAttr<WeakImportAttr>()) 5011200583Srdivacky IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5012193326Sed // work on super class metadata symbol. 5013198092Srdivacky std::string SuperClassName = 5014200583Srdivacky ObjCMetaClassName + 5015200583Srdivacky ID->getClassInterface()->getSuperClass()->getNameAsString(); 5016193326Sed SuperClassGV = GetClassGlobal(SuperClassName); 5017199482Srdivacky if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>()) 5018199482Srdivacky SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5019193326Sed } 5020193326Sed llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags, 5021193326Sed InstanceStart, 5022193326Sed InstanceSize,ID); 5023193326Sed std::string TClassName = ObjCMetaClassName + ClassName; 5024198092Srdivacky llvm::GlobalVariable *MetaTClass = 5025193326Sed BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV, 5026193326Sed classIsHidden); 5027199482Srdivacky DefinedMetaClasses.push_back(MetaTClass); 5028193326Sed 5029193326Sed // Metadata for the class 5030193326Sed flags = CLS; 5031193326Sed if (classIsHidden) 5032193326Sed flags |= OBJC2_CLS_HIDDEN; 5033207619Srdivacky if (ID->getNumIvarInitializers()) 5034207619Srdivacky flags |= eClassFlags_ABI2_HasCXXStructors; 5035193326Sed 5036194613Sed if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface())) 5037193326Sed flags |= CLS_EXCEPTION; 5038193326Sed 5039193326Sed if (!ID->getClassInterface()->getSuperClass()) { 5040193326Sed flags |= CLS_ROOT; 5041193326Sed SuperClassGV = 0; 5042193326Sed } else { 5043193326Sed // Has a root. Current class is not a root. 5044193326Sed std::string RootClassName = 5045193326Sed ID->getClassInterface()->getSuperClass()->getNameAsString(); 5046193326Sed SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName); 5047199482Srdivacky if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>()) 5048199482Srdivacky SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5049193326Sed } 5050193326Sed GetClassSizeInfo(ID, InstanceStart, InstanceSize); 5051193326Sed CLASS_RO_GV = BuildClassRoTInitializer(flags, 5052193326Sed InstanceStart, 5053198092Srdivacky InstanceSize, 5054193326Sed ID); 5055198092Srdivacky 5056193326Sed TClassName = ObjCClassName + ClassName; 5057198092Srdivacky llvm::GlobalVariable *ClassMD = 5058193326Sed BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV, 5059193326Sed classIsHidden); 5060193326Sed DefinedClasses.push_back(ClassMD); 5061193326Sed 5062193326Sed // Determine if this class is also "non-lazy". 5063193326Sed if (ImplementationIsNonLazy(ID)) 5064193326Sed DefinedNonLazyClasses.push_back(ClassMD); 5065193326Sed 5066193326Sed // Force the definition of the EHType if necessary. 5067193326Sed if (flags & CLS_EXCEPTION) 5068193326Sed GetInterfaceEHType(ID->getClassInterface(), true); 5069193326Sed} 5070193326Sed 5071193326Sed/// GenerateProtocolRef - This routine is called to generate code for 5072193326Sed/// a protocol reference expression; as in: 5073193326Sed/// @code 5074193326Sed/// @protocol(Proto1); 5075193326Sed/// @endcode 5076193326Sed/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1 5077193326Sed/// which will hold address of the protocol meta-data. 5078193326Sed/// 5079193326Sedllvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder, 5080198092Srdivacky const ObjCProtocolDecl *PD) { 5081198092Srdivacky 5082193326Sed // This routine is called for @protocol only. So, we must build definition 5083193326Sed // of protocol's meta-data (not a reference to it!) 5084193326Sed // 5085198092Srdivacky llvm::Constant *Init = 5086198092Srdivacky llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD), 5087198092Srdivacky ObjCTypes.ExternalProtocolPtrTy); 5088198092Srdivacky 5089193326Sed std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_"); 5090212904Sdim ProtocolName += PD->getName(); 5091198092Srdivacky 5092193326Sed llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName); 5093193326Sed if (PTGV) 5094199990Srdivacky return Builder.CreateLoad(PTGV, "tmp"); 5095193326Sed PTGV = new llvm::GlobalVariable( 5096198092Srdivacky CGM.getModule(), 5097198092Srdivacky Init->getType(), false, 5098198092Srdivacky llvm::GlobalValue::WeakAnyLinkage, 5099198092Srdivacky Init, 5100198092Srdivacky ProtocolName); 5101193326Sed PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip"); 5102193326Sed PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 5103198092Srdivacky CGM.AddUsedGlobal(PTGV); 5104199990Srdivacky return Builder.CreateLoad(PTGV, "tmp"); 5105193326Sed} 5106193326Sed 5107193326Sed/// GenerateCategory - Build metadata for a category implementation. 5108193326Sed/// struct _category_t { 5109193326Sed/// const char * const name; 5110193326Sed/// struct _class_t *const cls; 5111193326Sed/// const struct _method_list_t * const instance_methods; 5112193326Sed/// const struct _method_list_t * const class_methods; 5113193326Sed/// const struct _protocol_list_t * const protocols; 5114193326Sed/// const struct _prop_list_t * const properties; 5115193326Sed/// } 5116193326Sed/// 5117193326Sedvoid CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 5118193326Sed const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); 5119193326Sed const char *Prefix = "\01l_OBJC_$_CATEGORY_"; 5120198092Srdivacky std::string ExtCatName(Prefix + Interface->getNameAsString()+ 5121198092Srdivacky "_$_" + OCD->getNameAsString()); 5122198092Srdivacky std::string ExtClassName(getClassSymbolPrefix() + 5123193326Sed Interface->getNameAsString()); 5124198092Srdivacky 5125193326Sed std::vector<llvm::Constant*> Values(6); 5126193326Sed Values[0] = GetClassName(OCD->getIdentifier()); 5127193326Sed // meta-class entry symbol 5128193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName); 5129199482Srdivacky if (Interface->hasAttr<WeakImportAttr>()) 5130199482Srdivacky ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5131199482Srdivacky 5132193326Sed Values[1] = ClassGV; 5133193326Sed std::vector<llvm::Constant*> Methods; 5134193326Sed std::string MethodListName(Prefix); 5135198092Srdivacky MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() + 5136193326Sed "_$_" + OCD->getNameAsString(); 5137198092Srdivacky 5138198092Srdivacky for (ObjCCategoryImplDecl::instmeth_iterator 5139195341Sed i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { 5140193326Sed // Instance methods should always be defined. 5141193326Sed Methods.push_back(GetMethodConstant(*i)); 5142193326Sed } 5143198092Srdivacky 5144198092Srdivacky Values[2] = EmitMethodList(MethodListName, 5145198092Srdivacky "__DATA, __objc_const", 5146193326Sed Methods); 5147193326Sed 5148193326Sed MethodListName = Prefix; 5149193326Sed MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" + 5150193326Sed OCD->getNameAsString(); 5151193326Sed Methods.clear(); 5152198092Srdivacky for (ObjCCategoryImplDecl::classmeth_iterator 5153195341Sed i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { 5154193326Sed // Class methods should always be defined. 5155193326Sed Methods.push_back(GetMethodConstant(*i)); 5156193326Sed } 5157198092Srdivacky 5158198092Srdivacky Values[3] = EmitMethodList(MethodListName, 5159198092Srdivacky "__DATA, __objc_const", 5160193326Sed Methods); 5161198092Srdivacky const ObjCCategoryDecl *Category = 5162193326Sed Interface->FindCategoryDeclaration(OCD->getIdentifier()); 5163193326Sed if (Category) { 5164198398Srdivacky llvm::SmallString<256> ExtName; 5165198398Srdivacky llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_" 5166198398Srdivacky << OCD->getName(); 5167193326Sed Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_" 5168198398Srdivacky + Interface->getName() + "_$_" 5169198398Srdivacky + Category->getName(), 5170193326Sed Category->protocol_begin(), 5171193326Sed Category->protocol_end()); 5172198398Srdivacky Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), 5173198398Srdivacky OCD, Category, ObjCTypes); 5174198092Srdivacky } else { 5175193326Sed Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); 5176193326Sed Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); 5177193326Sed } 5178198092Srdivacky 5179198092Srdivacky llvm::Constant *Init = 5180198092Srdivacky llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy, 5181193326Sed Values); 5182193326Sed llvm::GlobalVariable *GCATV 5183198092Srdivacky = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy, 5184193326Sed false, 5185193326Sed llvm::GlobalValue::InternalLinkage, 5186193326Sed Init, 5187198092Srdivacky ExtCatName); 5188193326Sed GCATV->setAlignment( 5189207619Srdivacky CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy)); 5190193326Sed GCATV->setSection("__DATA, __objc_const"); 5191198092Srdivacky CGM.AddUsedGlobal(GCATV); 5192193326Sed DefinedCategories.push_back(GCATV); 5193193326Sed 5194193326Sed // Determine if this category is also "non-lazy". 5195193326Sed if (ImplementationIsNonLazy(OCD)) 5196193326Sed DefinedNonLazyCategories.push_back(GCATV); 5197193326Sed} 5198193326Sed 5199193326Sed/// GetMethodConstant - Return a struct objc_method constant for the 5200193326Sed/// given method if it has been defined. The result is null if the 5201193326Sed/// method has not been defined. The return value has type MethodPtrTy. 5202193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant( 5203198092Srdivacky const ObjCMethodDecl *MD) { 5204212904Sdim llvm::Function *Fn = GetMethodDefinition(MD); 5205193326Sed if (!Fn) 5206193326Sed return 0; 5207198092Srdivacky 5208193326Sed std::vector<llvm::Constant*> Method(3); 5209198092Srdivacky Method[0] = 5210198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 5211198092Srdivacky ObjCTypes.SelectorPtrTy); 5212193326Sed Method[1] = GetMethodVarType(MD); 5213193326Sed Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy); 5214193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method); 5215193326Sed} 5216193326Sed 5217193326Sed/// EmitMethodList - Build meta-data for method declarations 5218193326Sed/// struct _method_list_t { 5219193326Sed/// uint32_t entsize; // sizeof(struct _objc_method) 5220193326Sed/// uint32_t method_count; 5221193326Sed/// struct _objc_method method_list[method_count]; 5222193326Sed/// } 5223193326Sed/// 5224198398Srdivackyllvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name, 5225198398Srdivacky const char *Section, 5226198398Srdivacky const ConstantVector &Methods) { 5227193326Sed // Return null for empty list. 5228193326Sed if (Methods.empty()) 5229193326Sed return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy); 5230198092Srdivacky 5231193326Sed std::vector<llvm::Constant*> Values(3); 5232193326Sed // sizeof(struct _objc_method) 5233193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy); 5234193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 5235193326Sed // method_count 5236193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); 5237193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy, 5238193326Sed Methods.size()); 5239193326Sed Values[2] = llvm::ConstantArray::get(AT, Methods); 5240198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 5241198092Srdivacky 5242193326Sed llvm::GlobalVariable *GV = 5243198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 5244193326Sed llvm::GlobalValue::InternalLinkage, 5245193326Sed Init, 5246198092Srdivacky Name); 5247193326Sed GV->setAlignment( 5248207619Srdivacky CGM.getTargetData().getABITypeAlignment(Init->getType())); 5249193326Sed GV->setSection(Section); 5250198092Srdivacky CGM.AddUsedGlobal(GV); 5251193326Sed return llvm::ConstantExpr::getBitCast(GV, 5252193326Sed ObjCTypes.MethodListnfABIPtrTy); 5253193326Sed} 5254193326Sed 5255193326Sed/// ObjCIvarOffsetVariable - Returns the ivar offset variable for 5256193326Sed/// the given ivar. 5257206125Srdivackyllvm::GlobalVariable * 5258206125SrdivackyCGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, 5259206125Srdivacky const ObjCIvarDecl *Ivar) { 5260206125Srdivacky const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); 5261193326Sed std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() + 5262193326Sed '.' + Ivar->getNameAsString(); 5263198092Srdivacky llvm::GlobalVariable *IvarOffsetGV = 5264193326Sed CGM.getModule().getGlobalVariable(Name); 5265193326Sed if (!IvarOffsetGV) 5266198092Srdivacky IvarOffsetGV = 5267198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy, 5268193326Sed false, 5269193326Sed llvm::GlobalValue::ExternalLinkage, 5270193326Sed 0, 5271198092Srdivacky Name); 5272193326Sed return IvarOffsetGV; 5273193326Sed} 5274193326Sed 5275206125Srdivackyllvm::Constant * 5276206125SrdivackyCGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, 5277206125Srdivacky const ObjCIvarDecl *Ivar, 5278206125Srdivacky unsigned long int Offset) { 5279193326Sed llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar); 5280198092Srdivacky IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy, 5281193326Sed Offset)); 5282193326Sed IvarOffsetGV->setAlignment( 5283207619Srdivacky CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy)); 5284193326Sed 5285193326Sed // FIXME: This matches gcc, but shouldn't the visibility be set on the use as 5286193326Sed // well (i.e., in ObjCIvarOffsetVariable). 5287193326Sed if (Ivar->getAccessControl() == ObjCIvarDecl::Private || 5288193326Sed Ivar->getAccessControl() == ObjCIvarDecl::Package || 5289218893Sdim ID->getVisibility() == HiddenVisibility) 5290193326Sed IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 5291193326Sed else 5292193326Sed IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); 5293193326Sed IvarOffsetGV->setSection("__DATA, __objc_const"); 5294193326Sed return IvarOffsetGV; 5295193326Sed} 5296193326Sed 5297193326Sed/// EmitIvarList - Emit the ivar list for the given 5298193326Sed/// implementation. The return value has type 5299193326Sed/// IvarListnfABIPtrTy. 5300193326Sed/// struct _ivar_t { 5301193326Sed/// unsigned long int *offset; // pointer to ivar offset location 5302193326Sed/// char *name; 5303193326Sed/// char *type; 5304193326Sed/// uint32_t alignment; 5305193326Sed/// uint32_t size; 5306193326Sed/// } 5307193326Sed/// struct _ivar_list_t { 5308193326Sed/// uint32 entsize; // sizeof(struct _ivar_t) 5309193326Sed/// uint32 count; 5310193326Sed/// struct _iver_t list[count]; 5311193326Sed/// } 5312193326Sed/// 5313193326Sed 5314193326Sedllvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( 5315198092Srdivacky const ObjCImplementationDecl *ID) { 5316198092Srdivacky 5317193326Sed std::vector<llvm::Constant*> Ivars, Ivar(5); 5318198092Srdivacky 5319193326Sed const ObjCInterfaceDecl *OID = ID->getClassInterface(); 5320193326Sed assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface"); 5321198092Srdivacky 5322193326Sed // FIXME. Consolidate this with similar code in GenerateClass. 5323198092Srdivacky 5324193326Sed // Collect declared and synthesized ivars in a small vector. 5325193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; 5326193576Sed CGM.getContext().ShallowCollectObjCIvars(OID, OIvars); 5327198092Srdivacky 5328193326Sed for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { 5329193326Sed ObjCIvarDecl *IVD = OIvars[i]; 5330193576Sed // Ignore unnamed bit-fields. 5331193576Sed if (!IVD->getDeclName()) 5332193576Sed continue; 5333198092Srdivacky Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD, 5334193326Sed ComputeIvarBaseOffset(CGM, ID, IVD)); 5335193326Sed Ivar[1] = GetMethodVarName(IVD->getIdentifier()); 5336193326Sed Ivar[2] = GetMethodVarType(IVD); 5337193326Sed const llvm::Type *FieldTy = 5338193326Sed CGM.getTypes().ConvertTypeForMem(IVD->getType()); 5339193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy); 5340193326Sed unsigned Align = CGM.getContext().getPreferredTypeAlign( 5341198092Srdivacky IVD->getType().getTypePtr()) >> 3; 5342193326Sed Align = llvm::Log2_32(Align); 5343193326Sed Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align); 5344193326Sed // NOTE. Size of a bitfield does not match gcc's, because of the 5345193326Sed // way bitfields are treated special in each. But I am told that 5346193326Sed // 'size' for bitfield ivars is ignored by the runtime so it does 5347193326Sed // not matter. If it matters, there is enough info to get the 5348193326Sed // bitfield right! 5349193326Sed Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 5350193326Sed Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar)); 5351193326Sed } 5352193326Sed // Return null for empty list. 5353193326Sed if (Ivars.empty()) 5354193326Sed return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); 5355193326Sed std::vector<llvm::Constant*> Values(3); 5356193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy); 5357193326Sed Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 5358193326Sed Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size()); 5359193326Sed llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy, 5360193326Sed Ivars.size()); 5361193326Sed Values[2] = llvm::ConstantArray::get(AT, Ivars); 5362198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 5363193326Sed const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_"; 5364193326Sed llvm::GlobalVariable *GV = 5365198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 5366193326Sed llvm::GlobalValue::InternalLinkage, 5367193326Sed Init, 5368198398Srdivacky Prefix + OID->getName()); 5369193326Sed GV->setAlignment( 5370207619Srdivacky CGM.getTargetData().getABITypeAlignment(Init->getType())); 5371193326Sed GV->setSection("__DATA, __objc_const"); 5372198092Srdivacky 5373198092Srdivacky CGM.AddUsedGlobal(GV); 5374198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy); 5375193326Sed} 5376193326Sed 5377193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( 5378198092Srdivacky const ObjCProtocolDecl *PD) { 5379193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 5380198092Srdivacky 5381193326Sed if (!Entry) { 5382193326Sed // We use the initializer as a marker of whether this is a forward 5383193326Sed // reference or not. At module finalization we add the empty 5384193326Sed // contents for protocols which were referenced but never defined. 5385198092Srdivacky Entry = 5386198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false, 5387198092Srdivacky llvm::GlobalValue::ExternalLinkage, 5388198092Srdivacky 0, 5389198398Srdivacky "\01l_OBJC_PROTOCOL_$_" + PD->getName()); 5390193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 5391193326Sed } 5392198092Srdivacky 5393193326Sed return Entry; 5394193326Sed} 5395193326Sed 5396193326Sed/// GetOrEmitProtocol - Generate the protocol meta-data: 5397193326Sed/// @code 5398193326Sed/// struct _protocol_t { 5399193326Sed/// id isa; // NULL 5400193326Sed/// const char * const protocol_name; 5401193326Sed/// const struct _protocol_list_t * protocol_list; // super protocols 5402193326Sed/// const struct method_list_t * const instance_methods; 5403193326Sed/// const struct method_list_t * const class_methods; 5404193326Sed/// const struct method_list_t *optionalInstanceMethods; 5405193326Sed/// const struct method_list_t *optionalClassMethods; 5406193326Sed/// const struct _prop_list_t * properties; 5407193326Sed/// const uint32_t size; // sizeof(struct _protocol_t) 5408193326Sed/// const uint32_t flags; // = 0 5409193326Sed/// } 5410193326Sed/// @endcode 5411193326Sed/// 5412193326Sed 5413193326Sedllvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( 5414198092Srdivacky const ObjCProtocolDecl *PD) { 5415193326Sed llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; 5416198092Srdivacky 5417193326Sed // Early exit if a defining object has already been generated. 5418193326Sed if (Entry && Entry->hasInitializer()) 5419193326Sed return Entry; 5420193326Sed 5421193326Sed // Construct method lists. 5422193326Sed std::vector<llvm::Constant*> InstanceMethods, ClassMethods; 5423193326Sed std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; 5424198092Srdivacky for (ObjCProtocolDecl::instmeth_iterator 5425195341Sed i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { 5426193326Sed ObjCMethodDecl *MD = *i; 5427193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 5428193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 5429193326Sed OptInstanceMethods.push_back(C); 5430193326Sed } else { 5431193326Sed InstanceMethods.push_back(C); 5432198092Srdivacky } 5433193326Sed } 5434198092Srdivacky 5435198092Srdivacky for (ObjCProtocolDecl::classmeth_iterator 5436195341Sed i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { 5437193326Sed ObjCMethodDecl *MD = *i; 5438193326Sed llvm::Constant *C = GetMethodDescriptionConstant(MD); 5439193326Sed if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 5440193326Sed OptClassMethods.push_back(C); 5441193326Sed } else { 5442193326Sed ClassMethods.push_back(C); 5443198092Srdivacky } 5444193326Sed } 5445198092Srdivacky 5446193326Sed std::vector<llvm::Constant*> Values(10); 5447193326Sed // isa is NULL 5448193326Sed Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy); 5449193326Sed Values[1] = GetClassName(PD->getIdentifier()); 5450198398Srdivacky Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(), 5451198398Srdivacky PD->protocol_begin(), 5452198398Srdivacky PD->protocol_end()); 5453198092Srdivacky 5454193326Sed Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_" 5455198398Srdivacky + PD->getName(), 5456193326Sed "__DATA, __objc_const", 5457193326Sed InstanceMethods); 5458198092Srdivacky Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_" 5459198398Srdivacky + PD->getName(), 5460193326Sed "__DATA, __objc_const", 5461193326Sed ClassMethods); 5462193326Sed Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_" 5463198398Srdivacky + PD->getName(), 5464193326Sed "__DATA, __objc_const", 5465193326Sed OptInstanceMethods); 5466198092Srdivacky Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_" 5467198398Srdivacky + PD->getName(), 5468193326Sed "__DATA, __objc_const", 5469193326Sed OptClassMethods); 5470198398Srdivacky Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(), 5471193326Sed 0, PD, ObjCTypes); 5472198092Srdivacky uint32_t Size = 5473193326Sed CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); 5474193326Sed Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); 5475193326Sed Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy); 5476193326Sed llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy, 5477193326Sed Values); 5478198092Srdivacky 5479193326Sed if (Entry) { 5480193326Sed // Already created, fix the linkage and update the initializer. 5481193326Sed Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 5482193326Sed Entry->setInitializer(Init); 5483193326Sed } else { 5484198092Srdivacky Entry = 5485198398Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, 5486198398Srdivacky false, llvm::GlobalValue::WeakAnyLinkage, Init, 5487198398Srdivacky "\01l_OBJC_PROTOCOL_$_" + PD->getName()); 5488193326Sed Entry->setAlignment( 5489207619Srdivacky CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy)); 5490193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 5491193326Sed } 5492193326Sed Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); 5493198092Srdivacky CGM.AddUsedGlobal(Entry); 5494198092Srdivacky 5495193326Sed // Use this protocol meta-data to build protocol list table in section 5496193326Sed // __DATA, __objc_protolist 5497198398Srdivacky llvm::GlobalVariable *PTGV = 5498198398Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, 5499198398Srdivacky false, llvm::GlobalValue::WeakAnyLinkage, Entry, 5500198398Srdivacky "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName()); 5501193326Sed PTGV->setAlignment( 5502207619Srdivacky CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); 5503193326Sed PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip"); 5504193326Sed PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); 5505198092Srdivacky CGM.AddUsedGlobal(PTGV); 5506193326Sed return Entry; 5507193326Sed} 5508193326Sed 5509193326Sed/// EmitProtocolList - Generate protocol list meta-data: 5510193326Sed/// @code 5511193326Sed/// struct _protocol_list_t { 5512193326Sed/// long protocol_count; // Note, this is 32/64 bit 5513193326Sed/// struct _protocol_t[protocol_count]; 5514193326Sed/// } 5515193326Sed/// @endcode 5516193326Sed/// 5517193326Sedllvm::Constant * 5518198398SrdivackyCGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name, 5519198398Srdivacky ObjCProtocolDecl::protocol_iterator begin, 5520198398Srdivacky ObjCProtocolDecl::protocol_iterator end) { 5521193326Sed std::vector<llvm::Constant*> ProtocolRefs; 5522198092Srdivacky 5523193326Sed // Just return null for empty protocol lists 5524198092Srdivacky if (begin == end) 5525193326Sed return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy); 5526198092Srdivacky 5527193326Sed // FIXME: We shouldn't need to do this lookup here, should we? 5528198398Srdivacky llvm::SmallString<256> TmpName; 5529198398Srdivacky Name.toVector(TmpName); 5530198398Srdivacky llvm::GlobalVariable *GV = 5531198398Srdivacky CGM.getModule().getGlobalVariable(TmpName.str(), true); 5532193326Sed if (GV) 5533198398Srdivacky return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy); 5534198092Srdivacky 5535193326Sed for (; begin != end; ++begin) 5536193326Sed ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented??? 5537193326Sed 5538193326Sed // This list is null terminated. 5539193326Sed ProtocolRefs.push_back(llvm::Constant::getNullValue( 5540198092Srdivacky ObjCTypes.ProtocolnfABIPtrTy)); 5541198092Srdivacky 5542193326Sed std::vector<llvm::Constant*> Values(2); 5543198092Srdivacky Values[0] = 5544198092Srdivacky llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1); 5545198092Srdivacky Values[1] = 5546198092Srdivacky llvm::ConstantArray::get( 5547198092Srdivacky llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy, 5548198092Srdivacky ProtocolRefs.size()), 5549198092Srdivacky ProtocolRefs); 5550198092Srdivacky 5551198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 5552198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 5553193326Sed llvm::GlobalValue::InternalLinkage, 5554193326Sed Init, 5555198092Srdivacky Name); 5556193326Sed GV->setSection("__DATA, __objc_const"); 5557193326Sed GV->setAlignment( 5558207619Srdivacky CGM.getTargetData().getABITypeAlignment(Init->getType())); 5559198092Srdivacky CGM.AddUsedGlobal(GV); 5560198092Srdivacky return llvm::ConstantExpr::getBitCast(GV, 5561193326Sed ObjCTypes.ProtocolListnfABIPtrTy); 5562193326Sed} 5563193326Sed 5564193326Sed/// GetMethodDescriptionConstant - This routine build following meta-data: 5565193326Sed/// struct _objc_method { 5566193326Sed/// SEL _cmd; 5567193326Sed/// char *method_type; 5568193326Sed/// char *_imp; 5569193326Sed/// } 5570193326Sed 5571193326Sedllvm::Constant * 5572193326SedCGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) { 5573193326Sed std::vector<llvm::Constant*> Desc(3); 5574198092Srdivacky Desc[0] = 5575198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()), 5576198092Srdivacky ObjCTypes.SelectorPtrTy); 5577193326Sed Desc[1] = GetMethodVarType(MD); 5578193326Sed // Protocol methods have no implementation. So, this entry is always NULL. 5579193326Sed Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy); 5580193326Sed return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc); 5581193326Sed} 5582193326Sed 5583193326Sed/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference. 5584193326Sed/// This code gen. amounts to generating code for: 5585193326Sed/// @code 5586193326Sed/// (type *)((char *)base + _OBJC_IVAR_$_.ivar; 5587193326Sed/// @encode 5588198092Srdivacky/// 5589193326SedLValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( 5590208600Srdivacky CodeGen::CodeGenFunction &CGF, 5591208600Srdivacky QualType ObjectTy, 5592208600Srdivacky llvm::Value *BaseValue, 5593208600Srdivacky const ObjCIvarDecl *Ivar, 5594208600Srdivacky unsigned CVRQualifiers) { 5595208600Srdivacky ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface(); 5596193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 5597193326Sed EmitIvarOffset(CGF, ID, Ivar)); 5598193326Sed} 5599193326Sed 5600193326Sedllvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset( 5601198092Srdivacky CodeGen::CodeGenFunction &CGF, 5602198092Srdivacky const ObjCInterfaceDecl *Interface, 5603198092Srdivacky const ObjCIvarDecl *Ivar) { 5604199990Srdivacky return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar"); 5605193326Sed} 5606193326Sed 5607193326SedCodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend( 5608198092Srdivacky CodeGen::CodeGenFunction &CGF, 5609208600Srdivacky ReturnValueSlot Return, 5610198092Srdivacky QualType ResultType, 5611198092Srdivacky Selector Sel, 5612198092Srdivacky llvm::Value *Receiver, 5613198092Srdivacky QualType Arg0Ty, 5614198092Srdivacky bool IsSuper, 5615198092Srdivacky const CallArgList &CallArgs) { 5616193326Sed // FIXME. Even though IsSuper is passes. This function doese not handle calls 5617193326Sed // to 'super' receivers. 5618193326Sed CodeGenTypes &Types = CGM.getTypes(); 5619193326Sed llvm::Value *Arg0 = Receiver; 5620193326Sed if (!IsSuper) 5621193326Sed Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp"); 5622198092Srdivacky 5623193326Sed // Find the message function name. 5624193326Sed // FIXME. This is too much work to get the ABI-specific result type needed to 5625193326Sed // find the message name. 5626204643Srdivacky const CGFunctionInfo &FnInfo 5627206084Srdivacky = Types.getFunctionInfo(ResultType, CallArgList(), 5628206084Srdivacky FunctionType::ExtInfo()); 5629193326Sed llvm::Constant *Fn = 0; 5630193326Sed std::string Name("\01l_"); 5631210299Sed if (CGM.ReturnTypeUsesSRet(FnInfo)) { 5632212904Sdim if (IsSuper) { 5633212904Sdim Fn = ObjCTypes.getMessageSendSuper2StretFixupFn(); 5634212904Sdim Name += "objc_msgSendSuper2_stret_fixup"; 5635212904Sdim } else { 5636212904Sdim Fn = ObjCTypes.getMessageSendStretFixupFn(); 5637212904Sdim Name += "objc_msgSend_stret_fixup"; 5638212904Sdim } 5639210299Sed } else if (!IsSuper && CGM.ReturnTypeUsesFPRet(ResultType)) { 5640210299Sed Fn = ObjCTypes.getMessageSendFpretFixupFn(); 5641210299Sed Name += "objc_msgSend_fpret_fixup"; 5642198092Srdivacky } else { 5643212904Sdim if (IsSuper) { 5644212904Sdim Fn = ObjCTypes.getMessageSendSuper2FixupFn(); 5645212904Sdim Name += "objc_msgSendSuper2_fixup"; 5646212904Sdim } else { 5647212904Sdim Fn = ObjCTypes.getMessageSendFixupFn(); 5648212904Sdim Name += "objc_msgSend_fixup"; 5649212904Sdim } 5650193326Sed } 5651193326Sed assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend"); 5652193326Sed Name += '_'; 5653193326Sed std::string SelName(Sel.getAsString()); 5654193326Sed // Replace all ':' in selector name with '_' ouch! 5655198092Srdivacky for (unsigned i = 0; i < SelName.size(); i++) 5656193326Sed if (SelName[i] == ':') 5657193326Sed SelName[i] = '_'; 5658193326Sed Name += SelName; 5659193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 5660193326Sed if (!GV) { 5661193326Sed // Build message ref table entry. 5662193326Sed std::vector<llvm::Constant*> Values(2); 5663193326Sed Values[0] = Fn; 5664193326Sed Values[1] = GetMethodVarName(Sel); 5665198092Srdivacky llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false); 5666198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, 5667193326Sed llvm::GlobalValue::WeakAnyLinkage, 5668193326Sed Init, 5669198092Srdivacky Name); 5670193326Sed GV->setVisibility(llvm::GlobalValue::HiddenVisibility); 5671193326Sed GV->setAlignment(16); 5672193326Sed GV->setSection("__DATA, __objc_msgrefs, coalesced"); 5673193326Sed } 5674193326Sed llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy); 5675198092Srdivacky 5676193326Sed CallArgList ActualArgs; 5677193326Sed ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty)); 5678198092Srdivacky ActualArgs.push_back(std::make_pair(RValue::get(Arg1), 5679193326Sed ObjCTypes.MessageRefCPtrTy)); 5680193326Sed ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); 5681203955Srdivacky const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs, 5682206084Srdivacky FunctionType::ExtInfo()); 5683193326Sed llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0); 5684193326Sed Callee = CGF.Builder.CreateLoad(Callee); 5685193326Sed const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true); 5686193326Sed Callee = CGF.Builder.CreateBitCast(Callee, 5687193326Sed llvm::PointerType::getUnqual(FTy)); 5688208600Srdivacky return CGF.EmitCall(FnInfo1, Callee, Return, ActualArgs); 5689193326Sed} 5690193326Sed 5691193326Sed/// Generate code for a message send expression in the nonfragile abi. 5692198092SrdivackyCodeGen::RValue 5693198092SrdivackyCGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 5694208600Srdivacky ReturnValueSlot Return, 5695198092Srdivacky QualType ResultType, 5696198092Srdivacky Selector Sel, 5697198092Srdivacky llvm::Value *Receiver, 5698198092Srdivacky const CallArgList &CallArgs, 5699207619Srdivacky const ObjCInterfaceDecl *Class, 5700198092Srdivacky const ObjCMethodDecl *Method) { 5701193326Sed return LegacyDispatchedSelector(Sel) 5702208600Srdivacky ? EmitLegacyMessageSend(CGF, Return, ResultType, 5703208600Srdivacky EmitSelector(CGF.Builder, Sel), 5704198092Srdivacky Receiver, CGF.getContext().getObjCIdType(), 5705198092Srdivacky false, CallArgs, Method, ObjCTypes) 5706208600Srdivacky : EmitMessageSend(CGF, Return, ResultType, Sel, 5707198092Srdivacky Receiver, CGF.getContext().getObjCIdType(), 5708198092Srdivacky false, CallArgs); 5709193326Sed} 5710193326Sed 5711193326Sedllvm::GlobalVariable * 5712193326SedCGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) { 5713193326Sed llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); 5714193326Sed 5715193326Sed if (!GV) { 5716198092Srdivacky GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy, 5717198092Srdivacky false, llvm::GlobalValue::ExternalLinkage, 5718198092Srdivacky 0, Name); 5719193326Sed } 5720193326Sed 5721193326Sed return GV; 5722193326Sed} 5723193326Sed 5724198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder, 5725198092Srdivacky const ObjCInterfaceDecl *ID) { 5726193326Sed llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()]; 5727198092Srdivacky 5728193326Sed if (!Entry) { 5729193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5730193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 5731198092Srdivacky Entry = 5732198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, 5733198092Srdivacky false, llvm::GlobalValue::InternalLinkage, 5734198092Srdivacky ClassGV, 5735198092Srdivacky "\01L_OBJC_CLASSLIST_REFERENCES_$_"); 5736193326Sed Entry->setAlignment( 5737207619Srdivacky CGM.getTargetData().getABITypeAlignment( 5738198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 5739193326Sed Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip"); 5740198092Srdivacky CGM.AddUsedGlobal(Entry); 5741193326Sed } 5742198092Srdivacky 5743199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 5744193326Sed} 5745193326Sed 5746193326Sedllvm::Value * 5747198092SrdivackyCGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder, 5748193326Sed const ObjCInterfaceDecl *ID) { 5749193326Sed llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()]; 5750198092Srdivacky 5751193326Sed if (!Entry) { 5752193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5753193326Sed llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 5754198092Srdivacky Entry = 5755198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, 5756198092Srdivacky false, llvm::GlobalValue::InternalLinkage, 5757198092Srdivacky ClassGV, 5758198092Srdivacky "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); 5759193326Sed Entry->setAlignment( 5760207619Srdivacky CGM.getTargetData().getABITypeAlignment( 5761198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 5762193326Sed Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); 5763198092Srdivacky CGM.AddUsedGlobal(Entry); 5764193326Sed } 5765198092Srdivacky 5766199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 5767193326Sed} 5768193326Sed 5769193326Sed/// EmitMetaClassRef - Return a Value * of the address of _class_t 5770193326Sed/// meta-data 5771193326Sed/// 5772198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder, 5773198092Srdivacky const ObjCInterfaceDecl *ID) { 5774193326Sed llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; 5775193326Sed if (Entry) 5776199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 5777198092Srdivacky 5778193326Sed std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString()); 5779193326Sed llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName); 5780198092Srdivacky Entry = 5781198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false, 5782193326Sed llvm::GlobalValue::InternalLinkage, 5783198092Srdivacky MetaClassGV, 5784198092Srdivacky "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); 5785193326Sed Entry->setAlignment( 5786207619Srdivacky CGM.getTargetData().getABITypeAlignment( 5787198092Srdivacky ObjCTypes.ClassnfABIPtrTy)); 5788198092Srdivacky 5789193326Sed Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); 5790198092Srdivacky CGM.AddUsedGlobal(Entry); 5791198092Srdivacky 5792199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 5793193326Sed} 5794193326Sed 5795193326Sed/// GetClass - Return a reference to the class for the given interface 5796193326Sed/// decl. 5797193326Sedllvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder, 5798193326Sed const ObjCInterfaceDecl *ID) { 5799199482Srdivacky if (ID->hasAttr<WeakImportAttr>()) { 5800199482Srdivacky std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 5801199482Srdivacky llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName); 5802199482Srdivacky ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); 5803199482Srdivacky } 5804199482Srdivacky 5805193326Sed return EmitClassRef(Builder, ID); 5806193326Sed} 5807193326Sed 5808193326Sed/// Generates a message send where the super is the receiver. This is 5809193326Sed/// a message send to self with special delivery semantics indicating 5810193326Sed/// which class's method should be called. 5811193326SedCodeGen::RValue 5812193326SedCGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 5813208600Srdivacky ReturnValueSlot Return, 5814198092Srdivacky QualType ResultType, 5815198092Srdivacky Selector Sel, 5816198092Srdivacky const ObjCInterfaceDecl *Class, 5817198092Srdivacky bool isCategoryImpl, 5818198092Srdivacky llvm::Value *Receiver, 5819198092Srdivacky bool IsClassMessage, 5820198092Srdivacky const CodeGen::CallArgList &CallArgs, 5821198092Srdivacky const ObjCMethodDecl *Method) { 5822193326Sed // ... 5823193326Sed // Create and init a super structure; this is a (receiver, class) 5824193326Sed // pair we will pass to objc_msgSendSuper. 5825193326Sed llvm::Value *ObjCSuper = 5826193326Sed CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super"); 5827198092Srdivacky 5828193326Sed llvm::Value *ReceiverAsObject = 5829193326Sed CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); 5830193326Sed CGF.Builder.CreateStore(ReceiverAsObject, 5831193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 5832198092Srdivacky 5833193326Sed // If this is a class message the metaclass is passed as the target. 5834193326Sed llvm::Value *Target; 5835193326Sed if (IsClassMessage) { 5836193326Sed if (isCategoryImpl) { 5837193326Sed // Message sent to "super' in a class method defined in 5838193326Sed // a category implementation. 5839193326Sed Target = EmitClassRef(CGF.Builder, Class); 5840193326Sed Target = CGF.Builder.CreateStructGEP(Target, 0); 5841193326Sed Target = CGF.Builder.CreateLoad(Target); 5842198092Srdivacky } else 5843193326Sed Target = EmitMetaClassRef(CGF.Builder, Class); 5844198092Srdivacky } else 5845193326Sed Target = EmitSuperClassRef(CGF.Builder, Class); 5846198092Srdivacky 5847193326Sed // FIXME: We shouldn't need to do this cast, rectify the ASTContext and 5848193326Sed // ObjCTypes types. 5849193326Sed const llvm::Type *ClassTy = 5850193326Sed CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); 5851193326Sed Target = CGF.Builder.CreateBitCast(Target, ClassTy); 5852193326Sed CGF.Builder.CreateStore(Target, 5853193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 5854198092Srdivacky 5855193326Sed return (LegacyDispatchedSelector(Sel)) 5856208600Srdivacky ? EmitLegacyMessageSend(CGF, Return, ResultType, 5857208600Srdivacky EmitSelector(CGF.Builder, Sel), 5858198092Srdivacky ObjCSuper, ObjCTypes.SuperPtrCTy, 5859198092Srdivacky true, CallArgs, Method, ObjCTypes) 5860208600Srdivacky : EmitMessageSend(CGF, Return, ResultType, Sel, 5861198092Srdivacky ObjCSuper, ObjCTypes.SuperPtrCTy, 5862198092Srdivacky true, CallArgs); 5863193326Sed} 5864193326Sed 5865198092Srdivackyllvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder, 5866210299Sed Selector Sel, bool lval) { 5867193326Sed llvm::GlobalVariable *&Entry = SelectorReferences[Sel]; 5868198092Srdivacky 5869193326Sed if (!Entry) { 5870198092Srdivacky llvm::Constant *Casted = 5871198092Srdivacky llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel), 5872198092Srdivacky ObjCTypes.SelectorPtrTy); 5873198092Srdivacky Entry = 5874198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false, 5875198092Srdivacky llvm::GlobalValue::InternalLinkage, 5876198092Srdivacky Casted, "\01L_OBJC_SELECTOR_REFERENCES_"); 5877193326Sed Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip"); 5878198092Srdivacky CGM.AddUsedGlobal(Entry); 5879193326Sed } 5880198092Srdivacky 5881210299Sed if (lval) 5882210299Sed return Entry; 5883199990Srdivacky return Builder.CreateLoad(Entry, "tmp"); 5884193326Sed} 5885193326Sed/// EmitObjCIvarAssign - Code gen for assigning to a __strong object. 5886198092Srdivacky/// objc_assign_ivar (id src, id *dst, ptrdiff_t) 5887193326Sed/// 5888193326Sedvoid CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 5889198092Srdivacky llvm::Value *src, 5890198092Srdivacky llvm::Value *dst, 5891198092Srdivacky llvm::Value *ivarOffset) { 5892193326Sed const llvm::Type * SrcTy = src->getType(); 5893193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5894193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5895193326Sed assert(Size <= 8 && "does not support size > 8"); 5896193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5897193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5898193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5899193326Sed } 5900193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5901193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5902198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(), 5903198092Srdivacky src, dst, ivarOffset); 5904193326Sed return; 5905193326Sed} 5906193326Sed 5907193326Sed/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object. 5908193326Sed/// objc_assign_strongCast (id src, id *dst) 5909193326Sed/// 5910193326Sedvoid CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( 5911198092Srdivacky CodeGen::CodeGenFunction &CGF, 5912198092Srdivacky llvm::Value *src, llvm::Value *dst) { 5913193326Sed const llvm::Type * SrcTy = src->getType(); 5914193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5915193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5916193326Sed assert(Size <= 8 && "does not support size > 8"); 5917193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5918198092Srdivacky : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5919193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5920193326Sed } 5921193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5922193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5923193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(), 5924193326Sed src, dst, "weakassign"); 5925193326Sed return; 5926193326Sed} 5927193326Sed 5928198092Srdivackyvoid CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( 5929198092Srdivacky CodeGen::CodeGenFunction &CGF, 5930198092Srdivacky llvm::Value *DestPtr, 5931198092Srdivacky llvm::Value *SrcPtr, 5932210299Sed llvm::Value *Size) { 5933198092Srdivacky SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy); 5934198092Srdivacky DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy); 5935198092Srdivacky CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(), 5936210299Sed DestPtr, SrcPtr, Size); 5937198092Srdivacky return; 5938198092Srdivacky} 5939198092Srdivacky 5940193326Sed/// EmitObjCWeakRead - Code gen for loading value of a __weak 5941193326Sed/// object: objc_read_weak (id *src) 5942193326Sed/// 5943193326Sedllvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( 5944198092Srdivacky CodeGen::CodeGenFunction &CGF, 5945198092Srdivacky llvm::Value *AddrWeakObj) { 5946193326Sed const llvm::Type* DestTy = 5947198092Srdivacky cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType(); 5948198092Srdivacky AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy); 5949193326Sed llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(), 5950193326Sed AddrWeakObj, "weakread"); 5951193326Sed read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); 5952193326Sed return read_weak; 5953193326Sed} 5954193326Sed 5955193326Sed/// EmitObjCWeakAssign - Code gen for assigning to a __weak object. 5956193326Sed/// objc_assign_weak (id src, id *dst) 5957193326Sed/// 5958193326Sedvoid CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 5959198092Srdivacky llvm::Value *src, llvm::Value *dst) { 5960193326Sed const llvm::Type * SrcTy = src->getType(); 5961193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5962193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5963193326Sed assert(Size <= 8 && "does not support size > 8"); 5964193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5965193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5966193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5967193326Sed } 5968193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5969193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5970193326Sed CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(), 5971193326Sed src, dst, "weakassign"); 5972193326Sed return; 5973193326Sed} 5974193326Sed 5975193326Sed/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. 5976193326Sed/// objc_assign_global (id src, id *dst) 5977193326Sed/// 5978193326Sedvoid CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 5979212904Sdim llvm::Value *src, llvm::Value *dst, 5980212904Sdim bool threadlocal) { 5981193326Sed const llvm::Type * SrcTy = src->getType(); 5982193326Sed if (!isa<llvm::PointerType>(SrcTy)) { 5983193326Sed unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); 5984193326Sed assert(Size <= 8 && "does not support size > 8"); 5985193326Sed src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) 5986193326Sed : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); 5987193326Sed src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); 5988193326Sed } 5989193326Sed src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); 5990193326Sed dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy); 5991212904Sdim if (!threadlocal) 5992212904Sdim CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(), 5993212904Sdim src, dst, "globalassign"); 5994212904Sdim else 5995212904Sdim CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(), 5996212904Sdim src, dst, "threadlocalassign"); 5997193326Sed return; 5998193326Sed} 5999193326Sed 6000212904Sdimnamespace { 6001212904Sdim struct CallSyncExit : EHScopeStack::Cleanup { 6002212904Sdim llvm::Value *SyncExitFn; 6003212904Sdim llvm::Value *SyncArg; 6004212904Sdim CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg) 6005212904Sdim : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {} 6006212904Sdim 6007212904Sdim void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { 6008212904Sdim CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow(); 6009212904Sdim } 6010212904Sdim }; 6011212904Sdim} 6012212904Sdim 6013198092Srdivackyvoid 6014210299SedCGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 6015210299Sed const ObjCAtSynchronizedStmt &S) { 6016210299Sed // Evaluate the lock operand. This should dominate the cleanup. 6017210299Sed llvm::Value *SyncArg = CGF.EmitScalarExpr(S.getSynchExpr()); 6018193326Sed 6019210299Sed // Acquire the lock. 6020210299Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); 6021210299Sed CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg) 6022210299Sed ->setDoesNotThrow(); 6023210299Sed 6024210299Sed // Register an all-paths cleanup to release the lock. 6025212904Sdim CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup, 6026212904Sdim ObjCTypes.getSyncExitFn(), 6027212904Sdim SyncArg); 6028210299Sed 6029210299Sed // Emit the body of the statement. 6030210299Sed CGF.EmitStmt(S.getSynchBody()); 6031193326Sed 6032210299Sed // Pop the lock-release cleanup. 6033210299Sed CGF.PopCleanupBlock(); 6034210299Sed} 6035193326Sed 6036210299Sednamespace { 6037210299Sed struct CatchHandler { 6038210299Sed const VarDecl *Variable; 6039210299Sed const Stmt *Body; 6040210299Sed llvm::BasicBlock *Block; 6041210299Sed llvm::Value *TypeInfo; 6042210299Sed }; 6043198092Srdivacky 6044212904Sdim struct CallObjCEndCatch : EHScopeStack::Cleanup { 6045210299Sed CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) : 6046210299Sed MightThrow(MightThrow), Fn(Fn) {} 6047210299Sed bool MightThrow; 6048210299Sed llvm::Value *Fn; 6049193326Sed 6050210299Sed void Emit(CodeGenFunction &CGF, bool IsForEH) { 6051210299Sed if (!MightThrow) { 6052210299Sed CGF.Builder.CreateCall(Fn)->setDoesNotThrow(); 6053210299Sed return; 6054210299Sed } 6055193326Sed 6056210299Sed CGF.EmitCallOrInvoke(Fn, 0, 0); 6057210299Sed } 6058210299Sed }; 6059210299Sed} 6060193326Sed 6061212904Sdimllvm::Constant * 6062212904SdimCGObjCNonFragileABIMac::GetEHType(QualType T) { 6063212904Sdim // There's a particular fixed type info for 'id'. 6064212904Sdim if (T->isObjCIdType() || 6065212904Sdim T->isObjCQualifiedIdType()) { 6066212904Sdim llvm::Constant *IDEHType = 6067212904Sdim CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id"); 6068212904Sdim if (!IDEHType) 6069212904Sdim IDEHType = 6070212904Sdim new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, 6071212904Sdim false, 6072212904Sdim llvm::GlobalValue::ExternalLinkage, 6073212904Sdim 0, "OBJC_EHTYPE_id"); 6074212904Sdim return IDEHType; 6075212904Sdim } 6076212904Sdim 6077212904Sdim // All other types should be Objective-C interface pointer types. 6078212904Sdim const ObjCObjectPointerType *PT = 6079212904Sdim T->getAs<ObjCObjectPointerType>(); 6080212904Sdim assert(PT && "Invalid @catch type."); 6081212904Sdim const ObjCInterfaceType *IT = PT->getInterfaceType(); 6082212904Sdim assert(IT && "Invalid @catch type."); 6083212904Sdim return GetInterfaceEHType(IT->getDecl(), false); 6084212904Sdim} 6085212904Sdim 6086210299Sedvoid CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF, 6087210299Sed const ObjCAtTryStmt &S) { 6088210299Sed // Jump destination for falling out of catch bodies. 6089210299Sed CodeGenFunction::JumpDest Cont; 6090210299Sed if (S.getNumCatchStmts()) 6091210299Sed Cont = CGF.getJumpDestInCurrentScope("eh.cont"); 6092193326Sed 6093210299Sed CodeGenFunction::FinallyInfo FinallyInfo; 6094210299Sed if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) 6095210299Sed FinallyInfo = CGF.EnterFinallyBlock(Finally->getFinallyBody(), 6096210299Sed ObjCTypes.getObjCBeginCatchFn(), 6097210299Sed ObjCTypes.getObjCEndCatchFn(), 6098210299Sed ObjCTypes.getExceptionRethrowFn()); 6099210299Sed 6100210299Sed llvm::SmallVector<CatchHandler, 8> Handlers; 6101210299Sed 6102210299Sed // Enter the catch, if there is one. 6103210299Sed if (S.getNumCatchStmts()) { 6104210299Sed for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) { 6105210299Sed const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I); 6106207619Srdivacky const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); 6107193326Sed 6108210299Sed Handlers.push_back(CatchHandler()); 6109210299Sed CatchHandler &Handler = Handlers.back(); 6110210299Sed Handler.Variable = CatchDecl; 6111210299Sed Handler.Body = CatchStmt->getCatchBody(); 6112210299Sed Handler.Block = CGF.createBasicBlock("catch"); 6113210299Sed 6114210299Sed // @catch(...) always matches. 6115207619Srdivacky if (!CatchDecl) { 6116210299Sed Handler.TypeInfo = 0; // catch-all 6117210299Sed // Don't consider any other catches. 6118207619Srdivacky break; 6119207619Srdivacky } 6120193326Sed 6121212904Sdim Handler.TypeInfo = GetEHType(CatchDecl->getType()); 6122193326Sed } 6123193326Sed 6124210299Sed EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size()); 6125210299Sed for (unsigned I = 0, E = Handlers.size(); I != E; ++I) 6126210299Sed Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block); 6127193326Sed } 6128210299Sed 6129210299Sed // Emit the try body. 6130210299Sed CGF.EmitStmt(S.getTryBody()); 6131198092Srdivacky 6132210299Sed // Leave the try. 6133210299Sed if (S.getNumCatchStmts()) 6134210299Sed CGF.EHStack.popCatch(); 6135193326Sed 6136210299Sed // Remember where we were. 6137210299Sed CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); 6138193326Sed 6139210299Sed // Emit the handlers. 6140210299Sed for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { 6141210299Sed CatchHandler &Handler = Handlers[I]; 6142193326Sed 6143210299Sed CGF.EmitBlock(Handler.Block); 6144210299Sed llvm::Value *RawExn = CGF.Builder.CreateLoad(CGF.getExceptionSlot()); 6145193326Sed 6146210299Sed // Enter the catch. 6147210299Sed llvm::CallInst *Exn = 6148210299Sed CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), RawExn, 6149210299Sed "exn.adjusted"); 6150210299Sed Exn->setDoesNotThrow(); 6151198092Srdivacky 6152210299Sed // Add a cleanup to leave the catch. 6153210299Sed bool EndCatchMightThrow = (Handler.Variable == 0); 6154212904Sdim CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup, 6155212904Sdim EndCatchMightThrow, 6156212904Sdim ObjCTypes.getObjCEndCatchFn()); 6157193326Sed 6158210299Sed // Bind the catch parameter if it exists. 6159210299Sed if (const VarDecl *CatchParam = Handler.Variable) { 6160210299Sed const llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType()); 6161210299Sed llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType); 6162198092Srdivacky 6163218893Sdim CGF.EmitAutoVarDecl(*CatchParam); 6164210299Sed CGF.Builder.CreateStore(CastExn, CGF.GetAddrOfLocalVar(CatchParam)); 6165193326Sed } 6166193326Sed 6167210299Sed CGF.ObjCEHValueStack.push_back(Exn); 6168210299Sed CGF.EmitStmt(Handler.Body); 6169210299Sed CGF.ObjCEHValueStack.pop_back(); 6170193326Sed 6171210299Sed // Leave the earlier cleanup. 6172210299Sed CGF.PopCleanupBlock(); 6173193326Sed 6174210299Sed CGF.EmitBranchThroughCleanup(Cont); 6175210299Sed } 6176193326Sed 6177210299Sed // Go back to the try-statement fallthrough. 6178210299Sed CGF.Builder.restoreIP(SavedIP); 6179193326Sed 6180210299Sed // Pop out of the normal cleanup on the finally. 6181210299Sed if (S.getFinallyStmt()) 6182210299Sed CGF.ExitFinallyBlock(FinallyInfo); 6183193326Sed 6184212904Sdim if (Cont.isValid()) 6185212904Sdim CGF.EmitBlock(Cont.getBlock()); 6186193326Sed} 6187193326Sed 6188193326Sed/// EmitThrowStmt - Generate code for a throw statement. 6189193326Sedvoid CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 6190193326Sed const ObjCAtThrowStmt &S) { 6191193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 6192218893Sdim llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr); 6193218893Sdim Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, 6194218893Sdim "tmp"); 6195218893Sdim llvm::Value *Args[] = { Exception }; 6196218893Sdim CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(), 6197218893Sdim Args, Args+1) 6198218893Sdim .setDoesNotReturn(); 6199193326Sed } else { 6200218893Sdim CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn(), 0, 0) 6201218893Sdim .setDoesNotReturn(); 6202193326Sed } 6203193326Sed 6204218893Sdim CGF.Builder.CreateUnreachable(); 6205193326Sed CGF.Builder.ClearInsertionPoint(); 6206193326Sed} 6207193326Sed 6208212904Sdimllvm::Constant * 6209198092SrdivackyCGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, 6210193326Sed bool ForDefinition) { 6211193326Sed llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()]; 6212193326Sed 6213193326Sed // If we don't need a definition, return the entry if found or check 6214193326Sed // if we use an external reference. 6215193326Sed if (!ForDefinition) { 6216193326Sed if (Entry) 6217193326Sed return Entry; 6218193326Sed 6219193326Sed // If this type (or a super class) has the __objc_exception__ 6220193326Sed // attribute, emit an external reference. 6221194613Sed if (hasObjCExceptionAttribute(CGM.getContext(), ID)) 6222198092Srdivacky return Entry = 6223198092Srdivacky new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, 6224193326Sed llvm::GlobalValue::ExternalLinkage, 6225198092Srdivacky 0, 6226198398Srdivacky ("OBJC_EHTYPE_$_" + 6227198092Srdivacky ID->getIdentifier()->getName())); 6228193326Sed } 6229198092Srdivacky 6230193326Sed // Otherwise we need to either make a new entry or fill in the 6231193326Sed // initializer. 6232193326Sed assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition"); 6233193326Sed std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); 6234193326Sed std::string VTableName = "objc_ehtype_vtable"; 6235198092Srdivacky llvm::GlobalVariable *VTableGV = 6236193326Sed CGM.getModule().getGlobalVariable(VTableName); 6237193326Sed if (!VTableGV) 6238198092Srdivacky VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, 6239198092Srdivacky false, 6240193326Sed llvm::GlobalValue::ExternalLinkage, 6241198092Srdivacky 0, VTableName); 6242193326Sed 6243210299Sed llvm::Value *VTableIdx = 6244210299Sed llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2); 6245193326Sed 6246193326Sed std::vector<llvm::Constant*> Values(3); 6247193326Sed Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1); 6248193326Sed Values[1] = GetClassName(ID->getIdentifier()); 6249193326Sed Values[2] = GetClassGlobal(ClassName); 6250198092Srdivacky llvm::Constant *Init = 6251198092Srdivacky llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values); 6252193326Sed 6253193326Sed if (Entry) { 6254193326Sed Entry->setInitializer(Init); 6255193326Sed } else { 6256198092Srdivacky Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, 6257193326Sed llvm::GlobalValue::WeakAnyLinkage, 6258198092Srdivacky Init, 6259198398Srdivacky ("OBJC_EHTYPE_$_" + 6260198092Srdivacky ID->getIdentifier()->getName())); 6261193326Sed } 6262193326Sed 6263218893Sdim if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility) 6264193326Sed Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); 6265207619Srdivacky Entry->setAlignment(CGM.getTargetData().getABITypeAlignment( 6266207619Srdivacky ObjCTypes.EHTypeTy)); 6267193326Sed 6268193326Sed if (ForDefinition) { 6269193326Sed Entry->setSection("__DATA,__objc_const"); 6270193326Sed Entry->setLinkage(llvm::GlobalValue::ExternalLinkage); 6271193326Sed } else { 6272193326Sed Entry->setSection("__DATA,__datacoal_nt,coalesced"); 6273193326Sed } 6274193326Sed 6275193326Sed return Entry; 6276193326Sed} 6277198092Srdivacky 6278193326Sed/* *** */ 6279193326Sed 6280193326SedCodeGen::CGObjCRuntime * 6281193326SedCodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) { 6282193326Sed return new CGObjCMac(CGM); 6283193326Sed} 6284193326Sed 6285193326SedCodeGen::CGObjCRuntime * 6286193326SedCodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) { 6287193326Sed return new CGObjCNonFragileABIMac(CGM); 6288193326Sed} 6289