CGObjCGNU.cpp revision 207619
1193326Sed//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===// 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 GNU runtime. The 11193326Sed// class in this file generates structures used by the GNU Objective-C runtime 12193326Sed// library. These structures are defined in objc/objc.h and objc/objc-api.h in 13193326Sed// the GNU runtime distribution. 14193326Sed// 15193326Sed//===----------------------------------------------------------------------===// 16193326Sed 17193326Sed#include "CGObjCRuntime.h" 18193326Sed#include "CodeGenModule.h" 19193326Sed#include "CodeGenFunction.h" 20193326Sed 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 27193326Sed#include "llvm/Intrinsics.h" 28193326Sed#include "llvm/Module.h" 29207619Srdivacky#include "llvm/LLVMContext.h" 30193326Sed#include "llvm/ADT/SmallVector.h" 31193326Sed#include "llvm/ADT/StringMap.h" 32193326Sed#include "llvm/Support/Compiler.h" 33193326Sed#include "llvm/Target/TargetData.h" 34193326Sed 35193326Sed#include <map> 36193326Sed 37193326Sed 38193326Sedusing namespace clang; 39193326Sedusing namespace CodeGen; 40193326Sedusing llvm::dyn_cast; 41193326Sed 42193326Sed// The version of the runtime that this class targets. Must match the version 43193326Sed// in the runtime. 44193326Sedstatic const int RuntimeVersion = 8; 45193326Sedstatic const int NonFragileRuntimeVersion = 9; 46193326Sedstatic const int ProtocolVersion = 2; 47198092Srdivackystatic const int NonFragileProtocolVersion = 3; 48193326Sed 49193326Sednamespace { 50193326Sedclass CGObjCGNU : public CodeGen::CGObjCRuntime { 51193326Sedprivate: 52193326Sed CodeGen::CodeGenModule &CGM; 53193326Sed llvm::Module &TheModule; 54193326Sed const llvm::PointerType *SelectorTy; 55198092Srdivacky const llvm::IntegerType *Int8Ty; 56193326Sed const llvm::PointerType *PtrToInt8Ty; 57193326Sed const llvm::FunctionType *IMPTy; 58193326Sed const llvm::PointerType *IdTy; 59203955Srdivacky const llvm::PointerType *PtrToIdTy; 60204643Srdivacky CanQualType ASTIdTy; 61193326Sed const llvm::IntegerType *IntTy; 62193326Sed const llvm::PointerType *PtrTy; 63193326Sed const llvm::IntegerType *LongTy; 64193326Sed const llvm::PointerType *PtrToIntTy; 65193326Sed llvm::GlobalAlias *ClassPtrAlias; 66193326Sed llvm::GlobalAlias *MetaClassPtrAlias; 67193326Sed std::vector<llvm::Constant*> Classes; 68193326Sed std::vector<llvm::Constant*> Categories; 69193326Sed std::vector<llvm::Constant*> ConstantStrings; 70203955Srdivacky llvm::StringMap<llvm::Constant*> ObjCStrings; 71193326Sed llvm::Function *LoadFunction; 72193326Sed llvm::StringMap<llvm::Constant*> ExistingProtocols; 73193326Sed typedef std::pair<std::string, std::string> TypedSelector; 74193326Sed std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors; 75193326Sed llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors; 76203955Srdivacky // Selectors that we don't emit in GC mode 77203955Srdivacky Selector RetainSel, ReleaseSel, AutoreleaseSel; 78203955Srdivacky // Functions used for GC. 79203955Srdivacky llvm::Constant *IvarAssignFn, *StrongCastAssignFn, *MemMoveFn, *WeakReadFn, 80203955Srdivacky *WeakAssignFn, *GlobalAssignFn; 81193326Sed // Some zeros used for GEPs in lots of places. 82193326Sed llvm::Constant *Zeros[2]; 83193326Sed llvm::Constant *NULLPtr; 84198092Srdivacky llvm::LLVMContext &VMContext; 85207619Srdivacky /// Metadata kind used to tie method lookups to message sends. 86207619Srdivacky unsigned msgSendMDKind; 87193326Sedprivate: 88193326Sed llvm::Constant *GenerateIvarList( 89193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, 90193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes, 91193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets); 92193326Sed llvm::Constant *GenerateMethodList(const std::string &ClassName, 93193326Sed const std::string &CategoryName, 94198092Srdivacky const llvm::SmallVectorImpl<Selector> &MethodSels, 95198092Srdivacky const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes, 96193326Sed bool isClassMethodList); 97193326Sed llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName); 98198092Srdivacky llvm::Constant *GeneratePropertyList(const ObjCImplementationDecl *OID, 99198092Srdivacky llvm::SmallVectorImpl<Selector> &InstanceMethodSels, 100198092Srdivacky llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes); 101193326Sed llvm::Constant *GenerateProtocolList( 102193326Sed const llvm::SmallVectorImpl<std::string> &Protocols); 103198092Srdivacky // To ensure that all protocols are seen by the runtime, we add a category on 104198092Srdivacky // a class defined in the runtime, declaring no methods, but adopting the 105198092Srdivacky // protocols. 106198092Srdivacky void GenerateProtocolHolderCategory(void); 107193326Sed llvm::Constant *GenerateClassStructure( 108193326Sed llvm::Constant *MetaClass, 109193326Sed llvm::Constant *SuperClass, 110193326Sed unsigned info, 111193326Sed const char *Name, 112193326Sed llvm::Constant *Version, 113193326Sed llvm::Constant *InstanceSize, 114193326Sed llvm::Constant *IVars, 115193326Sed llvm::Constant *Methods, 116198092Srdivacky llvm::Constant *Protocols, 117198092Srdivacky llvm::Constant *IvarOffsets, 118207619Srdivacky llvm::Constant *Properties, 119207619Srdivacky bool isMeta=false); 120193326Sed llvm::Constant *GenerateProtocolMethodList( 121193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames, 122193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes); 123193326Sed llvm::Constant *MakeConstantString(const std::string &Str, const std::string 124193326Sed &Name=""); 125198092Srdivacky llvm::Constant *ExportUniqueString(const std::string &Str, const std::string 126198092Srdivacky prefix); 127193326Sed llvm::Constant *MakeGlobal(const llvm::StructType *Ty, 128203955Srdivacky std::vector<llvm::Constant*> &V, llvm::StringRef Name="", 129202379Srdivacky llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage); 130193326Sed llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty, 131203955Srdivacky std::vector<llvm::Constant*> &V, llvm::StringRef Name="", 132202379Srdivacky llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage); 133193326Sed llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, 134193326Sed const ObjCIvarDecl *Ivar); 135194613Sed void EmitClassRef(const std::string &className); 136203955Srdivacky llvm::Value* EnforceType(CGBuilderTy B, llvm::Value *V, const llvm::Type *Ty){ 137203955Srdivacky if (V->getType() == Ty) return V; 138203955Srdivacky return B.CreateBitCast(V, Ty); 139203955Srdivacky } 140193326Sedpublic: 141193326Sed CGObjCGNU(CodeGen::CodeGenModule &cgm); 142202879Srdivacky virtual llvm::Constant *GenerateConstantString(const StringLiteral *); 143198092Srdivacky virtual CodeGen::RValue 144193326Sed GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 145193326Sed QualType ResultType, 146193326Sed Selector Sel, 147193326Sed llvm::Value *Receiver, 148193326Sed const CallArgList &CallArgs, 149207619Srdivacky const ObjCInterfaceDecl *Class, 150193326Sed const ObjCMethodDecl *Method); 151198092Srdivacky virtual CodeGen::RValue 152193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 153193326Sed QualType ResultType, 154193326Sed Selector Sel, 155193326Sed const ObjCInterfaceDecl *Class, 156193326Sed bool isCategoryImpl, 157193326Sed llvm::Value *Receiver, 158193326Sed bool IsClassMessage, 159198092Srdivacky const CallArgList &CallArgs, 160198092Srdivacky const ObjCMethodDecl *Method); 161193326Sed virtual llvm::Value *GetClass(CGBuilderTy &Builder, 162193326Sed const ObjCInterfaceDecl *OID); 163193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel); 164193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl 165193326Sed *Method); 166198092Srdivacky 167198092Srdivacky virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, 168193326Sed const ObjCContainerDecl *CD); 169193326Sed virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); 170193326Sed virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); 171193326Sed virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, 172193326Sed const ObjCProtocolDecl *PD); 173193326Sed virtual void GenerateProtocol(const ObjCProtocolDecl *PD); 174193326Sed virtual llvm::Function *ModuleInitFunction(); 175193326Sed virtual llvm::Function *GetPropertyGetFunction(); 176193326Sed virtual llvm::Function *GetPropertySetFunction(); 177207619Srdivacky virtual llvm::Function *GetCopyStructFunction(); 178198092Srdivacky virtual llvm::Constant *EnumerationMutationFunction(); 179198092Srdivacky 180193326Sed virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 181193326Sed const Stmt &S); 182193326Sed virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 183193326Sed const ObjCAtThrowStmt &S); 184193326Sed virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 185193326Sed llvm::Value *AddrWeakObj); 186193326Sed virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 187193326Sed llvm::Value *src, llvm::Value *dst); 188193326Sed virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 189193326Sed llvm::Value *src, llvm::Value *dest); 190193326Sed virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 191198092Srdivacky llvm::Value *src, llvm::Value *dest, 192198092Srdivacky llvm::Value *ivarOffset); 193193326Sed virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 194193326Sed llvm::Value *src, llvm::Value *dest); 195198092Srdivacky virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 196198092Srdivacky llvm::Value *DestPtr, 197198092Srdivacky llvm::Value *SrcPtr, 198198092Srdivacky QualType Ty); 199193326Sed virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 200193326Sed QualType ObjectTy, 201193326Sed llvm::Value *BaseValue, 202193326Sed const ObjCIvarDecl *Ivar, 203193326Sed unsigned CVRQualifiers); 204193326Sed virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 205193326Sed const ObjCInterfaceDecl *Interface, 206193326Sed const ObjCIvarDecl *Ivar); 207193326Sed}; 208193326Sed} // end anonymous namespace 209193326Sed 210193326Sed 211194613Sed/// Emits a reference to a dummy variable which is emitted with each class. 212194613Sed/// This ensures that a linker error will be generated when trying to link 213194613Sed/// together modules where a referenced class is not defined. 214198092Srdivackyvoid CGObjCGNU::EmitClassRef(const std::string &className) { 215194613Sed std::string symbolRef = "__objc_class_ref_" + className; 216194613Sed // Don't emit two copies of the same symbol 217198092Srdivacky if (TheModule.getGlobalVariable(symbolRef)) 218198092Srdivacky return; 219194613Sed std::string symbolName = "__objc_class_name_" + className; 220194613Sed llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName); 221194613Sed if (!ClassSymbol) { 222198092Srdivacky ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false, 223198092Srdivacky llvm::GlobalValue::ExternalLinkage, 0, symbolName); 224194613Sed } 225198092Srdivacky new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true, 226198092Srdivacky llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef); 227194613Sed} 228193326Sed 229193326Sedstatic std::string SymbolNameForMethod(const std::string &ClassName, const 230193326Sed std::string &CategoryName, const std::string &MethodName, bool isClassMethod) 231193326Sed{ 232202379Srdivacky std::string MethodNameColonStripped = MethodName; 233202379Srdivacky std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(), 234202379Srdivacky ':', '_'); 235202379Srdivacky return std::string(isClassMethod ? "_c_" : "_i_") + ClassName + "_" + 236202379Srdivacky CategoryName + "_" + MethodNameColonStripped; 237193326Sed} 238193326Sed 239193326SedCGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm) 240193326Sed : CGM(cgm), TheModule(CGM.getModule()), ClassPtrAlias(0), 241198092Srdivacky MetaClassPtrAlias(0), VMContext(cgm.getLLVMContext()) { 242207619Srdivacky 243207619Srdivacky msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend"); 244207619Srdivacky 245193326Sed IntTy = cast<llvm::IntegerType>( 246193326Sed CGM.getTypes().ConvertType(CGM.getContext().IntTy)); 247193326Sed LongTy = cast<llvm::IntegerType>( 248193326Sed CGM.getTypes().ConvertType(CGM.getContext().LongTy)); 249198092Srdivacky 250198092Srdivacky Int8Ty = llvm::Type::getInt8Ty(VMContext); 251198092Srdivacky // C string type. Used in lots of places. 252198092Srdivacky PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty); 253198092Srdivacky 254193326Sed Zeros[0] = llvm::ConstantInt::get(LongTy, 0); 255193326Sed Zeros[1] = Zeros[0]; 256198092Srdivacky NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty); 257193326Sed // Get the selector Type. 258202879Srdivacky QualType selTy = CGM.getContext().getObjCSelType(); 259202879Srdivacky if (QualType() == selTy) { 260202879Srdivacky SelectorTy = PtrToInt8Ty; 261202879Srdivacky } else { 262202879Srdivacky SelectorTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(selTy)); 263202879Srdivacky } 264193326Sed 265193326Sed PtrToIntTy = llvm::PointerType::getUnqual(IntTy); 266193326Sed PtrTy = PtrToInt8Ty; 267198092Srdivacky 268193326Sed // Object type 269204643Srdivacky ASTIdTy = CGM.getContext().getCanonicalType(CGM.getContext().getObjCIdType()); 270202879Srdivacky if (QualType() == ASTIdTy) { 271202879Srdivacky IdTy = PtrToInt8Ty; 272202879Srdivacky } else { 273202879Srdivacky IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy)); 274202879Srdivacky } 275203955Srdivacky PtrToIdTy = llvm::PointerType::getUnqual(IdTy); 276198092Srdivacky 277193326Sed // IMP type 278193326Sed std::vector<const llvm::Type*> IMPArgs; 279193326Sed IMPArgs.push_back(IdTy); 280193326Sed IMPArgs.push_back(SelectorTy); 281193326Sed IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true); 282203955Srdivacky 283203955Srdivacky if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { 284203955Srdivacky // Get selectors needed in GC mode 285203955Srdivacky RetainSel = GetNullarySelector("retain", CGM.getContext()); 286203955Srdivacky ReleaseSel = GetNullarySelector("release", CGM.getContext()); 287203955Srdivacky AutoreleaseSel = GetNullarySelector("autorelease", CGM.getContext()); 288203955Srdivacky 289203955Srdivacky // Get functions needed in GC mode 290203955Srdivacky 291203955Srdivacky // id objc_assign_ivar(id, id, ptrdiff_t); 292203955Srdivacky std::vector<const llvm::Type*> Args(1, IdTy); 293203955Srdivacky Args.push_back(PtrToIdTy); 294203955Srdivacky // FIXME: ptrdiff_t 295203955Srdivacky Args.push_back(LongTy); 296203955Srdivacky llvm::FunctionType *FTy = llvm::FunctionType::get(IdTy, Args, false); 297203955Srdivacky IvarAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); 298203955Srdivacky // id objc_assign_strongCast (id, id*) 299203955Srdivacky Args.pop_back(); 300203955Srdivacky FTy = llvm::FunctionType::get(IdTy, Args, false); 301203955Srdivacky StrongCastAssignFn = 302203955Srdivacky CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); 303203955Srdivacky // id objc_assign_global(id, id*); 304203955Srdivacky FTy = llvm::FunctionType::get(IdTy, Args, false); 305203955Srdivacky GlobalAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); 306203955Srdivacky // id objc_assign_weak(id, id*); 307203955Srdivacky FTy = llvm::FunctionType::get(IdTy, Args, false); 308203955Srdivacky WeakAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); 309203955Srdivacky // id objc_read_weak(id*); 310203955Srdivacky Args.clear(); 311203955Srdivacky Args.push_back(PtrToIdTy); 312203955Srdivacky FTy = llvm::FunctionType::get(IdTy, Args, false); 313203955Srdivacky WeakReadFn = CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); 314203955Srdivacky // void *objc_memmove_collectable(void*, void *, size_t); 315203955Srdivacky Args.clear(); 316203955Srdivacky Args.push_back(PtrToInt8Ty); 317203955Srdivacky Args.push_back(PtrToInt8Ty); 318203955Srdivacky // FIXME: size_t 319203955Srdivacky Args.push_back(LongTy); 320203955Srdivacky FTy = llvm::FunctionType::get(IdTy, Args, false); 321203955Srdivacky MemMoveFn = CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); 322203955Srdivacky } 323193326Sed} 324198092Srdivacky 325193326Sed// This has to perform the lookup every time, since posing and related 326193326Sed// techniques can modify the name -> class mapping. 327193326Sedllvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder, 328193326Sed const ObjCInterfaceDecl *OID) { 329193326Sed llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getNameAsString()); 330202379Srdivacky // With the incompatible ABI, this will need to be replaced with a direct 331202379Srdivacky // reference to the class symbol. For the compatible nonfragile ABI we are 332202379Srdivacky // still performing this lookup at run time but emitting the symbol for the 333202379Srdivacky // class externally so that we can make the switch later. 334194613Sed EmitClassRef(OID->getNameAsString()); 335193326Sed ClassName = Builder.CreateStructGEP(ClassName, 0); 336193326Sed 337193326Sed std::vector<const llvm::Type*> Params(1, PtrToInt8Ty); 338193326Sed llvm::Constant *ClassLookupFn = 339193326Sed CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, 340193326Sed Params, 341193326Sed true), 342193326Sed "objc_lookup_class"); 343193326Sed return Builder.CreateCall(ClassLookupFn, ClassName); 344193326Sed} 345193326Sed 346193326Sedllvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel) { 347193326Sed llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()]; 348193326Sed if (US == 0) 349193326Sed US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy), 350198092Srdivacky llvm::GlobalValue::PrivateLinkage, 351198092Srdivacky ".objc_untyped_selector_alias"+Sel.getAsString(), 352193326Sed NULL, &TheModule); 353198092Srdivacky 354193326Sed return Builder.CreateLoad(US); 355193326Sed} 356193326Sed 357193326Sedllvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl 358193326Sed *Method) { 359193326Sed 360193326Sed std::string SelName = Method->getSelector().getAsString(); 361193326Sed std::string SelTypes; 362193326Sed CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes); 363193326Sed // Typed selectors 364193326Sed TypedSelector Selector = TypedSelector(SelName, 365193326Sed SelTypes); 366193326Sed 367193326Sed // If it's already cached, return it. 368198092Srdivacky if (TypedSelectors[Selector]) { 369198092Srdivacky return Builder.CreateLoad(TypedSelectors[Selector]); 370193326Sed } 371193326Sed 372193326Sed // If it isn't, cache it. 373193326Sed llvm::GlobalAlias *Sel = new llvm::GlobalAlias( 374193326Sed llvm::PointerType::getUnqual(SelectorTy), 375198092Srdivacky llvm::GlobalValue::PrivateLinkage, ".objc_selector_alias" + SelName, 376193326Sed NULL, &TheModule); 377193326Sed TypedSelectors[Selector] = Sel; 378193326Sed 379193326Sed return Builder.CreateLoad(Sel); 380193326Sed} 381193326Sed 382193326Sedllvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str, 383193326Sed const std::string &Name) { 384198092Srdivacky llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str()); 385193326Sed return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2); 386193326Sed} 387198092Srdivackyllvm::Constant *CGObjCGNU::ExportUniqueString(const std::string &Str, 388198092Srdivacky const std::string prefix) { 389198092Srdivacky std::string name = prefix + Str; 390198092Srdivacky llvm::Constant *ConstStr = TheModule.getGlobalVariable(name); 391198092Srdivacky if (!ConstStr) { 392198092Srdivacky llvm::Constant *value = llvm::ConstantArray::get(VMContext, Str, true); 393198092Srdivacky ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true, 394198092Srdivacky llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str); 395198092Srdivacky } 396198092Srdivacky return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2); 397198092Srdivacky} 398198092Srdivacky 399193326Sedllvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty, 400203955Srdivacky std::vector<llvm::Constant*> &V, llvm::StringRef Name, 401202379Srdivacky llvm::GlobalValue::LinkageTypes linkage) { 402193326Sed llvm::Constant *C = llvm::ConstantStruct::get(Ty, V); 403198092Srdivacky return new llvm::GlobalVariable(TheModule, Ty, false, 404198092Srdivacky llvm::GlobalValue::InternalLinkage, C, Name); 405193326Sed} 406198092Srdivacky 407193326Sedllvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty, 408203955Srdivacky std::vector<llvm::Constant*> &V, llvm::StringRef Name, 409202379Srdivacky llvm::GlobalValue::LinkageTypes linkage) { 410193326Sed llvm::Constant *C = llvm::ConstantArray::get(Ty, V); 411198092Srdivacky return new llvm::GlobalVariable(TheModule, Ty, false, 412198092Srdivacky llvm::GlobalValue::InternalLinkage, C, Name); 413193326Sed} 414193326Sed 415193326Sed/// Generate an NSConstantString object. 416202879Srdivackyllvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) { 417203955Srdivacky 418202879Srdivacky std::string Str(SL->getStrData(), SL->getByteLength()); 419202879Srdivacky 420203955Srdivacky // Look for an existing one 421203955Srdivacky llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str); 422203955Srdivacky if (old != ObjCStrings.end()) 423203955Srdivacky return old->getValue(); 424203955Srdivacky 425193326Sed std::vector<llvm::Constant*> Ivars; 426193326Sed Ivars.push_back(NULLPtr); 427193326Sed Ivars.push_back(MakeConstantString(Str)); 428193326Sed Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size())); 429193326Sed llvm::Constant *ObjCStr = MakeGlobal( 430198092Srdivacky llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL), 431193326Sed Ivars, ".objc_str"); 432203955Srdivacky ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty); 433203955Srdivacky ObjCStrings[Str] = ObjCStr; 434203955Srdivacky ConstantStrings.push_back(ObjCStr); 435193326Sed return ObjCStr; 436193326Sed} 437193326Sed 438193326Sed///Generates a message send where the super is the receiver. This is a message 439193326Sed///send to self with special delivery semantics indicating which class's method 440193326Sed///should be called. 441193326SedCodeGen::RValue 442193326SedCGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 443193326Sed QualType ResultType, 444193326Sed Selector Sel, 445193326Sed const ObjCInterfaceDecl *Class, 446193326Sed bool isCategoryImpl, 447193326Sed llvm::Value *Receiver, 448193326Sed bool IsClassMessage, 449198092Srdivacky const CallArgList &CallArgs, 450198092Srdivacky const ObjCMethodDecl *Method) { 451203955Srdivacky if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { 452203955Srdivacky if (Sel == RetainSel || Sel == AutoreleaseSel) { 453203955Srdivacky return RValue::get(Receiver); 454203955Srdivacky } 455203955Srdivacky if (Sel == ReleaseSel) { 456203955Srdivacky return RValue::get(0); 457203955Srdivacky } 458203955Srdivacky } 459193326Sed 460207619Srdivacky CGBuilderTy &Builder = CGF.Builder; 461207619Srdivacky llvm::Value *cmd = GetSelector(Builder, Sel); 462207619Srdivacky 463207619Srdivacky 464193326Sed CallArgList ActualArgs; 465193326Sed 466193326Sed ActualArgs.push_back( 467207619Srdivacky std::make_pair(RValue::get(Builder.CreateBitCast(Receiver, IdTy)), 468198092Srdivacky ASTIdTy)); 469193326Sed ActualArgs.push_back(std::make_pair(RValue::get(cmd), 470193326Sed CGF.getContext().getObjCSelType())); 471193326Sed ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); 472193326Sed 473193326Sed CodeGenTypes &Types = CGM.getTypes(); 474203955Srdivacky const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs, 475206084Srdivacky FunctionType::ExtInfo()); 476198092Srdivacky const llvm::FunctionType *impType = 477198092Srdivacky Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); 478193326Sed 479193326Sed llvm::Value *ReceiverClass = 0; 480193326Sed if (isCategoryImpl) { 481193326Sed llvm::Constant *classLookupFunction = 0; 482193326Sed std::vector<const llvm::Type*> Params; 483193326Sed Params.push_back(PtrTy); 484193326Sed if (IsClassMessage) { 485193326Sed classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get( 486193326Sed IdTy, Params, true), "objc_get_meta_class"); 487193326Sed } else { 488193326Sed classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get( 489193326Sed IdTy, Params, true), "objc_get_class"); 490193326Sed } 491207619Srdivacky ReceiverClass = Builder.CreateCall(classLookupFunction, 492193326Sed MakeConstantString(Class->getNameAsString())); 493193326Sed } else { 494193326Sed // Set up global aliases for the metaclass or class pointer if they do not 495193326Sed // already exist. These will are forward-references which will be set to 496198092Srdivacky // pointers to the class and metaclass structure created for the runtime 497198092Srdivacky // load function. To send a message to super, we look up the value of the 498193326Sed // super_class pointer from either the class or metaclass structure. 499193326Sed if (IsClassMessage) { 500193326Sed if (!MetaClassPtrAlias) { 501193326Sed MetaClassPtrAlias = new llvm::GlobalAlias(IdTy, 502193326Sed llvm::GlobalValue::InternalLinkage, ".objc_metaclass_ref" + 503193326Sed Class->getNameAsString(), NULL, &TheModule); 504193326Sed } 505193326Sed ReceiverClass = MetaClassPtrAlias; 506193326Sed } else { 507193326Sed if (!ClassPtrAlias) { 508193326Sed ClassPtrAlias = new llvm::GlobalAlias(IdTy, 509193326Sed llvm::GlobalValue::InternalLinkage, ".objc_class_ref" + 510193326Sed Class->getNameAsString(), NULL, &TheModule); 511193326Sed } 512193326Sed ReceiverClass = ClassPtrAlias; 513193326Sed } 514193326Sed } 515193326Sed // Cast the pointer to a simplified version of the class structure 516207619Srdivacky ReceiverClass = Builder.CreateBitCast(ReceiverClass, 517198092Srdivacky llvm::PointerType::getUnqual( 518198092Srdivacky llvm::StructType::get(VMContext, IdTy, IdTy, NULL))); 519193326Sed // Get the superclass pointer 520207619Srdivacky ReceiverClass = Builder.CreateStructGEP(ReceiverClass, 1); 521193326Sed // Load the superclass pointer 522207619Srdivacky ReceiverClass = Builder.CreateLoad(ReceiverClass); 523193326Sed // Construct the structure used to look up the IMP 524198092Srdivacky llvm::StructType *ObjCSuperTy = llvm::StructType::get(VMContext, 525198092Srdivacky Receiver->getType(), IdTy, NULL); 526207619Srdivacky llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy); 527193326Sed 528207619Srdivacky Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0)); 529207619Srdivacky Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1)); 530193326Sed 531193326Sed // Get the IMP 532193326Sed std::vector<const llvm::Type*> Params; 533193326Sed Params.push_back(llvm::PointerType::getUnqual(ObjCSuperTy)); 534193326Sed Params.push_back(SelectorTy); 535207619Srdivacky 536207619Srdivacky llvm::Value *lookupArgs[] = {ObjCSuper, cmd}; 537207619Srdivacky llvm::Value *imp; 538207619Srdivacky 539207619Srdivacky if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { 540207619Srdivacky // The lookup function returns a slot, which can be safely cached. 541207619Srdivacky llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy, 542207619Srdivacky IntTy, llvm::PointerType::getUnqual(impType), NULL); 543207619Srdivacky 544207619Srdivacky llvm::Constant *lookupFunction = 545207619Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get( 546207619Srdivacky llvm::PointerType::getUnqual(SlotTy), Params, true), 547207619Srdivacky "objc_slot_lookup_super"); 548207619Srdivacky 549207619Srdivacky llvm::CallInst *slot = Builder.CreateCall(lookupFunction, lookupArgs, 550207619Srdivacky lookupArgs+2); 551207619Srdivacky slot->setOnlyReadsMemory(); 552207619Srdivacky 553207619Srdivacky imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4)); 554207619Srdivacky } else { 555198092Srdivacky llvm::Constant *lookupFunction = 556193326Sed CGM.CreateRuntimeFunction(llvm::FunctionType::get( 557193326Sed llvm::PointerType::getUnqual(impType), Params, true), 558193326Sed "objc_msg_lookup_super"); 559207619Srdivacky imp = Builder.CreateCall(lookupFunction, lookupArgs, lookupArgs+2); 560207619Srdivacky } 561193326Sed 562207619Srdivacky llvm::Value *impMD[] = { 563207619Srdivacky llvm::MDString::get(VMContext, Sel.getAsString()), 564207619Srdivacky llvm::MDString::get(VMContext, Class->getSuperClass()->getNameAsString()), 565207619Srdivacky llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsClassMessage) 566207619Srdivacky }; 567207619Srdivacky llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD, 3); 568193326Sed 569207619Srdivacky llvm::Instruction *call; 570207619Srdivacky RValue msgRet = CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs, 571207619Srdivacky 0, &call); 572207619Srdivacky call->setMetadata(msgSendMDKind, node); 573207619Srdivacky return msgRet; 574193326Sed} 575193326Sed 576198092Srdivacky/// Generate code for a message send expression. 577193326SedCodeGen::RValue 578193326SedCGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 579193326Sed QualType ResultType, 580193326Sed Selector Sel, 581193326Sed llvm::Value *Receiver, 582193326Sed const CallArgList &CallArgs, 583207619Srdivacky const ObjCInterfaceDecl *Class, 584193326Sed const ObjCMethodDecl *Method) { 585207619Srdivacky // Strip out message sends to retain / release in GC mode 586203955Srdivacky if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { 587203955Srdivacky if (Sel == RetainSel || Sel == AutoreleaseSel) { 588203955Srdivacky return RValue::get(Receiver); 589203955Srdivacky } 590203955Srdivacky if (Sel == ReleaseSel) { 591203955Srdivacky return RValue::get(0); 592203955Srdivacky } 593203955Srdivacky } 594207619Srdivacky 595198092Srdivacky CGBuilderTy &Builder = CGF.Builder; 596207619Srdivacky 597207619Srdivacky // If the return type is something that goes in an integer register, the 598207619Srdivacky // runtime will handle 0 returns. For other cases, we fill in the 0 value 599207619Srdivacky // ourselves. 600207619Srdivacky // 601207619Srdivacky // The language spec says the result of this kind of message send is 602207619Srdivacky // undefined, but lots of people seem to have forgotten to read that 603207619Srdivacky // paragraph and insist on sending messages to nil that have structure 604207619Srdivacky // returns. With GCC, this generates a random return value (whatever happens 605207619Srdivacky // to be on the stack / in those registers at the time) on most platforms, 606207619Srdivacky // and generates a SegV on SPARC. With LLVM it corrupts the stack. 607207619Srdivacky bool isPointerSizedReturn = false; 608207619Srdivacky if (ResultType->isAnyPointerType() || ResultType->isIntegralType() || 609207619Srdivacky ResultType->isVoidType()) 610207619Srdivacky isPointerSizedReturn = true; 611207619Srdivacky 612207619Srdivacky llvm::BasicBlock *startBB = 0; 613207619Srdivacky llvm::BasicBlock *messageBB = 0; 614207619Srdivacky llvm::BasicBlock *contiueBB = 0; 615207619Srdivacky 616207619Srdivacky if (!isPointerSizedReturn) { 617207619Srdivacky startBB = Builder.GetInsertBlock(); 618207619Srdivacky messageBB = CGF.createBasicBlock("msgSend"); 619207619Srdivacky contiueBB = CGF.createBasicBlock("continue"); 620207619Srdivacky 621207619Srdivacky llvm::Value *isNil = Builder.CreateICmpEQ(Receiver, 622207619Srdivacky llvm::Constant::getNullValue(Receiver->getType())); 623207619Srdivacky Builder.CreateCondBr(isNil, contiueBB, messageBB); 624207619Srdivacky CGF.EmitBlock(messageBB); 625207619Srdivacky } 626207619Srdivacky 627198092Srdivacky IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy)); 628193326Sed llvm::Value *cmd; 629193326Sed if (Method) 630198092Srdivacky cmd = GetSelector(Builder, Method); 631193326Sed else 632198092Srdivacky cmd = GetSelector(Builder, Sel); 633193326Sed CallArgList ActualArgs; 634193326Sed 635198092Srdivacky Receiver = Builder.CreateBitCast(Receiver, IdTy); 636193326Sed ActualArgs.push_back( 637198092Srdivacky std::make_pair(RValue::get(Receiver), ASTIdTy)); 638193326Sed ActualArgs.push_back(std::make_pair(RValue::get(cmd), 639193326Sed CGF.getContext().getObjCSelType())); 640193326Sed ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); 641193326Sed 642193326Sed CodeGenTypes &Types = CGM.getTypes(); 643203955Srdivacky const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs, 644206084Srdivacky FunctionType::ExtInfo()); 645198092Srdivacky const llvm::FunctionType *impType = 646198092Srdivacky Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); 647193326Sed 648207619Srdivacky llvm::Value *impMD[] = { 649207619Srdivacky llvm::MDString::get(VMContext, Sel.getAsString()), 650207619Srdivacky llvm::MDString::get(VMContext, Class ? Class->getNameAsString() :""), 651207619Srdivacky llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), Class!=0) 652207619Srdivacky }; 653207619Srdivacky llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD, 3); 654207619Srdivacky 655207619Srdivacky 656193326Sed llvm::Value *imp; 657193326Sed // For sender-aware dispatch, we pass the sender as the third argument to a 658193326Sed // lookup function. When sending messages from C code, the sender is nil. 659198092Srdivacky // objc_msg_lookup_sender(id *receiver, SEL selector, id sender); 660198092Srdivacky if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { 661198092Srdivacky 662198092Srdivacky std::vector<const llvm::Type*> Params; 663198092Srdivacky llvm::Value *ReceiverPtr = CGF.CreateTempAlloca(Receiver->getType()); 664198092Srdivacky Builder.CreateStore(Receiver, ReceiverPtr); 665198092Srdivacky Params.push_back(ReceiverPtr->getType()); 666198092Srdivacky Params.push_back(SelectorTy); 667193326Sed llvm::Value *self; 668193326Sed 669193326Sed if (isa<ObjCMethodDecl>(CGF.CurFuncDecl)) { 670193326Sed self = CGF.LoadObjCSelf(); 671193326Sed } else { 672193326Sed self = llvm::ConstantPointerNull::get(IdTy); 673193326Sed } 674198092Srdivacky 675193326Sed Params.push_back(self->getType()); 676198092Srdivacky 677198092Srdivacky // The lookup function returns a slot, which can be safely cached. 678198092Srdivacky llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy, 679198092Srdivacky IntTy, llvm::PointerType::getUnqual(impType), NULL); 680198092Srdivacky llvm::Constant *lookupFunction = 681193326Sed CGM.CreateRuntimeFunction(llvm::FunctionType::get( 682198092Srdivacky llvm::PointerType::getUnqual(SlotTy), Params, true), 683193326Sed "objc_msg_lookup_sender"); 684193326Sed 685198092Srdivacky // The lookup function is guaranteed not to capture the receiver pointer. 686198092Srdivacky if (llvm::Function *LookupFn = dyn_cast<llvm::Function>(lookupFunction)) { 687198092Srdivacky LookupFn->setDoesNotCapture(1); 688198092Srdivacky } 689198092Srdivacky 690207619Srdivacky llvm::CallInst *slot = 691198092Srdivacky Builder.CreateCall3(lookupFunction, ReceiverPtr, cmd, self); 692207619Srdivacky slot->setOnlyReadsMemory(); 693207619Srdivacky slot->setMetadata(msgSendMDKind, node); 694207619Srdivacky 695198092Srdivacky imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4)); 696207619Srdivacky 697198092Srdivacky // The lookup function may have changed the receiver, so make sure we use 698198092Srdivacky // the new one. 699198092Srdivacky ActualArgs[0] = 700198092Srdivacky std::make_pair(RValue::get(Builder.CreateLoad(ReceiverPtr)), ASTIdTy); 701193326Sed } else { 702198092Srdivacky std::vector<const llvm::Type*> Params; 703198092Srdivacky Params.push_back(Receiver->getType()); 704198092Srdivacky Params.push_back(SelectorTy); 705198092Srdivacky llvm::Constant *lookupFunction = 706193326Sed CGM.CreateRuntimeFunction(llvm::FunctionType::get( 707193326Sed llvm::PointerType::getUnqual(impType), Params, true), 708193326Sed "objc_msg_lookup"); 709193326Sed 710198092Srdivacky imp = Builder.CreateCall2(lookupFunction, Receiver, cmd); 711207619Srdivacky cast<llvm::CallInst>(imp)->setMetadata(msgSendMDKind, node); 712193326Sed } 713207619Srdivacky llvm::Instruction *call; 714207619Srdivacky RValue msgRet = CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs, 715207619Srdivacky 0, &call); 716207619Srdivacky call->setMetadata(msgSendMDKind, node); 717193326Sed 718207619Srdivacky if (!isPointerSizedReturn) { 719207619Srdivacky CGF.EmitBlock(contiueBB); 720207619Srdivacky if (msgRet.isScalar()) { 721207619Srdivacky llvm::Value *v = msgRet.getScalarVal(); 722207619Srdivacky llvm::PHINode *phi = Builder.CreatePHI(v->getType()); 723207619Srdivacky phi->addIncoming(v, messageBB); 724207619Srdivacky phi->addIncoming(llvm::Constant::getNullValue(v->getType()), startBB); 725207619Srdivacky msgRet = RValue::get(phi); 726207619Srdivacky } else if (msgRet.isAggregate()) { 727207619Srdivacky llvm::Value *v = msgRet.getAggregateAddr(); 728207619Srdivacky llvm::PHINode *phi = Builder.CreatePHI(v->getType()); 729207619Srdivacky const llvm::PointerType *RetTy = cast<llvm::PointerType>(v->getType()); 730207619Srdivacky llvm::AllocaInst *NullVal = 731207619Srdivacky CGF.CreateTempAlloca(RetTy->getElementType(), "null"); 732207619Srdivacky CGF.InitTempAlloca(NullVal, 733207619Srdivacky llvm::Constant::getNullValue(RetTy->getElementType())); 734207619Srdivacky phi->addIncoming(v, messageBB); 735207619Srdivacky phi->addIncoming(NullVal, startBB); 736207619Srdivacky msgRet = RValue::getAggregate(phi); 737207619Srdivacky } else /* isComplex() */ { 738207619Srdivacky std::pair<llvm::Value*,llvm::Value*> v = msgRet.getComplexVal(); 739207619Srdivacky llvm::PHINode *phi = Builder.CreatePHI(v.first->getType()); 740207619Srdivacky phi->addIncoming(v.first, messageBB); 741207619Srdivacky phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()), 742207619Srdivacky startBB); 743207619Srdivacky llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType()); 744207619Srdivacky phi2->addIncoming(v.second, messageBB); 745207619Srdivacky phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()), 746207619Srdivacky startBB); 747207619Srdivacky msgRet = RValue::getComplex(phi, phi2); 748207619Srdivacky } 749207619Srdivacky } 750207619Srdivacky return msgRet; 751193326Sed} 752193326Sed 753198092Srdivacky/// Generates a MethodList. Used in construction of a objc_class and 754193326Sed/// objc_category structures. 755193326Sedllvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName, 756198092Srdivacky const std::string &CategoryName, 757198092Srdivacky const llvm::SmallVectorImpl<Selector> &MethodSels, 758198092Srdivacky const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes, 759193326Sed bool isClassMethodList) { 760198092Srdivacky if (MethodSels.empty()) 761198092Srdivacky return NULLPtr; 762198092Srdivacky // Get the method structure type. 763198092Srdivacky llvm::StructType *ObjCMethodTy = llvm::StructType::get(VMContext, 764193326Sed PtrToInt8Ty, // Really a selector, but the runtime creates it us. 765193326Sed PtrToInt8Ty, // Method types 766193326Sed llvm::PointerType::getUnqual(IMPTy), //Method pointer 767193326Sed NULL); 768193326Sed std::vector<llvm::Constant*> Methods; 769193326Sed std::vector<llvm::Constant*> Elements; 770193326Sed for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) { 771193326Sed Elements.clear(); 772193326Sed if (llvm::Constant *Method = 773193326Sed TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName, 774193326Sed MethodSels[i].getAsString(), 775193326Sed isClassMethodList))) { 776198092Srdivacky llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString()); 777198092Srdivacky Elements.push_back(C); 778198092Srdivacky Elements.push_back(MethodTypes[i]); 779193326Sed Method = llvm::ConstantExpr::getBitCast(Method, 780193326Sed llvm::PointerType::getUnqual(IMPTy)); 781193326Sed Elements.push_back(Method); 782193326Sed Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements)); 783193326Sed } 784193326Sed } 785193326Sed 786193326Sed // Array of method structures 787193326Sed llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy, 788193326Sed Methods.size()); 789193326Sed llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy, 790193326Sed Methods); 791193326Sed 792193326Sed // Structure containing list pointer, array and array count 793193326Sed llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields; 794198092Srdivacky llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get(VMContext); 795193326Sed llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy); 796198092Srdivacky llvm::StructType *ObjCMethodListTy = llvm::StructType::get(VMContext, 797198092Srdivacky NextPtrTy, 798198092Srdivacky IntTy, 799193326Sed ObjCMethodArrayTy, 800193326Sed NULL); 801193326Sed // Refine next pointer type to concrete type 802193326Sed llvm::cast<llvm::OpaqueType>( 803193326Sed OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy); 804193326Sed ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get()); 805193326Sed 806193326Sed Methods.clear(); 807193326Sed Methods.push_back(llvm::ConstantPointerNull::get( 808193326Sed llvm::PointerType::getUnqual(ObjCMethodListTy))); 809198092Srdivacky Methods.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 810193326Sed MethodTypes.size())); 811193326Sed Methods.push_back(MethodArray); 812198092Srdivacky 813193326Sed // Create an instance of the structure 814193326Sed return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list"); 815193326Sed} 816193326Sed 817193326Sed/// Generates an IvarList. Used in construction of a objc_class. 818193326Sedllvm::Constant *CGObjCGNU::GenerateIvarList( 819193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, 820193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes, 821193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) { 822199482Srdivacky if (IvarNames.size() == 0) 823199482Srdivacky return NULLPtr; 824198092Srdivacky // Get the method structure type. 825198092Srdivacky llvm::StructType *ObjCIvarTy = llvm::StructType::get(VMContext, 826193326Sed PtrToInt8Ty, 827193326Sed PtrToInt8Ty, 828193326Sed IntTy, 829193326Sed NULL); 830193326Sed std::vector<llvm::Constant*> Ivars; 831193326Sed std::vector<llvm::Constant*> Elements; 832193326Sed for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) { 833193326Sed Elements.clear(); 834198092Srdivacky Elements.push_back(IvarNames[i]); 835198092Srdivacky Elements.push_back(IvarTypes[i]); 836193326Sed Elements.push_back(IvarOffsets[i]); 837193326Sed Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements)); 838193326Sed } 839193326Sed 840193326Sed // Array of method structures 841193326Sed llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy, 842193326Sed IvarNames.size()); 843193326Sed 844198092Srdivacky 845193326Sed Elements.clear(); 846193326Sed Elements.push_back(llvm::ConstantInt::get(IntTy, (int)IvarNames.size())); 847193326Sed Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars)); 848193326Sed // Structure containing array and array count 849198092Srdivacky llvm::StructType *ObjCIvarListTy = llvm::StructType::get(VMContext, IntTy, 850193326Sed ObjCIvarArrayTy, 851193326Sed NULL); 852193326Sed 853193326Sed // Create an instance of the structure 854193326Sed return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list"); 855193326Sed} 856193326Sed 857193326Sed/// Generate a class structure 858193326Sedllvm::Constant *CGObjCGNU::GenerateClassStructure( 859193326Sed llvm::Constant *MetaClass, 860193326Sed llvm::Constant *SuperClass, 861193326Sed unsigned info, 862193326Sed const char *Name, 863193326Sed llvm::Constant *Version, 864193326Sed llvm::Constant *InstanceSize, 865193326Sed llvm::Constant *IVars, 866193326Sed llvm::Constant *Methods, 867198092Srdivacky llvm::Constant *Protocols, 868198092Srdivacky llvm::Constant *IvarOffsets, 869207619Srdivacky llvm::Constant *Properties, 870207619Srdivacky bool isMeta) { 871193326Sed // Set up the class structure 872193326Sed // Note: Several of these are char*s when they should be ids. This is 873193326Sed // because the runtime performs this translation on load. 874198092Srdivacky // 875198092Srdivacky // Fields marked New ABI are part of the GNUstep runtime. We emit them 876198092Srdivacky // anyway; the classes will still work with the GNU runtime, they will just 877198092Srdivacky // be ignored. 878198092Srdivacky llvm::StructType *ClassTy = llvm::StructType::get(VMContext, 879193326Sed PtrToInt8Ty, // class_pointer 880193326Sed PtrToInt8Ty, // super_class 881193326Sed PtrToInt8Ty, // name 882193326Sed LongTy, // version 883193326Sed LongTy, // info 884193326Sed LongTy, // instance_size 885193326Sed IVars->getType(), // ivars 886193326Sed Methods->getType(), // methods 887198092Srdivacky // These are all filled in by the runtime, so we pretend 888193326Sed PtrTy, // dtable 889193326Sed PtrTy, // subclass_list 890193326Sed PtrTy, // sibling_class 891193326Sed PtrTy, // protocols 892193326Sed PtrTy, // gc_object_type 893198092Srdivacky // New ABI: 894198092Srdivacky LongTy, // abi_version 895198092Srdivacky IvarOffsets->getType(), // ivar_offsets 896198092Srdivacky Properties->getType(), // properties 897193326Sed NULL); 898193326Sed llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0); 899193326Sed // Fill in the structure 900193326Sed std::vector<llvm::Constant*> Elements; 901193326Sed Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty)); 902193326Sed Elements.push_back(SuperClass); 903193326Sed Elements.push_back(MakeConstantString(Name, ".class_name")); 904193326Sed Elements.push_back(Zero); 905193326Sed Elements.push_back(llvm::ConstantInt::get(LongTy, info)); 906193326Sed Elements.push_back(InstanceSize); 907193326Sed Elements.push_back(IVars); 908193326Sed Elements.push_back(Methods); 909198092Srdivacky Elements.push_back(NULLPtr); 910198092Srdivacky Elements.push_back(NULLPtr); 911198092Srdivacky Elements.push_back(NULLPtr); 912193326Sed Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy)); 913198092Srdivacky Elements.push_back(NULLPtr); 914198092Srdivacky Elements.push_back(Zero); 915198092Srdivacky Elements.push_back(IvarOffsets); 916198092Srdivacky Elements.push_back(Properties); 917193326Sed // Create an instance of the structure 918202379Srdivacky // This is now an externally visible symbol, so that we can speed up class 919202379Srdivacky // messages in the next ABI. 920207619Srdivacky return MakeGlobal(ClassTy, Elements, (isMeta ? "_OBJC_METACLASS_": 921207619Srdivacky "_OBJC_CLASS_") + std::string(Name), llvm::GlobalValue::ExternalLinkage); 922193326Sed} 923193326Sed 924193326Sedllvm::Constant *CGObjCGNU::GenerateProtocolMethodList( 925193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames, 926193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) { 927198092Srdivacky // Get the method structure type. 928198092Srdivacky llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(VMContext, 929193326Sed PtrToInt8Ty, // Really a selector, but the runtime does the casting for us. 930193326Sed PtrToInt8Ty, 931193326Sed NULL); 932193326Sed std::vector<llvm::Constant*> Methods; 933193326Sed std::vector<llvm::Constant*> Elements; 934193326Sed for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) { 935193326Sed Elements.clear(); 936198092Srdivacky Elements.push_back(MethodNames[i]); 937198092Srdivacky Elements.push_back(MethodTypes[i]); 938193326Sed Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements)); 939193326Sed } 940193326Sed llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy, 941193326Sed MethodNames.size()); 942198092Srdivacky llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy, 943198092Srdivacky Methods); 944198092Srdivacky llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(VMContext, 945193326Sed IntTy, ObjCMethodArrayTy, NULL); 946193326Sed Methods.clear(); 947193326Sed Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size())); 948193326Sed Methods.push_back(Array); 949193326Sed return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list"); 950193326Sed} 951198092Srdivacky 952193326Sed// Create the protocol list structure used in classes, categories and so on 953193326Sedllvm::Constant *CGObjCGNU::GenerateProtocolList( 954193326Sed const llvm::SmallVectorImpl<std::string> &Protocols) { 955193326Sed llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty, 956193326Sed Protocols.size()); 957198092Srdivacky llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext, 958193326Sed PtrTy, //Should be a recurisve pointer, but it's always NULL here. 959193326Sed LongTy,//FIXME: Should be size_t 960193326Sed ProtocolArrayTy, 961193326Sed NULL); 962198092Srdivacky std::vector<llvm::Constant*> Elements; 963193326Sed for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end(); 964193326Sed iter != endIter ; iter++) { 965199990Srdivacky llvm::Constant *protocol = 0; 966199990Srdivacky llvm::StringMap<llvm::Constant*>::iterator value = 967199990Srdivacky ExistingProtocols.find(*iter); 968199990Srdivacky if (value == ExistingProtocols.end()) { 969193326Sed protocol = GenerateEmptyProtocol(*iter); 970199990Srdivacky } else { 971199990Srdivacky protocol = value->getValue(); 972199990Srdivacky } 973198092Srdivacky llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(protocol, 974198092Srdivacky PtrToInt8Ty); 975193326Sed Elements.push_back(Ptr); 976193326Sed } 977193326Sed llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy, 978193326Sed Elements); 979193326Sed Elements.clear(); 980193326Sed Elements.push_back(NULLPtr); 981193326Sed Elements.push_back(llvm::ConstantInt::get(LongTy, Protocols.size())); 982193326Sed Elements.push_back(ProtocolArray); 983193326Sed return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list"); 984193326Sed} 985193326Sed 986198092Srdivackyllvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder, 987193326Sed const ObjCProtocolDecl *PD) { 988193326Sed llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()]; 989198092Srdivacky const llvm::Type *T = 990193326Sed CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType()); 991193326Sed return Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T)); 992193326Sed} 993193326Sed 994193326Sedllvm::Constant *CGObjCGNU::GenerateEmptyProtocol( 995193326Sed const std::string &ProtocolName) { 996193326Sed llvm::SmallVector<std::string, 0> EmptyStringVector; 997193326Sed llvm::SmallVector<llvm::Constant*, 0> EmptyConstantVector; 998193326Sed 999193326Sed llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector); 1000198092Srdivacky llvm::Constant *MethodList = 1001193326Sed GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector); 1002193326Sed // Protocols are objects containing lists of the methods implemented and 1003193326Sed // protocols adopted. 1004198092Srdivacky llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy, 1005193326Sed PtrToInt8Ty, 1006193326Sed ProtocolList->getType(), 1007198092Srdivacky MethodList->getType(), 1008198092Srdivacky MethodList->getType(), 1009198092Srdivacky MethodList->getType(), 1010198092Srdivacky MethodList->getType(), 1011193326Sed NULL); 1012198092Srdivacky std::vector<llvm::Constant*> Elements; 1013193326Sed // The isa pointer must be set to a magic number so the runtime knows it's 1014193326Sed // the correct layout. 1015198092Srdivacky int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ? 1016198092Srdivacky NonFragileProtocolVersion : ProtocolVersion; 1017193326Sed Elements.push_back(llvm::ConstantExpr::getIntToPtr( 1018198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy)); 1019193326Sed Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name")); 1020193326Sed Elements.push_back(ProtocolList); 1021198092Srdivacky Elements.push_back(MethodList); 1022198092Srdivacky Elements.push_back(MethodList); 1023198092Srdivacky Elements.push_back(MethodList); 1024198092Srdivacky Elements.push_back(MethodList); 1025193326Sed return MakeGlobal(ProtocolTy, Elements, ".objc_protocol"); 1026193326Sed} 1027193326Sed 1028193326Sedvoid CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { 1029193326Sed ASTContext &Context = CGM.getContext(); 1030193326Sed std::string ProtocolName = PD->getNameAsString(); 1031193326Sed llvm::SmallVector<std::string, 16> Protocols; 1032193326Sed for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(), 1033193326Sed E = PD->protocol_end(); PI != E; ++PI) 1034193326Sed Protocols.push_back((*PI)->getNameAsString()); 1035193326Sed llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames; 1036193326Sed llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; 1037198092Srdivacky llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodNames; 1038198092Srdivacky llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodTypes; 1039195341Sed for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(), 1040195341Sed E = PD->instmeth_end(); iter != E; iter++) { 1041193326Sed std::string TypeStr; 1042193326Sed Context.getObjCEncodingForMethodDecl(*iter, TypeStr); 1043198092Srdivacky if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) { 1044198092Srdivacky InstanceMethodNames.push_back( 1045198092Srdivacky MakeConstantString((*iter)->getSelector().getAsString())); 1046198092Srdivacky InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); 1047198092Srdivacky } else { 1048198092Srdivacky OptionalInstanceMethodNames.push_back( 1049198092Srdivacky MakeConstantString((*iter)->getSelector().getAsString())); 1050198092Srdivacky OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr)); 1051198092Srdivacky } 1052193326Sed } 1053193326Sed // Collect information about class methods: 1054193326Sed llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames; 1055193326Sed llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; 1056198092Srdivacky llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodNames; 1057198092Srdivacky llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodTypes; 1058198092Srdivacky for (ObjCProtocolDecl::classmeth_iterator 1059195341Sed iter = PD->classmeth_begin(), endIter = PD->classmeth_end(); 1060195341Sed iter != endIter ; iter++) { 1061193326Sed std::string TypeStr; 1062193326Sed Context.getObjCEncodingForMethodDecl((*iter),TypeStr); 1063198092Srdivacky if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) { 1064198092Srdivacky ClassMethodNames.push_back( 1065198092Srdivacky MakeConstantString((*iter)->getSelector().getAsString())); 1066198092Srdivacky ClassMethodTypes.push_back(MakeConstantString(TypeStr)); 1067198092Srdivacky } else { 1068198092Srdivacky OptionalClassMethodNames.push_back( 1069198092Srdivacky MakeConstantString((*iter)->getSelector().getAsString())); 1070198092Srdivacky OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr)); 1071198092Srdivacky } 1072193326Sed } 1073193326Sed 1074193326Sed llvm::Constant *ProtocolList = GenerateProtocolList(Protocols); 1075193326Sed llvm::Constant *InstanceMethodList = 1076193326Sed GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes); 1077193326Sed llvm::Constant *ClassMethodList = 1078193326Sed GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes); 1079198092Srdivacky llvm::Constant *OptionalInstanceMethodList = 1080198092Srdivacky GenerateProtocolMethodList(OptionalInstanceMethodNames, 1081198092Srdivacky OptionalInstanceMethodTypes); 1082198092Srdivacky llvm::Constant *OptionalClassMethodList = 1083198092Srdivacky GenerateProtocolMethodList(OptionalClassMethodNames, 1084198092Srdivacky OptionalClassMethodTypes); 1085198092Srdivacky 1086198092Srdivacky // Property metadata: name, attributes, isSynthesized, setter name, setter 1087198092Srdivacky // types, getter name, getter types. 1088198092Srdivacky // The isSynthesized value is always set to 0 in a protocol. It exists to 1089198092Srdivacky // simplify the runtime library by allowing it to use the same data 1090198092Srdivacky // structures for protocol metadata everywhere. 1091198092Srdivacky llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext, 1092198092Srdivacky PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, 1093198092Srdivacky PtrToInt8Ty, NULL); 1094198092Srdivacky std::vector<llvm::Constant*> Properties; 1095198092Srdivacky std::vector<llvm::Constant*> OptionalProperties; 1096198092Srdivacky 1097198092Srdivacky // Add all of the property methods need adding to the method list and to the 1098198092Srdivacky // property metadata list. 1099198092Srdivacky for (ObjCContainerDecl::prop_iterator 1100198092Srdivacky iter = PD->prop_begin(), endIter = PD->prop_end(); 1101198092Srdivacky iter != endIter ; iter++) { 1102198092Srdivacky std::vector<llvm::Constant*> Fields; 1103198092Srdivacky ObjCPropertyDecl *property = (*iter); 1104198092Srdivacky 1105198092Srdivacky Fields.push_back(MakeConstantString(property->getNameAsString())); 1106198092Srdivacky Fields.push_back(llvm::ConstantInt::get(Int8Ty, 1107198092Srdivacky property->getPropertyAttributes())); 1108198092Srdivacky Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0)); 1109198092Srdivacky if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) { 1110198092Srdivacky std::string TypeStr; 1111198092Srdivacky Context.getObjCEncodingForMethodDecl(getter,TypeStr); 1112198092Srdivacky llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); 1113198092Srdivacky InstanceMethodTypes.push_back(TypeEncoding); 1114198092Srdivacky Fields.push_back(MakeConstantString(getter->getSelector().getAsString())); 1115198092Srdivacky Fields.push_back(TypeEncoding); 1116198092Srdivacky } else { 1117198092Srdivacky Fields.push_back(NULLPtr); 1118198092Srdivacky Fields.push_back(NULLPtr); 1119198092Srdivacky } 1120198092Srdivacky if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) { 1121198092Srdivacky std::string TypeStr; 1122198092Srdivacky Context.getObjCEncodingForMethodDecl(setter,TypeStr); 1123198092Srdivacky llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); 1124198092Srdivacky InstanceMethodTypes.push_back(TypeEncoding); 1125198092Srdivacky Fields.push_back(MakeConstantString(setter->getSelector().getAsString())); 1126198092Srdivacky Fields.push_back(TypeEncoding); 1127198092Srdivacky } else { 1128198092Srdivacky Fields.push_back(NULLPtr); 1129198092Srdivacky Fields.push_back(NULLPtr); 1130198092Srdivacky } 1131198092Srdivacky if (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) { 1132198092Srdivacky OptionalProperties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields)); 1133198092Srdivacky } else { 1134198092Srdivacky Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields)); 1135198092Srdivacky } 1136198092Srdivacky } 1137198092Srdivacky llvm::Constant *PropertyArray = llvm::ConstantArray::get( 1138198092Srdivacky llvm::ArrayType::get(PropertyMetadataTy, Properties.size()), Properties); 1139198092Srdivacky llvm::Constant* PropertyListInitFields[] = 1140198092Srdivacky {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray}; 1141198092Srdivacky 1142198092Srdivacky llvm::Constant *PropertyListInit = 1143198092Srdivacky llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false); 1144198092Srdivacky llvm::Constant *PropertyList = new llvm::GlobalVariable(TheModule, 1145198092Srdivacky PropertyListInit->getType(), false, llvm::GlobalValue::InternalLinkage, 1146198092Srdivacky PropertyListInit, ".objc_property_list"); 1147198092Srdivacky 1148198092Srdivacky llvm::Constant *OptionalPropertyArray = 1149198092Srdivacky llvm::ConstantArray::get(llvm::ArrayType::get(PropertyMetadataTy, 1150198092Srdivacky OptionalProperties.size()) , OptionalProperties); 1151198092Srdivacky llvm::Constant* OptionalPropertyListInitFields[] = { 1152198092Srdivacky llvm::ConstantInt::get(IntTy, OptionalProperties.size()), NULLPtr, 1153198092Srdivacky OptionalPropertyArray }; 1154198092Srdivacky 1155198092Srdivacky llvm::Constant *OptionalPropertyListInit = 1156198092Srdivacky llvm::ConstantStruct::get(VMContext, OptionalPropertyListInitFields, 3, false); 1157198092Srdivacky llvm::Constant *OptionalPropertyList = new llvm::GlobalVariable(TheModule, 1158198092Srdivacky OptionalPropertyListInit->getType(), false, 1159198092Srdivacky llvm::GlobalValue::InternalLinkage, OptionalPropertyListInit, 1160198092Srdivacky ".objc_property_list"); 1161198092Srdivacky 1162193326Sed // Protocols are objects containing lists of the methods implemented and 1163193326Sed // protocols adopted. 1164198092Srdivacky llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy, 1165193326Sed PtrToInt8Ty, 1166193326Sed ProtocolList->getType(), 1167193326Sed InstanceMethodList->getType(), 1168193326Sed ClassMethodList->getType(), 1169198092Srdivacky OptionalInstanceMethodList->getType(), 1170198092Srdivacky OptionalClassMethodList->getType(), 1171198092Srdivacky PropertyList->getType(), 1172198092Srdivacky OptionalPropertyList->getType(), 1173193326Sed NULL); 1174198092Srdivacky std::vector<llvm::Constant*> Elements; 1175193326Sed // The isa pointer must be set to a magic number so the runtime knows it's 1176193326Sed // the correct layout. 1177198092Srdivacky int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ? 1178198092Srdivacky NonFragileProtocolVersion : ProtocolVersion; 1179193326Sed Elements.push_back(llvm::ConstantExpr::getIntToPtr( 1180198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy)); 1181193326Sed Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name")); 1182193326Sed Elements.push_back(ProtocolList); 1183193326Sed Elements.push_back(InstanceMethodList); 1184193326Sed Elements.push_back(ClassMethodList); 1185198092Srdivacky Elements.push_back(OptionalInstanceMethodList); 1186198092Srdivacky Elements.push_back(OptionalClassMethodList); 1187198092Srdivacky Elements.push_back(PropertyList); 1188198092Srdivacky Elements.push_back(OptionalPropertyList); 1189198092Srdivacky ExistingProtocols[ProtocolName] = 1190193326Sed llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements, 1191193326Sed ".objc_protocol"), IdTy); 1192193326Sed} 1193198092Srdivackyvoid CGObjCGNU::GenerateProtocolHolderCategory(void) { 1194198092Srdivacky // Collect information about instance methods 1195198092Srdivacky llvm::SmallVector<Selector, 1> MethodSels; 1196198092Srdivacky llvm::SmallVector<llvm::Constant*, 1> MethodTypes; 1197193326Sed 1198198092Srdivacky std::vector<llvm::Constant*> Elements; 1199198092Srdivacky const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack"; 1200198092Srdivacky const std::string CategoryName = "AnotherHack"; 1201198092Srdivacky Elements.push_back(MakeConstantString(CategoryName)); 1202198092Srdivacky Elements.push_back(MakeConstantString(ClassName)); 1203198092Srdivacky // Instance method list 1204198092Srdivacky Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( 1205198092Srdivacky ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy)); 1206198092Srdivacky // Class method list 1207198092Srdivacky Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( 1208198092Srdivacky ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy)); 1209198092Srdivacky // Protocol list 1210198092Srdivacky llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrTy, 1211198092Srdivacky ExistingProtocols.size()); 1212198092Srdivacky llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext, 1213198092Srdivacky PtrTy, //Should be a recurisve pointer, but it's always NULL here. 1214198092Srdivacky LongTy,//FIXME: Should be size_t 1215198092Srdivacky ProtocolArrayTy, 1216198092Srdivacky NULL); 1217198092Srdivacky std::vector<llvm::Constant*> ProtocolElements; 1218198092Srdivacky for (llvm::StringMapIterator<llvm::Constant*> iter = 1219198092Srdivacky ExistingProtocols.begin(), endIter = ExistingProtocols.end(); 1220198092Srdivacky iter != endIter ; iter++) { 1221198092Srdivacky llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(iter->getValue(), 1222198092Srdivacky PtrTy); 1223198092Srdivacky ProtocolElements.push_back(Ptr); 1224198092Srdivacky } 1225198092Srdivacky llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy, 1226198092Srdivacky ProtocolElements); 1227198092Srdivacky ProtocolElements.clear(); 1228198092Srdivacky ProtocolElements.push_back(NULLPtr); 1229198092Srdivacky ProtocolElements.push_back(llvm::ConstantInt::get(LongTy, 1230198092Srdivacky ExistingProtocols.size())); 1231198092Srdivacky ProtocolElements.push_back(ProtocolArray); 1232198092Srdivacky Elements.push_back(llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolListTy, 1233198092Srdivacky ProtocolElements, ".objc_protocol_list"), PtrTy)); 1234198092Srdivacky Categories.push_back(llvm::ConstantExpr::getBitCast( 1235198092Srdivacky MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, 1236198092Srdivacky PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy)); 1237198092Srdivacky} 1238198092Srdivacky 1239193326Sedvoid CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 1240193326Sed std::string ClassName = OCD->getClassInterface()->getNameAsString(); 1241193326Sed std::string CategoryName = OCD->getNameAsString(); 1242193326Sed // Collect information about instance methods 1243193326Sed llvm::SmallVector<Selector, 16> InstanceMethodSels; 1244193326Sed llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; 1245193326Sed for (ObjCCategoryImplDecl::instmeth_iterator 1246195341Sed iter = OCD->instmeth_begin(), endIter = OCD->instmeth_end(); 1247193326Sed iter != endIter ; iter++) { 1248193326Sed InstanceMethodSels.push_back((*iter)->getSelector()); 1249193326Sed std::string TypeStr; 1250193326Sed CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr); 1251198092Srdivacky InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); 1252193326Sed } 1253193326Sed 1254193326Sed // Collect information about class methods 1255193326Sed llvm::SmallVector<Selector, 16> ClassMethodSels; 1256193326Sed llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; 1257198092Srdivacky for (ObjCCategoryImplDecl::classmeth_iterator 1258195341Sed iter = OCD->classmeth_begin(), endIter = OCD->classmeth_end(); 1259193326Sed iter != endIter ; iter++) { 1260193326Sed ClassMethodSels.push_back((*iter)->getSelector()); 1261193326Sed std::string TypeStr; 1262193326Sed CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr); 1263198092Srdivacky ClassMethodTypes.push_back(MakeConstantString(TypeStr)); 1264193326Sed } 1265193326Sed 1266193326Sed // Collect the names of referenced protocols 1267193326Sed llvm::SmallVector<std::string, 16> Protocols; 1268205219Srdivacky const ObjCCategoryDecl *CatDecl = OCD->getCategoryDecl(); 1269205219Srdivacky const ObjCList<ObjCProtocolDecl> &Protos = CatDecl->getReferencedProtocols(); 1270193326Sed for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(), 1271193326Sed E = Protos.end(); I != E; ++I) 1272193326Sed Protocols.push_back((*I)->getNameAsString()); 1273193326Sed 1274193326Sed std::vector<llvm::Constant*> Elements; 1275193326Sed Elements.push_back(MakeConstantString(CategoryName)); 1276193326Sed Elements.push_back(MakeConstantString(ClassName)); 1277198092Srdivacky // Instance method list 1278193326Sed Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( 1279193326Sed ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes, 1280193326Sed false), PtrTy)); 1281193326Sed // Class method list 1282193326Sed Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( 1283193326Sed ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true), 1284193326Sed PtrTy)); 1285193326Sed // Protocol list 1286193326Sed Elements.push_back(llvm::ConstantExpr::getBitCast( 1287193326Sed GenerateProtocolList(Protocols), PtrTy)); 1288193326Sed Categories.push_back(llvm::ConstantExpr::getBitCast( 1289198092Srdivacky MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, 1290198092Srdivacky PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy)); 1291193326Sed} 1292193326Sed 1293198092Srdivackyllvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID, 1294198092Srdivacky llvm::SmallVectorImpl<Selector> &InstanceMethodSels, 1295198092Srdivacky llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes) { 1296198092Srdivacky ASTContext &Context = CGM.getContext(); 1297198092Srdivacky // 1298198092Srdivacky // Property metadata: name, attributes, isSynthesized, setter name, setter 1299198092Srdivacky // types, getter name, getter types. 1300198092Srdivacky llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext, 1301198092Srdivacky PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, 1302198092Srdivacky PtrToInt8Ty, NULL); 1303198092Srdivacky std::vector<llvm::Constant*> Properties; 1304198092Srdivacky 1305198092Srdivacky 1306198092Srdivacky // Add all of the property methods need adding to the method list and to the 1307198092Srdivacky // property metadata list. 1308198092Srdivacky for (ObjCImplDecl::propimpl_iterator 1309198092Srdivacky iter = OID->propimpl_begin(), endIter = OID->propimpl_end(); 1310198092Srdivacky iter != endIter ; iter++) { 1311198092Srdivacky std::vector<llvm::Constant*> Fields; 1312198092Srdivacky ObjCPropertyDecl *property = (*iter)->getPropertyDecl(); 1313204643Srdivacky ObjCPropertyImplDecl *propertyImpl = *iter; 1314204643Srdivacky bool isSynthesized = (propertyImpl->getPropertyImplementation() == 1315204643Srdivacky ObjCPropertyImplDecl::Synthesize); 1316198092Srdivacky 1317198092Srdivacky Fields.push_back(MakeConstantString(property->getNameAsString())); 1318198092Srdivacky Fields.push_back(llvm::ConstantInt::get(Int8Ty, 1319198092Srdivacky property->getPropertyAttributes())); 1320204643Srdivacky Fields.push_back(llvm::ConstantInt::get(Int8Ty, isSynthesized)); 1321198092Srdivacky if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) { 1322198092Srdivacky std::string TypeStr; 1323198092Srdivacky Context.getObjCEncodingForMethodDecl(getter,TypeStr); 1324198092Srdivacky llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); 1325204643Srdivacky if (isSynthesized) { 1326204643Srdivacky InstanceMethodTypes.push_back(TypeEncoding); 1327204643Srdivacky InstanceMethodSels.push_back(getter->getSelector()); 1328204643Srdivacky } 1329198092Srdivacky Fields.push_back(MakeConstantString(getter->getSelector().getAsString())); 1330198092Srdivacky Fields.push_back(TypeEncoding); 1331198092Srdivacky } else { 1332198092Srdivacky Fields.push_back(NULLPtr); 1333198092Srdivacky Fields.push_back(NULLPtr); 1334198092Srdivacky } 1335198092Srdivacky if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) { 1336198092Srdivacky std::string TypeStr; 1337198092Srdivacky Context.getObjCEncodingForMethodDecl(setter,TypeStr); 1338198092Srdivacky llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); 1339204643Srdivacky if (isSynthesized) { 1340204643Srdivacky InstanceMethodTypes.push_back(TypeEncoding); 1341204643Srdivacky InstanceMethodSels.push_back(setter->getSelector()); 1342204643Srdivacky } 1343198092Srdivacky Fields.push_back(MakeConstantString(setter->getSelector().getAsString())); 1344198092Srdivacky Fields.push_back(TypeEncoding); 1345198092Srdivacky } else { 1346198092Srdivacky Fields.push_back(NULLPtr); 1347198092Srdivacky Fields.push_back(NULLPtr); 1348198092Srdivacky } 1349198092Srdivacky Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields)); 1350198092Srdivacky } 1351198092Srdivacky llvm::ArrayType *PropertyArrayTy = 1352198092Srdivacky llvm::ArrayType::get(PropertyMetadataTy, Properties.size()); 1353198092Srdivacky llvm::Constant *PropertyArray = llvm::ConstantArray::get(PropertyArrayTy, 1354198092Srdivacky Properties); 1355198092Srdivacky llvm::Constant* PropertyListInitFields[] = 1356198092Srdivacky {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray}; 1357198092Srdivacky 1358198092Srdivacky llvm::Constant *PropertyListInit = 1359198092Srdivacky llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false); 1360198092Srdivacky return new llvm::GlobalVariable(TheModule, PropertyListInit->getType(), false, 1361198092Srdivacky llvm::GlobalValue::InternalLinkage, PropertyListInit, 1362198092Srdivacky ".objc_property_list"); 1363198092Srdivacky} 1364198092Srdivacky 1365193326Sedvoid CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { 1366193326Sed ASTContext &Context = CGM.getContext(); 1367193326Sed 1368193326Sed // Get the superclass name. 1369198092Srdivacky const ObjCInterfaceDecl * SuperClassDecl = 1370193326Sed OID->getClassInterface()->getSuperClass(); 1371193326Sed std::string SuperClassName; 1372194613Sed if (SuperClassDecl) { 1373193326Sed SuperClassName = SuperClassDecl->getNameAsString(); 1374194613Sed EmitClassRef(SuperClassName); 1375194613Sed } 1376193326Sed 1377193326Sed // Get the class name 1378193326Sed ObjCInterfaceDecl *ClassDecl = 1379193326Sed const_cast<ObjCInterfaceDecl *>(OID->getClassInterface()); 1380193326Sed std::string ClassName = ClassDecl->getNameAsString(); 1381194613Sed // Emit the symbol that is used to generate linker errors if this class is 1382194613Sed // referenced in other modules but not declared. 1383195341Sed std::string classSymbolName = "__objc_class_name_" + ClassName; 1384198092Srdivacky if (llvm::GlobalVariable *symbol = 1385195341Sed TheModule.getGlobalVariable(classSymbolName)) { 1386195341Sed symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0)); 1387195341Sed } else { 1388198092Srdivacky new llvm::GlobalVariable(TheModule, LongTy, false, 1389198092Srdivacky llvm::GlobalValue::ExternalLinkage, llvm::ConstantInt::get(LongTy, 0), 1390198092Srdivacky classSymbolName); 1391195341Sed } 1392198092Srdivacky 1393193326Sed // Get the size of instances. 1394193326Sed int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8; 1395193326Sed 1396193326Sed // Collect information about instance variables. 1397193326Sed llvm::SmallVector<llvm::Constant*, 16> IvarNames; 1398193326Sed llvm::SmallVector<llvm::Constant*, 16> IvarTypes; 1399193326Sed llvm::SmallVector<llvm::Constant*, 16> IvarOffsets; 1400198092Srdivacky 1401198092Srdivacky std::vector<llvm::Constant*> IvarOffsetValues; 1402198092Srdivacky 1403198092Srdivacky int superInstanceSize = !SuperClassDecl ? 0 : 1404193326Sed Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize() / 8; 1405193326Sed // For non-fragile ivars, set the instance size to 0 - {the size of just this 1406193326Sed // class}. The runtime will then set this to the correct value on load. 1407193326Sed if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { 1408193326Sed instanceSize = 0 - (instanceSize - superInstanceSize); 1409193326Sed } 1410207619Srdivacky 1411207619Srdivacky // Collect declared and synthesized ivars. 1412207619Srdivacky llvm::SmallVector<ObjCIvarDecl*, 16> OIvars; 1413207619Srdivacky CGM.getContext().ShallowCollectObjCIvars(ClassDecl, OIvars); 1414207619Srdivacky 1415207619Srdivacky for (unsigned i = 0, e = OIvars.size(); i != e; ++i) { 1416207619Srdivacky ObjCIvarDecl *IVD = OIvars[i]; 1417193326Sed // Store the name 1418207619Srdivacky IvarNames.push_back(MakeConstantString(IVD->getNameAsString())); 1419193326Sed // Get the type encoding for this ivar 1420193326Sed std::string TypeStr; 1421207619Srdivacky Context.getObjCEncodingForType(IVD->getType(), TypeStr); 1422198092Srdivacky IvarTypes.push_back(MakeConstantString(TypeStr)); 1423193326Sed // Get the offset 1424207619Srdivacky uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD); 1425199482Srdivacky uint64_t Offset = BaseOffset; 1426193326Sed if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { 1427198092Srdivacky Offset = BaseOffset - superInstanceSize; 1428193326Sed } 1429193326Sed IvarOffsets.push_back( 1430198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset)); 1431198092Srdivacky IvarOffsetValues.push_back(new llvm::GlobalVariable(TheModule, IntTy, 1432198092Srdivacky false, llvm::GlobalValue::ExternalLinkage, 1433198092Srdivacky llvm::ConstantInt::get(IntTy, BaseOffset), 1434198092Srdivacky "__objc_ivar_offset_value_" + ClassName +"." + 1435207619Srdivacky IVD->getNameAsString())); 1436193326Sed } 1437198092Srdivacky llvm::Constant *IvarOffsetArrayInit = 1438198092Srdivacky llvm::ConstantArray::get(llvm::ArrayType::get(PtrToIntTy, 1439198092Srdivacky IvarOffsetValues.size()), IvarOffsetValues); 1440198092Srdivacky llvm::GlobalVariable *IvarOffsetArray = new llvm::GlobalVariable(TheModule, 1441198092Srdivacky IvarOffsetArrayInit->getType(), false, 1442198092Srdivacky llvm::GlobalValue::InternalLinkage, IvarOffsetArrayInit, 1443198092Srdivacky ".ivar.offsets"); 1444193326Sed 1445193326Sed // Collect information about instance methods 1446193326Sed llvm::SmallVector<Selector, 16> InstanceMethodSels; 1447193326Sed llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; 1448198092Srdivacky for (ObjCImplementationDecl::instmeth_iterator 1449195341Sed iter = OID->instmeth_begin(), endIter = OID->instmeth_end(); 1450193326Sed iter != endIter ; iter++) { 1451193326Sed InstanceMethodSels.push_back((*iter)->getSelector()); 1452193326Sed std::string TypeStr; 1453193326Sed Context.getObjCEncodingForMethodDecl((*iter),TypeStr); 1454198092Srdivacky InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); 1455193326Sed } 1456193326Sed 1457198092Srdivacky llvm::Constant *Properties = GeneratePropertyList(OID, InstanceMethodSels, 1458198092Srdivacky InstanceMethodTypes); 1459198092Srdivacky 1460198092Srdivacky 1461193326Sed // Collect information about class methods 1462193326Sed llvm::SmallVector<Selector, 16> ClassMethodSels; 1463193326Sed llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; 1464193326Sed for (ObjCImplementationDecl::classmeth_iterator 1465195341Sed iter = OID->classmeth_begin(), endIter = OID->classmeth_end(); 1466193326Sed iter != endIter ; iter++) { 1467193326Sed ClassMethodSels.push_back((*iter)->getSelector()); 1468193326Sed std::string TypeStr; 1469193326Sed Context.getObjCEncodingForMethodDecl((*iter),TypeStr); 1470198092Srdivacky ClassMethodTypes.push_back(MakeConstantString(TypeStr)); 1471193326Sed } 1472193326Sed // Collect the names of referenced protocols 1473193326Sed llvm::SmallVector<std::string, 16> Protocols; 1474193326Sed const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols(); 1475193326Sed for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(), 1476193326Sed E = Protos.end(); I != E; ++I) 1477193326Sed Protocols.push_back((*I)->getNameAsString()); 1478193326Sed 1479193326Sed 1480193326Sed 1481193326Sed // Get the superclass pointer. 1482193326Sed llvm::Constant *SuperClass; 1483193326Sed if (!SuperClassName.empty()) { 1484193326Sed SuperClass = MakeConstantString(SuperClassName, ".super_class_name"); 1485193326Sed } else { 1486193326Sed SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty); 1487193326Sed } 1488193326Sed // Empty vector used to construct empty method lists 1489193326Sed llvm::SmallVector<llvm::Constant*, 1> empty; 1490193326Sed // Generate the method and instance variable lists 1491193326Sed llvm::Constant *MethodList = GenerateMethodList(ClassName, "", 1492193326Sed InstanceMethodSels, InstanceMethodTypes, false); 1493193326Sed llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "", 1494193326Sed ClassMethodSels, ClassMethodTypes, true); 1495193326Sed llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes, 1496193326Sed IvarOffsets); 1497198092Srdivacky // Irrespective of whether we are compiling for a fragile or non-fragile ABI, 1498198092Srdivacky // we emit a symbol containing the offset for each ivar in the class. This 1499198092Srdivacky // allows code compiled for the non-Fragile ABI to inherit from code compiled 1500198092Srdivacky // for the legacy ABI, without causing problems. The converse is also 1501198092Srdivacky // possible, but causes all ivar accesses to be fragile. 1502198092Srdivacky int i = 0; 1503198092Srdivacky // Offset pointer for getting at the correct field in the ivar list when 1504198092Srdivacky // setting up the alias. These are: The base address for the global, the 1505198092Srdivacky // ivar array (second field), the ivar in this list (set for each ivar), and 1506198092Srdivacky // the offset (third field in ivar structure) 1507198092Srdivacky const llvm::Type *IndexTy = llvm::Type::getInt32Ty(VMContext); 1508198092Srdivacky llvm::Constant *offsetPointerIndexes[] = {Zeros[0], 1509198092Srdivacky llvm::ConstantInt::get(IndexTy, 1), 0, 1510198092Srdivacky llvm::ConstantInt::get(IndexTy, 2) }; 1511198092Srdivacky 1512198092Srdivacky for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(), 1513198092Srdivacky endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) { 1514198092Srdivacky const std::string Name = "__objc_ivar_offset_" + ClassName + '.' 1515198092Srdivacky +(*iter)->getNameAsString(); 1516198092Srdivacky offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, i++); 1517198092Srdivacky // Get the correct ivar field 1518198092Srdivacky llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr( 1519198092Srdivacky IvarList, offsetPointerIndexes, 4); 1520198092Srdivacky // Get the existing alias, if one exists. 1521198092Srdivacky llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name); 1522198092Srdivacky if (offset) { 1523198092Srdivacky offset->setInitializer(offsetValue); 1524198092Srdivacky // If this is the real definition, change its linkage type so that 1525198092Srdivacky // different modules will use this one, rather than their private 1526198092Srdivacky // copy. 1527198092Srdivacky offset->setLinkage(llvm::GlobalValue::ExternalLinkage); 1528198092Srdivacky } else { 1529198092Srdivacky // Add a new alias if there isn't one already. 1530198092Srdivacky offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(), 1531198092Srdivacky false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name); 1532198092Srdivacky } 1533198092Srdivacky } 1534193326Sed //Generate metaclass for class methods 1535193326Sed llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr, 1536199482Srdivacky NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList( 1537207619Srdivacky empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr, NULLPtr, true); 1538193326Sed 1539193326Sed // Generate the class structure 1540193326Sed llvm::Constant *ClassStruct = 1541198092Srdivacky GenerateClassStructure(MetaClassStruct, SuperClass, 0x11L, 1542193326Sed ClassName.c_str(), 0, 1543193326Sed llvm::ConstantInt::get(LongTy, instanceSize), IvarList, 1544198092Srdivacky MethodList, GenerateProtocolList(Protocols), IvarOffsetArray, 1545198092Srdivacky Properties); 1546193326Sed 1547193326Sed // Resolve the class aliases, if they exist. 1548193326Sed if (ClassPtrAlias) { 1549193326Sed ClassPtrAlias->setAliasee( 1550193326Sed llvm::ConstantExpr::getBitCast(ClassStruct, IdTy)); 1551193326Sed ClassPtrAlias = 0; 1552193326Sed } 1553193326Sed if (MetaClassPtrAlias) { 1554193326Sed MetaClassPtrAlias->setAliasee( 1555193326Sed llvm::ConstantExpr::getBitCast(MetaClassStruct, IdTy)); 1556193326Sed MetaClassPtrAlias = 0; 1557193326Sed } 1558193326Sed 1559193326Sed // Add class structure to list to be added to the symtab later 1560193326Sed ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty); 1561193326Sed Classes.push_back(ClassStruct); 1562193326Sed} 1563193326Sed 1564195099Sed 1565198092Srdivackyllvm::Function *CGObjCGNU::ModuleInitFunction() { 1566193326Sed // Only emit an ObjC load function if no Objective-C stuff has been called 1567193326Sed if (Classes.empty() && Categories.empty() && ConstantStrings.empty() && 1568193326Sed ExistingProtocols.empty() && TypedSelectors.empty() && 1569193326Sed UntypedSelectors.empty()) 1570193326Sed return NULL; 1571193326Sed 1572198092Srdivacky // Add all referenced protocols to a category. 1573198092Srdivacky GenerateProtocolHolderCategory(); 1574198092Srdivacky 1575193326Sed const llvm::StructType *SelStructTy = dyn_cast<llvm::StructType>( 1576193326Sed SelectorTy->getElementType()); 1577193326Sed const llvm::Type *SelStructPtrTy = SelectorTy; 1578193326Sed bool isSelOpaque = false; 1579193326Sed if (SelStructTy == 0) { 1580198092Srdivacky SelStructTy = llvm::StructType::get(VMContext, PtrToInt8Ty, 1581198092Srdivacky PtrToInt8Ty, NULL); 1582193326Sed SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy); 1583193326Sed isSelOpaque = true; 1584193326Sed } 1585193326Sed 1586193326Sed // Name the ObjC types to make the IR a bit easier to read 1587193326Sed TheModule.addTypeName(".objc_selector", SelStructPtrTy); 1588193326Sed TheModule.addTypeName(".objc_id", IdTy); 1589193326Sed TheModule.addTypeName(".objc_imp", IMPTy); 1590193326Sed 1591193326Sed std::vector<llvm::Constant*> Elements; 1592193326Sed llvm::Constant *Statics = NULLPtr; 1593193326Sed // Generate statics list: 1594193326Sed if (ConstantStrings.size()) { 1595193326Sed llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty, 1596193326Sed ConstantStrings.size() + 1); 1597193326Sed ConstantStrings.push_back(NULLPtr); 1598198092Srdivacky 1599199990Srdivacky llvm::StringRef StringClass = CGM.getLangOptions().ObjCConstantStringClass; 1600199990Srdivacky if (StringClass.empty()) StringClass = "NXConstantString"; 1601198092Srdivacky Elements.push_back(MakeConstantString(StringClass, 1602198092Srdivacky ".objc_static_class_name")); 1603193326Sed Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy, 1604193326Sed ConstantStrings)); 1605198092Srdivacky llvm::StructType *StaticsListTy = 1606198092Srdivacky llvm::StructType::get(VMContext, PtrToInt8Ty, StaticsArrayTy, NULL); 1607198092Srdivacky llvm::Type *StaticsListPtrTy = 1608198092Srdivacky llvm::PointerType::getUnqual(StaticsListTy); 1609193326Sed Statics = MakeGlobal(StaticsListTy, Elements, ".objc_statics"); 1610193326Sed llvm::ArrayType *StaticsListArrayTy = 1611193326Sed llvm::ArrayType::get(StaticsListPtrTy, 2); 1612193326Sed Elements.clear(); 1613193326Sed Elements.push_back(Statics); 1614193326Sed Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy)); 1615193326Sed Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr"); 1616193326Sed Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy); 1617193326Sed } 1618193326Sed // Array of classes, categories, and constant objects 1619193326Sed llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty, 1620193326Sed Classes.size() + Categories.size() + 2); 1621198092Srdivacky llvm::StructType *SymTabTy = llvm::StructType::get(VMContext, 1622198092Srdivacky LongTy, SelStructPtrTy, 1623198092Srdivacky llvm::Type::getInt16Ty(VMContext), 1624198092Srdivacky llvm::Type::getInt16Ty(VMContext), 1625193326Sed ClassListTy, NULL); 1626193326Sed 1627193326Sed Elements.clear(); 1628193326Sed // Pointer to an array of selectors used in this module. 1629193326Sed std::vector<llvm::Constant*> Selectors; 1630193326Sed for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator 1631193326Sed iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end(); 1632193326Sed iter != iterEnd ; ++iter) { 1633198092Srdivacky Elements.push_back(ExportUniqueString(iter->first.first, ".objc_sel_name")); 1634193326Sed Elements.push_back(MakeConstantString(iter->first.second, 1635193326Sed ".objc_sel_types")); 1636193326Sed Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); 1637193326Sed Elements.clear(); 1638193326Sed } 1639193326Sed for (llvm::StringMap<llvm::GlobalAlias*>::iterator 1640193326Sed iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end(); 1641193326Sed iter != iterEnd; ++iter) { 1642193326Sed Elements.push_back( 1643198092Srdivacky ExportUniqueString(iter->getKeyData(), ".objc_sel_name")); 1644193326Sed Elements.push_back(NULLPtr); 1645193326Sed Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); 1646193326Sed Elements.clear(); 1647193326Sed } 1648193326Sed Elements.push_back(NULLPtr); 1649193326Sed Elements.push_back(NULLPtr); 1650193326Sed Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); 1651193326Sed Elements.clear(); 1652193326Sed // Number of static selectors 1653193326Sed Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() )); 1654193326Sed llvm::Constant *SelectorList = MakeGlobal( 1655193326Sed llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors, 1656193326Sed ".objc_selector_list"); 1657198092Srdivacky Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList, 1658193326Sed SelStructPtrTy)); 1659193326Sed 1660193326Sed // Now that all of the static selectors exist, create pointers to them. 1661193326Sed int index = 0; 1662193326Sed for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator 1663193326Sed iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end(); 1664193326Sed iter != iterEnd; ++iter) { 1665193326Sed llvm::Constant *Idxs[] = {Zeros[0], 1666198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]}; 1667198092Srdivacky llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy, 1668193326Sed true, llvm::GlobalValue::InternalLinkage, 1669193326Sed llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), 1670198092Srdivacky ".objc_sel_ptr"); 1671193326Sed // If selectors are defined as an opaque type, cast the pointer to this 1672193326Sed // type. 1673193326Sed if (isSelOpaque) { 1674193326Sed SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, 1675193326Sed llvm::PointerType::getUnqual(SelectorTy)); 1676193326Sed } 1677193326Sed (*iter).second->setAliasee(SelPtr); 1678193326Sed } 1679193326Sed for (llvm::StringMap<llvm::GlobalAlias*>::iterator 1680193326Sed iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end(); 1681193326Sed iter != iterEnd; iter++) { 1682193326Sed llvm::Constant *Idxs[] = {Zeros[0], 1683198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]}; 1684198092Srdivacky llvm::Constant *SelPtr = new llvm::GlobalVariable 1685198092Srdivacky (TheModule, SelStructPtrTy, 1686198092Srdivacky true, llvm::GlobalValue::InternalLinkage, 1687198092Srdivacky llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), 1688198092Srdivacky ".objc_sel_ptr"); 1689193326Sed // If selectors are defined as an opaque type, cast the pointer to this 1690193326Sed // type. 1691193326Sed if (isSelOpaque) { 1692193326Sed SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, 1693193326Sed llvm::PointerType::getUnqual(SelectorTy)); 1694193326Sed } 1695193326Sed (*iter).second->setAliasee(SelPtr); 1696193326Sed } 1697193326Sed // Number of classes defined. 1698198092Srdivacky Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext), 1699193326Sed Classes.size())); 1700193326Sed // Number of categories defined 1701198092Srdivacky Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext), 1702193326Sed Categories.size())); 1703193326Sed // Create an array of classes, then categories, then static object instances 1704193326Sed Classes.insert(Classes.end(), Categories.begin(), Categories.end()); 1705193326Sed // NULL-terminated list of static object instances (mainly constant strings) 1706193326Sed Classes.push_back(Statics); 1707193326Sed Classes.push_back(NULLPtr); 1708193326Sed llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes); 1709193326Sed Elements.push_back(ClassList); 1710198092Srdivacky // Construct the symbol table 1711193326Sed llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements); 1712193326Sed 1713193326Sed // The symbol table is contained in a module which has some version-checking 1714193326Sed // constants 1715198092Srdivacky llvm::StructType * ModuleTy = llvm::StructType::get(VMContext, LongTy, LongTy, 1716193326Sed PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL); 1717193326Sed Elements.clear(); 1718193326Sed // Runtime version used for compatibility checking. 1719193326Sed if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { 1720198092Srdivacky Elements.push_back(llvm::ConstantInt::get(LongTy, 1721193326Sed NonFragileRuntimeVersion)); 1722193326Sed } else { 1723193326Sed Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion)); 1724193326Sed } 1725193326Sed // sizeof(ModuleTy) 1726203955Srdivacky llvm::TargetData td(&TheModule); 1727198092Srdivacky Elements.push_back(llvm::ConstantInt::get(LongTy, 1728198092Srdivacky td.getTypeSizeInBits(ModuleTy)/8)); 1729193326Sed //FIXME: Should be the path to the file where this module was declared 1730193326Sed Elements.push_back(NULLPtr); 1731193326Sed Elements.push_back(SymTab); 1732193326Sed llvm::Value *Module = MakeGlobal(ModuleTy, Elements); 1733193326Sed 1734193326Sed // Create the load function calling the runtime entry point with the module 1735193326Sed // structure 1736193326Sed llvm::Function * LoadFunction = llvm::Function::Create( 1737198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false), 1738193326Sed llvm::GlobalValue::InternalLinkage, ".objc_load_function", 1739193326Sed &TheModule); 1740198092Srdivacky llvm::BasicBlock *EntryBB = 1741198092Srdivacky llvm::BasicBlock::Create(VMContext, "entry", LoadFunction); 1742198092Srdivacky CGBuilderTy Builder(VMContext); 1743193326Sed Builder.SetInsertPoint(EntryBB); 1744193326Sed 1745193326Sed std::vector<const llvm::Type*> Params(1, 1746193326Sed llvm::PointerType::getUnqual(ModuleTy)); 1747193326Sed llvm::Value *Register = CGM.CreateRuntimeFunction(llvm::FunctionType::get( 1748198092Srdivacky llvm::Type::getVoidTy(VMContext), Params, true), "__objc_exec_class"); 1749193326Sed Builder.CreateCall(Register, Module); 1750193326Sed Builder.CreateRetVoid(); 1751193326Sed 1752193326Sed return LoadFunction; 1753193326Sed} 1754193326Sed 1755193326Sedllvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD, 1756198092Srdivacky const ObjCContainerDecl *CD) { 1757198092Srdivacky const ObjCCategoryImplDecl *OCD = 1758193326Sed dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext()); 1759193326Sed std::string CategoryName = OCD ? OCD->getNameAsString() : ""; 1760205408Srdivacky std::string ClassName = CD->getName(); 1761193326Sed std::string MethodName = OMD->getSelector().getAsString(); 1762193326Sed bool isClassMethod = !OMD->isInstanceMethod(); 1763193326Sed 1764193326Sed CodeGenTypes &Types = CGM.getTypes(); 1765198092Srdivacky const llvm::FunctionType *MethodTy = 1766193326Sed Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic()); 1767193326Sed std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName, 1768193326Sed MethodName, isClassMethod); 1769193326Sed 1770198092Srdivacky llvm::Function *Method 1771198092Srdivacky = llvm::Function::Create(MethodTy, 1772198092Srdivacky llvm::GlobalValue::InternalLinkage, 1773198092Srdivacky FunctionName, 1774198092Srdivacky &TheModule); 1775193326Sed return Method; 1776193326Sed} 1777193326Sed 1778193326Sedllvm::Function *CGObjCGNU::GetPropertyGetFunction() { 1779198092Srdivacky std::vector<const llvm::Type*> Params; 1780198092Srdivacky const llvm::Type *BoolTy = 1781198092Srdivacky CGM.getTypes().ConvertType(CGM.getContext().BoolTy); 1782198092Srdivacky Params.push_back(IdTy); 1783198092Srdivacky Params.push_back(SelectorTy); 1784207619Srdivacky Params.push_back(IntTy); 1785198092Srdivacky Params.push_back(BoolTy); 1786207619Srdivacky // void objc_getProperty (id, SEL, int, bool) 1787198092Srdivacky const llvm::FunctionType *FTy = 1788198092Srdivacky llvm::FunctionType::get(IdTy, Params, false); 1789198092Srdivacky return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy, 1790198092Srdivacky "objc_getProperty")); 1791193326Sed} 1792193326Sed 1793193326Sedllvm::Function *CGObjCGNU::GetPropertySetFunction() { 1794198092Srdivacky std::vector<const llvm::Type*> Params; 1795198092Srdivacky const llvm::Type *BoolTy = 1796198092Srdivacky CGM.getTypes().ConvertType(CGM.getContext().BoolTy); 1797198092Srdivacky Params.push_back(IdTy); 1798198092Srdivacky Params.push_back(SelectorTy); 1799207619Srdivacky Params.push_back(IntTy); 1800198092Srdivacky Params.push_back(IdTy); 1801198092Srdivacky Params.push_back(BoolTy); 1802198092Srdivacky Params.push_back(BoolTy); 1803207619Srdivacky // void objc_setProperty (id, SEL, int, id, bool, bool) 1804198092Srdivacky const llvm::FunctionType *FTy = 1805198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); 1806198092Srdivacky return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy, 1807198092Srdivacky "objc_setProperty")); 1808193326Sed} 1809193326Sed 1810207619Srdivacky// FIXME. Implement this. 1811207619Srdivackyllvm::Function *CGObjCGNU::GetCopyStructFunction() { 1812207619Srdivacky return 0; 1813207619Srdivacky} 1814207619Srdivacky 1815198092Srdivackyllvm::Constant *CGObjCGNU::EnumerationMutationFunction() { 1816198092Srdivacky CodeGen::CodeGenTypes &Types = CGM.getTypes(); 1817198092Srdivacky ASTContext &Ctx = CGM.getContext(); 1818198092Srdivacky // void objc_enumerationMutation (id) 1819204643Srdivacky llvm::SmallVector<CanQualType,1> Params; 1820198092Srdivacky Params.push_back(ASTIdTy); 1821198092Srdivacky const llvm::FunctionType *FTy = 1822203955Srdivacky Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params, 1823206084Srdivacky FunctionType::ExtInfo()), false); 1824198092Srdivacky return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); 1825193326Sed} 1826193326Sed 1827193326Sedvoid CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1828193326Sed const Stmt &S) { 1829193326Sed // Pointer to the personality function 1830193326Sed llvm::Constant *Personality = 1831198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), 1832195341Sed true), 1833193326Sed "__gnu_objc_personality_v0"); 1834193326Sed Personality = llvm::ConstantExpr::getBitCast(Personality, PtrTy); 1835193326Sed std::vector<const llvm::Type*> Params; 1836193326Sed Params.push_back(PtrTy); 1837193326Sed llvm::Value *RethrowFn = 1838198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 1839202379Srdivacky Params, false), "_Unwind_Resume"); 1840193326Sed 1841193326Sed bool isTry = isa<ObjCAtTryStmt>(S); 1842193326Sed llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); 1843193326Sed llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest(); 1844193326Sed llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); 1845193326Sed llvm::BasicBlock *CatchInCatch = CGF.createBasicBlock("catch.rethrow"); 1846193326Sed llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally"); 1847193326Sed llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); 1848193326Sed llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); 1849193326Sed 1850201361Srdivacky // @synchronized() 1851193326Sed if (!isTry) { 1852193326Sed std::vector<const llvm::Type*> Args(1, IdTy); 1853193326Sed llvm::FunctionType *FTy = 1854198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 1855193326Sed llvm::Value *SyncEnter = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); 1856198092Srdivacky llvm::Value *SyncArg = 1857193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 1858193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy); 1859193326Sed CGF.Builder.CreateCall(SyncEnter, SyncArg); 1860193326Sed } 1861193326Sed 1862193326Sed 1863193326Sed // Push an EH context entry, used for handling rethrows and jumps 1864193326Sed // through finally. 1865193326Sed CGF.PushCleanupBlock(FinallyBlock); 1866193326Sed 1867193326Sed // Emit the statements in the @try {} block 1868193326Sed CGF.setInvokeDest(TryHandler); 1869193326Sed 1870193326Sed CGF.EmitBlock(TryBlock); 1871198092Srdivacky CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() 1872193326Sed : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); 1873193326Sed 1874193326Sed // Jump to @finally if there is no exception 1875193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 1876193326Sed 1877193326Sed // Emit the handlers 1878193326Sed CGF.EmitBlock(TryHandler); 1879193326Sed 1880193326Sed // Get the correct versions of the exception handling intrinsics 1881198092Srdivacky llvm::Value *llvm_eh_exception = 1882193326Sed CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 1883198092Srdivacky llvm::Value *llvm_eh_selector = 1884198092Srdivacky CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 1885198092Srdivacky llvm::Value *llvm_eh_typeid_for = 1886198092Srdivacky CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); 1887193326Sed 1888193326Sed // Exception object 1889193326Sed llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 1890193326Sed llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow"); 1891193326Sed 1892193326Sed llvm::SmallVector<llvm::Value*, 8> ESelArgs; 1893207619Srdivacky llvm::SmallVector<std::pair<const VarDecl*, const Stmt*>, 8> Handlers; 1894193326Sed 1895193326Sed ESelArgs.push_back(Exc); 1896193326Sed ESelArgs.push_back(Personality); 1897193326Sed 1898193326Sed bool HasCatchAll = false; 1899193326Sed // Only @try blocks are allowed @catch blocks, but both can have @finally 1900193326Sed if (isTry) { 1901207619Srdivacky if (cast<ObjCAtTryStmt>(S).getNumCatchStmts()) { 1902207619Srdivacky const ObjCAtTryStmt &AtTry = cast<ObjCAtTryStmt>(S); 1903193326Sed CGF.setInvokeDest(CatchInCatch); 1904193326Sed 1905207619Srdivacky for (unsigned I = 0, N = AtTry.getNumCatchStmts(); I != N; ++I) { 1906207619Srdivacky const ObjCAtCatchStmt *CatchStmt = AtTry.getCatchStmt(I); 1907207619Srdivacky const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); 1908198092Srdivacky Handlers.push_back(std::make_pair(CatchDecl, 1909198092Srdivacky CatchStmt->getCatchBody())); 1910193326Sed 1911193326Sed // @catch() and @catch(id) both catch any ObjC exception 1912198092Srdivacky if (!CatchDecl || CatchDecl->getType()->isObjCIdType() 1913193326Sed || CatchDecl->getType()->isObjCQualifiedIdType()) { 1914193326Sed // Use i8* null here to signal this is a catch all, not a cleanup. 1915193326Sed ESelArgs.push_back(NULLPtr); 1916193326Sed HasCatchAll = true; 1917193326Sed // No further catches after this one will ever by reached 1918193326Sed break; 1919198092Srdivacky } 1920193326Sed 1921193326Sed // All other types should be Objective-C interface pointer types. 1922198092Srdivacky const ObjCObjectPointerType *OPT = 1923198092Srdivacky CatchDecl->getType()->getAs<ObjCObjectPointerType>(); 1924198092Srdivacky assert(OPT && "Invalid @catch type."); 1925198092Srdivacky const ObjCInterfaceType *IT = 1926198092Srdivacky OPT->getPointeeType()->getAs<ObjCInterfaceType>(); 1927193326Sed assert(IT && "Invalid @catch type."); 1928193326Sed llvm::Value *EHType = 1929193326Sed MakeConstantString(IT->getDecl()->getNameAsString()); 1930193326Sed ESelArgs.push_back(EHType); 1931193326Sed } 1932193326Sed } 1933193326Sed } 1934193326Sed 1935193326Sed // We use a cleanup unless there was already a catch all. 1936193326Sed if (!HasCatchAll) { 1937198092Srdivacky ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); 1938193326Sed Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0)); 1939193326Sed } 1940193326Sed 1941193326Sed // Find which handler was matched. 1942193326Sed llvm::Value *ESelector = CGF.Builder.CreateCall(llvm_eh_selector, 1943193326Sed ESelArgs.begin(), ESelArgs.end(), "selector"); 1944193326Sed 1945193326Sed for (unsigned i = 0, e = Handlers.size(); i != e; ++i) { 1946207619Srdivacky const VarDecl *CatchParam = Handlers[i].first; 1947193326Sed const Stmt *CatchBody = Handlers[i].second; 1948193326Sed 1949193326Sed llvm::BasicBlock *Next = 0; 1950193326Sed 1951193326Sed // The last handler always matches. 1952193326Sed if (i + 1 != e) { 1953193326Sed assert(CatchParam && "Only last handler can be a catch all."); 1954193326Sed 1955193326Sed // Test whether this block matches the type for the selector and branch 1956193326Sed // to Match if it does, or to the next BB if it doesn't. 1957193326Sed llvm::BasicBlock *Match = CGF.createBasicBlock("match"); 1958193326Sed Next = CGF.createBasicBlock("catch.next"); 1959193326Sed llvm::Value *Id = CGF.Builder.CreateCall(llvm_eh_typeid_for, 1960193326Sed CGF.Builder.CreateBitCast(ESelArgs[i+2], PtrTy)); 1961193326Sed CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(ESelector, Id), Match, 1962193326Sed Next); 1963193326Sed 1964193326Sed CGF.EmitBlock(Match); 1965193326Sed } 1966198092Srdivacky 1967193326Sed if (CatchBody) { 1968193326Sed llvm::Value *ExcObject = CGF.Builder.CreateBitCast(Exc, 1969193326Sed CGF.ConvertType(CatchParam->getType())); 1970198092Srdivacky 1971193326Sed // Bind the catch parameter if it exists. 1972193326Sed if (CatchParam) { 1973193326Sed // CatchParam is a ParmVarDecl because of the grammar 1974193326Sed // construction used to handle this, but for codegen purposes 1975193326Sed // we treat this as a local decl. 1976193326Sed CGF.EmitLocalBlockVarDecl(*CatchParam); 1977193326Sed CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(CatchParam)); 1978193326Sed } 1979193326Sed 1980193326Sed CGF.ObjCEHValueStack.push_back(ExcObject); 1981193326Sed CGF.EmitStmt(CatchBody); 1982193326Sed CGF.ObjCEHValueStack.pop_back(); 1983193326Sed 1984193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 1985193326Sed 1986193326Sed if (Next) 1987193326Sed CGF.EmitBlock(Next); 1988193326Sed } else { 1989193326Sed assert(!Next && "catchup should be last handler."); 1990193326Sed 1991193326Sed CGF.Builder.CreateStore(Exc, RethrowPtr); 1992193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 1993193326Sed } 1994193326Sed } 1995193326Sed // The @finally block is a secondary landing pad for any exceptions thrown in 1996193326Sed // @catch() blocks 1997193326Sed CGF.EmitBlock(CatchInCatch); 1998193326Sed Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 1999193326Sed ESelArgs.clear(); 2000193326Sed ESelArgs.push_back(Exc); 2001193326Sed ESelArgs.push_back(Personality); 2002201361Srdivacky // If there is a @catch or @finally clause in outside of this one then we 2003201361Srdivacky // need to make sure that we catch and rethrow it. 2004201361Srdivacky if (PrevLandingPad) { 2005201361Srdivacky ESelArgs.push_back(NULLPtr); 2006201361Srdivacky } else { 2007201361Srdivacky ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); 2008201361Srdivacky } 2009193326Sed CGF.Builder.CreateCall(llvm_eh_selector, ESelArgs.begin(), ESelArgs.end(), 2010193326Sed "selector"); 2011193326Sed CGF.Builder.CreateCall(llvm_eh_typeid_for, 2012193326Sed CGF.Builder.CreateIntToPtr(ESelArgs[2], PtrTy)); 2013193326Sed CGF.Builder.CreateStore(Exc, RethrowPtr); 2014193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 2015193326Sed 2016193326Sed CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); 2017193326Sed 2018193326Sed CGF.setInvokeDest(PrevLandingPad); 2019193326Sed 2020193326Sed CGF.EmitBlock(FinallyBlock); 2021193326Sed 2022193326Sed 2023193326Sed if (isTry) { 2024198092Srdivacky if (const ObjCAtFinallyStmt* FinallyStmt = 2025193326Sed cast<ObjCAtTryStmt>(S).getFinallyStmt()) 2026193326Sed CGF.EmitStmt(FinallyStmt->getFinallyBody()); 2027193326Sed } else { 2028193326Sed // Emit 'objc_sync_exit(expr)' as finally's sole statement for 2029193326Sed // @synchronized. 2030193326Sed std::vector<const llvm::Type*> Args(1, IdTy); 2031193326Sed llvm::FunctionType *FTy = 2032198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 2033193326Sed llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); 2034198092Srdivacky llvm::Value *SyncArg = 2035193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 2036193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy); 2037193326Sed CGF.Builder.CreateCall(SyncExit, SyncArg); 2038193326Sed } 2039193326Sed 2040193326Sed if (Info.SwitchBlock) 2041193326Sed CGF.EmitBlock(Info.SwitchBlock); 2042193326Sed if (Info.EndBlock) 2043193326Sed CGF.EmitBlock(Info.EndBlock); 2044193326Sed 2045193326Sed // Branch around the rethrow code. 2046193326Sed CGF.EmitBranch(FinallyEnd); 2047193326Sed 2048193326Sed CGF.EmitBlock(FinallyRethrow); 2049198092Srdivacky 2050201361Srdivacky llvm::Value *ExceptionObject = CGF.Builder.CreateLoad(RethrowPtr); 2051201361Srdivacky llvm::BasicBlock *UnwindBB = CGF.getInvokeDest(); 2052201361Srdivacky if (!UnwindBB) { 2053201361Srdivacky CGF.Builder.CreateCall(RethrowFn, ExceptionObject); 2054201361Srdivacky // Exception always thrown, next instruction is never reached. 2055201361Srdivacky CGF.Builder.CreateUnreachable(); 2056201361Srdivacky } else { 2057201361Srdivacky // If there is a @catch block outside this scope, we invoke instead of 2058201361Srdivacky // calling because we may return to this function. This is very slow, but 2059201361Srdivacky // some people still do it. It would be nice to add an optimised path for 2060201361Srdivacky // this. 2061201361Srdivacky CGF.Builder.CreateInvoke(RethrowFn, UnwindBB, UnwindBB, &ExceptionObject, 2062201361Srdivacky &ExceptionObject+1); 2063201361Srdivacky } 2064201361Srdivacky 2065193326Sed CGF.EmitBlock(FinallyEnd); 2066193326Sed} 2067193326Sed 2068193326Sedvoid CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 2069193326Sed const ObjCAtThrowStmt &S) { 2070193326Sed llvm::Value *ExceptionAsObject; 2071193326Sed 2072193326Sed std::vector<const llvm::Type*> Args(1, IdTy); 2073193326Sed llvm::FunctionType *FTy = 2074198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 2075198092Srdivacky llvm::Value *ThrowFn = 2076193326Sed CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); 2077198092Srdivacky 2078193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 2079193326Sed llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr); 2080193326Sed ExceptionAsObject = Exception; 2081193326Sed } else { 2082198092Srdivacky assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && 2083193326Sed "Unexpected rethrow outside @catch block."); 2084193326Sed ExceptionAsObject = CGF.ObjCEHValueStack.back(); 2085193326Sed } 2086193326Sed ExceptionAsObject = 2087193326Sed CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy, "tmp"); 2088198092Srdivacky 2089193326Sed // Note: This may have to be an invoke, if we want to support constructs like: 2090193326Sed // @try { 2091193326Sed // @throw(obj); 2092193326Sed // } 2093193326Sed // @catch(id) ... 2094193326Sed // 2095193326Sed // This is effectively turning @throw into an incredibly-expensive goto, but 2096193326Sed // it may happen as a result of inlining followed by missed optimizations, or 2097193326Sed // as a result of stupidity. 2098193326Sed llvm::BasicBlock *UnwindBB = CGF.getInvokeDest(); 2099193326Sed if (!UnwindBB) { 2100193326Sed CGF.Builder.CreateCall(ThrowFn, ExceptionAsObject); 2101193326Sed CGF.Builder.CreateUnreachable(); 2102193326Sed } else { 2103193326Sed CGF.Builder.CreateInvoke(ThrowFn, UnwindBB, UnwindBB, &ExceptionAsObject, 2104193326Sed &ExceptionAsObject+1); 2105193326Sed } 2106193326Sed // Clear the insertion point to indicate we are in unreachable code. 2107193326Sed CGF.Builder.ClearInsertionPoint(); 2108193326Sed} 2109193326Sed 2110193326Sedllvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 2111198092Srdivacky llvm::Value *AddrWeakObj) { 2112203955Srdivacky CGBuilderTy B = CGF.Builder; 2113203955Srdivacky AddrWeakObj = EnforceType(B, AddrWeakObj, IdTy); 2114203955Srdivacky return B.CreateCall(WeakReadFn, AddrWeakObj); 2115193326Sed} 2116193326Sed 2117193326Sedvoid CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 2118198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2119203955Srdivacky CGBuilderTy B = CGF.Builder; 2120203955Srdivacky src = EnforceType(B, src, IdTy); 2121203955Srdivacky dst = EnforceType(B, dst, PtrToIdTy); 2122203955Srdivacky B.CreateCall2(WeakAssignFn, src, dst); 2123193326Sed} 2124193326Sed 2125193326Sedvoid CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 2126198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2127203955Srdivacky CGBuilderTy B = CGF.Builder; 2128203955Srdivacky src = EnforceType(B, src, IdTy); 2129203955Srdivacky dst = EnforceType(B, dst, PtrToIdTy); 2130203955Srdivacky B.CreateCall2(GlobalAssignFn, src, dst); 2131193326Sed} 2132193326Sed 2133193326Sedvoid CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 2134198092Srdivacky llvm::Value *src, llvm::Value *dst, 2135198092Srdivacky llvm::Value *ivarOffset) { 2136203955Srdivacky CGBuilderTy B = CGF.Builder; 2137203955Srdivacky src = EnforceType(B, src, IdTy); 2138203955Srdivacky dst = EnforceType(B, dst, PtrToIdTy); 2139203955Srdivacky B.CreateCall3(IvarAssignFn, src, dst, ivarOffset); 2140193326Sed} 2141193326Sed 2142193326Sedvoid CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 2143198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2144203955Srdivacky CGBuilderTy B = CGF.Builder; 2145203955Srdivacky src = EnforceType(B, src, IdTy); 2146203955Srdivacky dst = EnforceType(B, dst, PtrToIdTy); 2147203955Srdivacky B.CreateCall2(StrongCastAssignFn, src, dst); 2148193326Sed} 2149193326Sed 2150198092Srdivackyvoid CGObjCGNU::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 2151198092Srdivacky llvm::Value *DestPtr, 2152198092Srdivacky llvm::Value *SrcPtr, 2153198092Srdivacky QualType Ty) { 2154203955Srdivacky CGBuilderTy B = CGF.Builder; 2155203955Srdivacky DestPtr = EnforceType(B, DestPtr, IdTy); 2156203955Srdivacky SrcPtr = EnforceType(B, SrcPtr, PtrToIdTy); 2157203955Srdivacky 2158203955Srdivacky std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty); 2159203955Srdivacky unsigned long size = TypeInfo.first/8; 2160203955Srdivacky // FIXME: size_t 2161203955Srdivacky llvm::Value *N = llvm::ConstantInt::get(LongTy, size); 2162203955Srdivacky 2163203955Srdivacky B.CreateCall3(MemMoveFn, DestPtr, SrcPtr, N); 2164198092Srdivacky} 2165198092Srdivacky 2166193326Sedllvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable( 2167193326Sed const ObjCInterfaceDecl *ID, 2168193326Sed const ObjCIvarDecl *Ivar) { 2169193326Sed const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString() 2170193326Sed + '.' + Ivar->getNameAsString(); 2171193326Sed // Emit the variable and initialize it with what we think the correct value 2172193326Sed // is. This allows code compiled with non-fragile ivars to work correctly 2173193326Sed // when linked against code which isn't (most of the time). 2174198092Srdivacky llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name); 2175198092Srdivacky if (!IvarOffsetPointer) { 2176207619Srdivacky uint64_t Offset; 2177207619Srdivacky if (ObjCImplementationDecl *OID = 2178207619Srdivacky CGM.getContext().getObjCImplementation( 2179207619Srdivacky const_cast<ObjCInterfaceDecl *>(ID))) 2180207619Srdivacky Offset = ComputeIvarBaseOffset(CGM, OID, Ivar); 2181207619Srdivacky else 2182207619Srdivacky Offset = ComputeIvarBaseOffset(CGM, ID, Ivar); 2183207619Srdivacky 2184193326Sed llvm::ConstantInt *OffsetGuess = 2185202379Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset, "ivar"); 2186198092Srdivacky // Don't emit the guess in non-PIC code because the linker will not be able 2187198092Srdivacky // to replace it with the real version for a library. In non-PIC code you 2188198092Srdivacky // must compile with the fragile ABI if you want to use ivars from a 2189198092Srdivacky // GCC-compiled class. 2190198092Srdivacky if (CGM.getLangOptions().PICLevel) { 2191198092Srdivacky llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule, 2192198092Srdivacky llvm::Type::getInt32Ty(VMContext), false, 2193198092Srdivacky llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess"); 2194198092Srdivacky IvarOffsetPointer = new llvm::GlobalVariable(TheModule, 2195198092Srdivacky IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage, 2196198092Srdivacky IvarOffsetGV, Name); 2197198092Srdivacky } else { 2198198092Srdivacky IvarOffsetPointer = new llvm::GlobalVariable(TheModule, 2199198092Srdivacky llvm::Type::getInt32PtrTy(VMContext), false, 2200198092Srdivacky llvm::GlobalValue::ExternalLinkage, 0, Name); 2201198092Srdivacky } 2202193326Sed } 2203198092Srdivacky return IvarOffsetPointer; 2204193326Sed} 2205193326Sed 2206193326SedLValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 2207193326Sed QualType ObjectTy, 2208193326Sed llvm::Value *BaseValue, 2209193326Sed const ObjCIvarDecl *Ivar, 2210193326Sed unsigned CVRQualifiers) { 2211198092Srdivacky const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); 2212193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 2213193326Sed EmitIvarOffset(CGF, ID, Ivar)); 2214193326Sed} 2215198092Srdivacky 2216193326Sedstatic const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, 2217193326Sed const ObjCInterfaceDecl *OID, 2218193326Sed const ObjCIvarDecl *OIVD) { 2219193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; 2220193576Sed Context.ShallowCollectObjCIvars(OID, Ivars); 2221193326Sed for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { 2222193326Sed if (OIVD == Ivars[k]) 2223193326Sed return OID; 2224193326Sed } 2225198092Srdivacky 2226193326Sed // Otherwise check in the super class. 2227193326Sed if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 2228193326Sed return FindIvarInterface(Context, Super, OIVD); 2229198092Srdivacky 2230193326Sed return 0; 2231193326Sed} 2232193326Sed 2233193326Sedllvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 2234193326Sed const ObjCInterfaceDecl *Interface, 2235193326Sed const ObjCIvarDecl *Ivar) { 2236198092Srdivacky if (CGM.getLangOptions().ObjCNonFragileABI) { 2237193326Sed Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar); 2238198092Srdivacky return CGF.Builder.CreateLoad(CGF.Builder.CreateLoad( 2239198092Srdivacky ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar")); 2240193326Sed } 2241193326Sed uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar); 2242193326Sed return llvm::ConstantInt::get(LongTy, Offset, "ivar"); 2243193326Sed} 2244193326Sed 2245198092SrdivackyCodeGen::CGObjCRuntime * 2246198092SrdivackyCodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM) { 2247193326Sed return new CGObjCGNU(CGM); 2248193326Sed} 2249