CGObjCGNU.cpp revision 205408
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" 29193326Sed#include "llvm/ADT/SmallVector.h" 30193326Sed#include "llvm/ADT/StringMap.h" 31193326Sed#include "llvm/Support/Compiler.h" 32193326Sed#include "llvm/Target/TargetData.h" 33193326Sed 34193326Sed#include <map> 35193326Sed 36193326Sed 37193326Sedusing namespace clang; 38193326Sedusing namespace CodeGen; 39193326Sedusing llvm::dyn_cast; 40193326Sed 41193326Sed// The version of the runtime that this class targets. Must match the version 42193326Sed// in the runtime. 43193326Sedstatic const int RuntimeVersion = 8; 44193326Sedstatic const int NonFragileRuntimeVersion = 9; 45193326Sedstatic const int ProtocolVersion = 2; 46198092Srdivackystatic const int NonFragileProtocolVersion = 3; 47193326Sed 48193326Sednamespace { 49193326Sedclass CGObjCGNU : public CodeGen::CGObjCRuntime { 50193326Sedprivate: 51193326Sed CodeGen::CodeGenModule &CGM; 52193326Sed llvm::Module &TheModule; 53193326Sed const llvm::PointerType *SelectorTy; 54198092Srdivacky const llvm::IntegerType *Int8Ty; 55193326Sed const llvm::PointerType *PtrToInt8Ty; 56193326Sed const llvm::FunctionType *IMPTy; 57193326Sed const llvm::PointerType *IdTy; 58203955Srdivacky const llvm::PointerType *PtrToIdTy; 59204643Srdivacky CanQualType ASTIdTy; 60193326Sed const llvm::IntegerType *IntTy; 61193326Sed const llvm::PointerType *PtrTy; 62193326Sed const llvm::IntegerType *LongTy; 63193326Sed const llvm::PointerType *PtrToIntTy; 64193326Sed llvm::GlobalAlias *ClassPtrAlias; 65193326Sed llvm::GlobalAlias *MetaClassPtrAlias; 66193326Sed std::vector<llvm::Constant*> Classes; 67193326Sed std::vector<llvm::Constant*> Categories; 68193326Sed std::vector<llvm::Constant*> ConstantStrings; 69203955Srdivacky llvm::StringMap<llvm::Constant*> ObjCStrings; 70193326Sed llvm::Function *LoadFunction; 71193326Sed llvm::StringMap<llvm::Constant*> ExistingProtocols; 72193326Sed typedef std::pair<std::string, std::string> TypedSelector; 73193326Sed std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors; 74193326Sed llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors; 75203955Srdivacky // Selectors that we don't emit in GC mode 76203955Srdivacky Selector RetainSel, ReleaseSel, AutoreleaseSel; 77203955Srdivacky // Functions used for GC. 78203955Srdivacky llvm::Constant *IvarAssignFn, *StrongCastAssignFn, *MemMoveFn, *WeakReadFn, 79203955Srdivacky *WeakAssignFn, *GlobalAssignFn; 80193326Sed // Some zeros used for GEPs in lots of places. 81193326Sed llvm::Constant *Zeros[2]; 82193326Sed llvm::Constant *NULLPtr; 83198092Srdivacky llvm::LLVMContext &VMContext; 84193326Sedprivate: 85193326Sed llvm::Constant *GenerateIvarList( 86193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, 87193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes, 88193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets); 89193326Sed llvm::Constant *GenerateMethodList(const std::string &ClassName, 90193326Sed const std::string &CategoryName, 91198092Srdivacky const llvm::SmallVectorImpl<Selector> &MethodSels, 92198092Srdivacky const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes, 93193326Sed bool isClassMethodList); 94193326Sed llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName); 95198092Srdivacky llvm::Constant *GeneratePropertyList(const ObjCImplementationDecl *OID, 96198092Srdivacky llvm::SmallVectorImpl<Selector> &InstanceMethodSels, 97198092Srdivacky llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes); 98193326Sed llvm::Constant *GenerateProtocolList( 99193326Sed const llvm::SmallVectorImpl<std::string> &Protocols); 100198092Srdivacky // To ensure that all protocols are seen by the runtime, we add a category on 101198092Srdivacky // a class defined in the runtime, declaring no methods, but adopting the 102198092Srdivacky // protocols. 103198092Srdivacky void GenerateProtocolHolderCategory(void); 104193326Sed llvm::Constant *GenerateClassStructure( 105193326Sed llvm::Constant *MetaClass, 106193326Sed llvm::Constant *SuperClass, 107193326Sed unsigned info, 108193326Sed const char *Name, 109193326Sed llvm::Constant *Version, 110193326Sed llvm::Constant *InstanceSize, 111193326Sed llvm::Constant *IVars, 112193326Sed llvm::Constant *Methods, 113198092Srdivacky llvm::Constant *Protocols, 114198092Srdivacky llvm::Constant *IvarOffsets, 115198092Srdivacky llvm::Constant *Properties); 116193326Sed llvm::Constant *GenerateProtocolMethodList( 117193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames, 118193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes); 119193326Sed llvm::Constant *MakeConstantString(const std::string &Str, const std::string 120193326Sed &Name=""); 121198092Srdivacky llvm::Constant *ExportUniqueString(const std::string &Str, const std::string 122198092Srdivacky prefix); 123193326Sed llvm::Constant *MakeGlobal(const llvm::StructType *Ty, 124203955Srdivacky std::vector<llvm::Constant*> &V, llvm::StringRef Name="", 125202379Srdivacky llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage); 126193326Sed llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty, 127203955Srdivacky std::vector<llvm::Constant*> &V, llvm::StringRef Name="", 128202379Srdivacky llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage); 129193326Sed llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, 130193326Sed const ObjCIvarDecl *Ivar); 131194613Sed void EmitClassRef(const std::string &className); 132203955Srdivacky llvm::Value* EnforceType(CGBuilderTy B, llvm::Value *V, const llvm::Type *Ty){ 133203955Srdivacky if (V->getType() == Ty) return V; 134203955Srdivacky return B.CreateBitCast(V, Ty); 135203955Srdivacky } 136193326Sedpublic: 137193326Sed CGObjCGNU(CodeGen::CodeGenModule &cgm); 138202879Srdivacky virtual llvm::Constant *GenerateConstantString(const StringLiteral *); 139198092Srdivacky virtual CodeGen::RValue 140193326Sed GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 141193326Sed QualType ResultType, 142193326Sed Selector Sel, 143193326Sed llvm::Value *Receiver, 144193326Sed bool IsClassMessage, 145193326Sed const CallArgList &CallArgs, 146193326Sed const ObjCMethodDecl *Method); 147198092Srdivacky virtual CodeGen::RValue 148193326Sed GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 149193326Sed QualType ResultType, 150193326Sed Selector Sel, 151193326Sed const ObjCInterfaceDecl *Class, 152193326Sed bool isCategoryImpl, 153193326Sed llvm::Value *Receiver, 154193326Sed bool IsClassMessage, 155198092Srdivacky const CallArgList &CallArgs, 156198092Srdivacky const ObjCMethodDecl *Method); 157193326Sed virtual llvm::Value *GetClass(CGBuilderTy &Builder, 158193326Sed const ObjCInterfaceDecl *OID); 159193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel); 160193326Sed virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl 161193326Sed *Method); 162198092Srdivacky 163198092Srdivacky virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, 164193326Sed const ObjCContainerDecl *CD); 165193326Sed virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD); 166193326Sed virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl); 167193326Sed virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder, 168193326Sed const ObjCProtocolDecl *PD); 169193326Sed virtual void GenerateProtocol(const ObjCProtocolDecl *PD); 170193326Sed virtual llvm::Function *ModuleInitFunction(); 171193326Sed virtual llvm::Function *GetPropertyGetFunction(); 172193326Sed virtual llvm::Function *GetPropertySetFunction(); 173198092Srdivacky virtual llvm::Constant *EnumerationMutationFunction(); 174198092Srdivacky 175193326Sed virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 176193326Sed const Stmt &S); 177193326Sed virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 178193326Sed const ObjCAtThrowStmt &S); 179193326Sed virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 180193326Sed llvm::Value *AddrWeakObj); 181193326Sed virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 182193326Sed llvm::Value *src, llvm::Value *dst); 183193326Sed virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 184193326Sed llvm::Value *src, llvm::Value *dest); 185193326Sed virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 186198092Srdivacky llvm::Value *src, llvm::Value *dest, 187198092Srdivacky llvm::Value *ivarOffset); 188193326Sed virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 189193326Sed llvm::Value *src, llvm::Value *dest); 190198092Srdivacky virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 191198092Srdivacky llvm::Value *DestPtr, 192198092Srdivacky llvm::Value *SrcPtr, 193198092Srdivacky QualType Ty); 194193326Sed virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 195193326Sed QualType ObjectTy, 196193326Sed llvm::Value *BaseValue, 197193326Sed const ObjCIvarDecl *Ivar, 198193326Sed unsigned CVRQualifiers); 199193326Sed virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 200193326Sed const ObjCInterfaceDecl *Interface, 201193326Sed const ObjCIvarDecl *Ivar); 202193326Sed}; 203193326Sed} // end anonymous namespace 204193326Sed 205193326Sed 206194613Sed/// Emits a reference to a dummy variable which is emitted with each class. 207194613Sed/// This ensures that a linker error will be generated when trying to link 208194613Sed/// together modules where a referenced class is not defined. 209198092Srdivackyvoid CGObjCGNU::EmitClassRef(const std::string &className) { 210194613Sed std::string symbolRef = "__objc_class_ref_" + className; 211194613Sed // Don't emit two copies of the same symbol 212198092Srdivacky if (TheModule.getGlobalVariable(symbolRef)) 213198092Srdivacky return; 214194613Sed std::string symbolName = "__objc_class_name_" + className; 215194613Sed llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName); 216194613Sed if (!ClassSymbol) { 217198092Srdivacky ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false, 218198092Srdivacky llvm::GlobalValue::ExternalLinkage, 0, symbolName); 219194613Sed } 220198092Srdivacky new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true, 221198092Srdivacky llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef); 222194613Sed} 223193326Sed 224193326Sedstatic std::string SymbolNameForClass(const std::string &ClassName) { 225194613Sed return "_OBJC_CLASS_" + ClassName; 226193326Sed} 227193326Sed 228193326Sedstatic std::string SymbolNameForMethod(const std::string &ClassName, const 229193326Sed std::string &CategoryName, const std::string &MethodName, bool isClassMethod) 230193326Sed{ 231202379Srdivacky std::string MethodNameColonStripped = MethodName; 232202379Srdivacky std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(), 233202379Srdivacky ':', '_'); 234202379Srdivacky return std::string(isClassMethod ? "_c_" : "_i_") + ClassName + "_" + 235202379Srdivacky CategoryName + "_" + MethodNameColonStripped; 236193326Sed} 237193326Sed 238193326SedCGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm) 239193326Sed : CGM(cgm), TheModule(CGM.getModule()), ClassPtrAlias(0), 240198092Srdivacky MetaClassPtrAlias(0), VMContext(cgm.getLLVMContext()) { 241193326Sed IntTy = cast<llvm::IntegerType>( 242193326Sed CGM.getTypes().ConvertType(CGM.getContext().IntTy)); 243193326Sed LongTy = cast<llvm::IntegerType>( 244193326Sed CGM.getTypes().ConvertType(CGM.getContext().LongTy)); 245198092Srdivacky 246198092Srdivacky Int8Ty = llvm::Type::getInt8Ty(VMContext); 247198092Srdivacky // C string type. Used in lots of places. 248198092Srdivacky PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty); 249198092Srdivacky 250193326Sed Zeros[0] = llvm::ConstantInt::get(LongTy, 0); 251193326Sed Zeros[1] = Zeros[0]; 252198092Srdivacky NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty); 253193326Sed // Get the selector Type. 254202879Srdivacky QualType selTy = CGM.getContext().getObjCSelType(); 255202879Srdivacky if (QualType() == selTy) { 256202879Srdivacky SelectorTy = PtrToInt8Ty; 257202879Srdivacky } else { 258202879Srdivacky SelectorTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(selTy)); 259202879Srdivacky } 260193326Sed 261193326Sed PtrToIntTy = llvm::PointerType::getUnqual(IntTy); 262193326Sed PtrTy = PtrToInt8Ty; 263198092Srdivacky 264193326Sed // Object type 265204643Srdivacky ASTIdTy = CGM.getContext().getCanonicalType(CGM.getContext().getObjCIdType()); 266202879Srdivacky if (QualType() == ASTIdTy) { 267202879Srdivacky IdTy = PtrToInt8Ty; 268202879Srdivacky } else { 269202879Srdivacky IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy)); 270202879Srdivacky } 271203955Srdivacky PtrToIdTy = llvm::PointerType::getUnqual(IdTy); 272198092Srdivacky 273193326Sed // IMP type 274193326Sed std::vector<const llvm::Type*> IMPArgs; 275193326Sed IMPArgs.push_back(IdTy); 276193326Sed IMPArgs.push_back(SelectorTy); 277193326Sed IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true); 278203955Srdivacky 279203955Srdivacky if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { 280203955Srdivacky // Get selectors needed in GC mode 281203955Srdivacky RetainSel = GetNullarySelector("retain", CGM.getContext()); 282203955Srdivacky ReleaseSel = GetNullarySelector("release", CGM.getContext()); 283203955Srdivacky AutoreleaseSel = GetNullarySelector("autorelease", CGM.getContext()); 284203955Srdivacky 285203955Srdivacky // Get functions needed in GC mode 286203955Srdivacky 287203955Srdivacky // id objc_assign_ivar(id, id, ptrdiff_t); 288203955Srdivacky std::vector<const llvm::Type*> Args(1, IdTy); 289203955Srdivacky Args.push_back(PtrToIdTy); 290203955Srdivacky // FIXME: ptrdiff_t 291203955Srdivacky Args.push_back(LongTy); 292203955Srdivacky llvm::FunctionType *FTy = llvm::FunctionType::get(IdTy, Args, false); 293203955Srdivacky IvarAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); 294203955Srdivacky // id objc_assign_strongCast (id, id*) 295203955Srdivacky Args.pop_back(); 296203955Srdivacky FTy = llvm::FunctionType::get(IdTy, Args, false); 297203955Srdivacky StrongCastAssignFn = 298203955Srdivacky CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); 299203955Srdivacky // id objc_assign_global(id, id*); 300203955Srdivacky FTy = llvm::FunctionType::get(IdTy, Args, false); 301203955Srdivacky GlobalAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); 302203955Srdivacky // id objc_assign_weak(id, id*); 303203955Srdivacky FTy = llvm::FunctionType::get(IdTy, Args, false); 304203955Srdivacky WeakAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); 305203955Srdivacky // id objc_read_weak(id*); 306203955Srdivacky Args.clear(); 307203955Srdivacky Args.push_back(PtrToIdTy); 308203955Srdivacky FTy = llvm::FunctionType::get(IdTy, Args, false); 309203955Srdivacky WeakReadFn = CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); 310203955Srdivacky // void *objc_memmove_collectable(void*, void *, size_t); 311203955Srdivacky Args.clear(); 312203955Srdivacky Args.push_back(PtrToInt8Ty); 313203955Srdivacky Args.push_back(PtrToInt8Ty); 314203955Srdivacky // FIXME: size_t 315203955Srdivacky Args.push_back(LongTy); 316203955Srdivacky FTy = llvm::FunctionType::get(IdTy, Args, false); 317203955Srdivacky MemMoveFn = CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); 318203955Srdivacky } 319193326Sed} 320198092Srdivacky 321193326Sed// This has to perform the lookup every time, since posing and related 322193326Sed// techniques can modify the name -> class mapping. 323193326Sedllvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder, 324193326Sed const ObjCInterfaceDecl *OID) { 325193326Sed llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getNameAsString()); 326202379Srdivacky // With the incompatible ABI, this will need to be replaced with a direct 327202379Srdivacky // reference to the class symbol. For the compatible nonfragile ABI we are 328202379Srdivacky // still performing this lookup at run time but emitting the symbol for the 329202379Srdivacky // class externally so that we can make the switch later. 330194613Sed EmitClassRef(OID->getNameAsString()); 331193326Sed ClassName = Builder.CreateStructGEP(ClassName, 0); 332193326Sed 333193326Sed std::vector<const llvm::Type*> Params(1, PtrToInt8Ty); 334193326Sed llvm::Constant *ClassLookupFn = 335193326Sed CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, 336193326Sed Params, 337193326Sed true), 338193326Sed "objc_lookup_class"); 339193326Sed return Builder.CreateCall(ClassLookupFn, ClassName); 340193326Sed} 341193326Sed 342193326Sedllvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel) { 343193326Sed llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()]; 344193326Sed if (US == 0) 345193326Sed US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy), 346198092Srdivacky llvm::GlobalValue::PrivateLinkage, 347198092Srdivacky ".objc_untyped_selector_alias"+Sel.getAsString(), 348193326Sed NULL, &TheModule); 349198092Srdivacky 350193326Sed return Builder.CreateLoad(US); 351193326Sed} 352193326Sed 353193326Sedllvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl 354193326Sed *Method) { 355193326Sed 356193326Sed std::string SelName = Method->getSelector().getAsString(); 357193326Sed std::string SelTypes; 358193326Sed CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes); 359193326Sed // Typed selectors 360193326Sed TypedSelector Selector = TypedSelector(SelName, 361193326Sed SelTypes); 362193326Sed 363193326Sed // If it's already cached, return it. 364198092Srdivacky if (TypedSelectors[Selector]) { 365198092Srdivacky return Builder.CreateLoad(TypedSelectors[Selector]); 366193326Sed } 367193326Sed 368193326Sed // If it isn't, cache it. 369193326Sed llvm::GlobalAlias *Sel = new llvm::GlobalAlias( 370193326Sed llvm::PointerType::getUnqual(SelectorTy), 371198092Srdivacky llvm::GlobalValue::PrivateLinkage, ".objc_selector_alias" + SelName, 372193326Sed NULL, &TheModule); 373193326Sed TypedSelectors[Selector] = Sel; 374193326Sed 375193326Sed return Builder.CreateLoad(Sel); 376193326Sed} 377193326Sed 378193326Sedllvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str, 379193326Sed const std::string &Name) { 380198092Srdivacky llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str()); 381193326Sed return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2); 382193326Sed} 383198092Srdivackyllvm::Constant *CGObjCGNU::ExportUniqueString(const std::string &Str, 384198092Srdivacky const std::string prefix) { 385198092Srdivacky std::string name = prefix + Str; 386198092Srdivacky llvm::Constant *ConstStr = TheModule.getGlobalVariable(name); 387198092Srdivacky if (!ConstStr) { 388198092Srdivacky llvm::Constant *value = llvm::ConstantArray::get(VMContext, Str, true); 389198092Srdivacky ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true, 390198092Srdivacky llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str); 391198092Srdivacky } 392198092Srdivacky return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2); 393198092Srdivacky} 394198092Srdivacky 395193326Sedllvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty, 396203955Srdivacky std::vector<llvm::Constant*> &V, llvm::StringRef Name, 397202379Srdivacky llvm::GlobalValue::LinkageTypes linkage) { 398193326Sed llvm::Constant *C = llvm::ConstantStruct::get(Ty, V); 399198092Srdivacky return new llvm::GlobalVariable(TheModule, Ty, false, 400198092Srdivacky llvm::GlobalValue::InternalLinkage, C, Name); 401193326Sed} 402198092Srdivacky 403193326Sedllvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty, 404203955Srdivacky std::vector<llvm::Constant*> &V, llvm::StringRef Name, 405202379Srdivacky llvm::GlobalValue::LinkageTypes linkage) { 406193326Sed llvm::Constant *C = llvm::ConstantArray::get(Ty, V); 407198092Srdivacky return new llvm::GlobalVariable(TheModule, Ty, false, 408198092Srdivacky llvm::GlobalValue::InternalLinkage, C, Name); 409193326Sed} 410193326Sed 411193326Sed/// Generate an NSConstantString object. 412202879Srdivackyllvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) { 413203955Srdivacky 414202879Srdivacky std::string Str(SL->getStrData(), SL->getByteLength()); 415202879Srdivacky 416203955Srdivacky // Look for an existing one 417203955Srdivacky llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str); 418203955Srdivacky if (old != ObjCStrings.end()) 419203955Srdivacky return old->getValue(); 420203955Srdivacky 421193326Sed std::vector<llvm::Constant*> Ivars; 422193326Sed Ivars.push_back(NULLPtr); 423193326Sed Ivars.push_back(MakeConstantString(Str)); 424193326Sed Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size())); 425193326Sed llvm::Constant *ObjCStr = MakeGlobal( 426198092Srdivacky llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL), 427193326Sed Ivars, ".objc_str"); 428203955Srdivacky ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty); 429203955Srdivacky ObjCStrings[Str] = ObjCStr; 430203955Srdivacky ConstantStrings.push_back(ObjCStr); 431193326Sed return ObjCStr; 432193326Sed} 433193326Sed 434193326Sed///Generates a message send where the super is the receiver. This is a message 435193326Sed///send to self with special delivery semantics indicating which class's method 436193326Sed///should be called. 437193326SedCodeGen::RValue 438193326SedCGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, 439193326Sed QualType ResultType, 440193326Sed Selector Sel, 441193326Sed const ObjCInterfaceDecl *Class, 442193326Sed bool isCategoryImpl, 443193326Sed llvm::Value *Receiver, 444193326Sed bool IsClassMessage, 445198092Srdivacky const CallArgList &CallArgs, 446198092Srdivacky const ObjCMethodDecl *Method) { 447203955Srdivacky if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { 448203955Srdivacky if (Sel == RetainSel || Sel == AutoreleaseSel) { 449203955Srdivacky return RValue::get(Receiver); 450203955Srdivacky } 451203955Srdivacky if (Sel == ReleaseSel) { 452203955Srdivacky return RValue::get(0); 453203955Srdivacky } 454203955Srdivacky } 455193326Sed llvm::Value *cmd = GetSelector(CGF.Builder, Sel); 456193326Sed 457193326Sed CallArgList ActualArgs; 458193326Sed 459193326Sed ActualArgs.push_back( 460198092Srdivacky std::make_pair(RValue::get(CGF.Builder.CreateBitCast(Receiver, IdTy)), 461198092Srdivacky ASTIdTy)); 462193326Sed ActualArgs.push_back(std::make_pair(RValue::get(cmd), 463193326Sed CGF.getContext().getObjCSelType())); 464193326Sed ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); 465193326Sed 466193326Sed CodeGenTypes &Types = CGM.getTypes(); 467203955Srdivacky const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs, 468203955Srdivacky CC_Default, false); 469198092Srdivacky const llvm::FunctionType *impType = 470198092Srdivacky Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); 471193326Sed 472193326Sed llvm::Value *ReceiverClass = 0; 473193326Sed if (isCategoryImpl) { 474193326Sed llvm::Constant *classLookupFunction = 0; 475193326Sed std::vector<const llvm::Type*> Params; 476193326Sed Params.push_back(PtrTy); 477193326Sed if (IsClassMessage) { 478193326Sed classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get( 479193326Sed IdTy, Params, true), "objc_get_meta_class"); 480193326Sed } else { 481193326Sed classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get( 482193326Sed IdTy, Params, true), "objc_get_class"); 483193326Sed } 484193326Sed ReceiverClass = CGF.Builder.CreateCall(classLookupFunction, 485193326Sed MakeConstantString(Class->getNameAsString())); 486193326Sed } else { 487193326Sed // Set up global aliases for the metaclass or class pointer if they do not 488193326Sed // already exist. These will are forward-references which will be set to 489198092Srdivacky // pointers to the class and metaclass structure created for the runtime 490198092Srdivacky // load function. To send a message to super, we look up the value of the 491193326Sed // super_class pointer from either the class or metaclass structure. 492193326Sed if (IsClassMessage) { 493193326Sed if (!MetaClassPtrAlias) { 494193326Sed MetaClassPtrAlias = new llvm::GlobalAlias(IdTy, 495193326Sed llvm::GlobalValue::InternalLinkage, ".objc_metaclass_ref" + 496193326Sed Class->getNameAsString(), NULL, &TheModule); 497193326Sed } 498193326Sed ReceiverClass = MetaClassPtrAlias; 499193326Sed } else { 500193326Sed if (!ClassPtrAlias) { 501193326Sed ClassPtrAlias = new llvm::GlobalAlias(IdTy, 502193326Sed llvm::GlobalValue::InternalLinkage, ".objc_class_ref" + 503193326Sed Class->getNameAsString(), NULL, &TheModule); 504193326Sed } 505193326Sed ReceiverClass = ClassPtrAlias; 506193326Sed } 507193326Sed } 508193326Sed // Cast the pointer to a simplified version of the class structure 509198092Srdivacky ReceiverClass = CGF.Builder.CreateBitCast(ReceiverClass, 510198092Srdivacky llvm::PointerType::getUnqual( 511198092Srdivacky llvm::StructType::get(VMContext, IdTy, IdTy, NULL))); 512193326Sed // Get the superclass pointer 513193326Sed ReceiverClass = CGF.Builder.CreateStructGEP(ReceiverClass, 1); 514193326Sed // Load the superclass pointer 515193326Sed ReceiverClass = CGF.Builder.CreateLoad(ReceiverClass); 516193326Sed // Construct the structure used to look up the IMP 517198092Srdivacky llvm::StructType *ObjCSuperTy = llvm::StructType::get(VMContext, 518198092Srdivacky Receiver->getType(), IdTy, NULL); 519193326Sed llvm::Value *ObjCSuper = CGF.Builder.CreateAlloca(ObjCSuperTy); 520193326Sed 521193326Sed CGF.Builder.CreateStore(Receiver, CGF.Builder.CreateStructGEP(ObjCSuper, 0)); 522193326Sed CGF.Builder.CreateStore(ReceiverClass, 523193326Sed CGF.Builder.CreateStructGEP(ObjCSuper, 1)); 524193326Sed 525193326Sed // Get the IMP 526193326Sed std::vector<const llvm::Type*> Params; 527193326Sed Params.push_back(llvm::PointerType::getUnqual(ObjCSuperTy)); 528193326Sed Params.push_back(SelectorTy); 529198092Srdivacky llvm::Constant *lookupFunction = 530193326Sed CGM.CreateRuntimeFunction(llvm::FunctionType::get( 531193326Sed llvm::PointerType::getUnqual(impType), Params, true), 532193326Sed "objc_msg_lookup_super"); 533193326Sed 534193326Sed llvm::Value *lookupArgs[] = {ObjCSuper, cmd}; 535193326Sed llvm::Value *imp = CGF.Builder.CreateCall(lookupFunction, lookupArgs, 536193326Sed lookupArgs+2); 537193326Sed 538201361Srdivacky return CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs); 539193326Sed} 540193326Sed 541198092Srdivacky/// Generate code for a message send expression. 542193326SedCodeGen::RValue 543193326SedCGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, 544193326Sed QualType ResultType, 545193326Sed Selector Sel, 546193326Sed llvm::Value *Receiver, 547193326Sed bool IsClassMessage, 548193326Sed const CallArgList &CallArgs, 549193326Sed const ObjCMethodDecl *Method) { 550203955Srdivacky if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) { 551203955Srdivacky if (Sel == RetainSel || Sel == AutoreleaseSel) { 552203955Srdivacky return RValue::get(Receiver); 553203955Srdivacky } 554203955Srdivacky if (Sel == ReleaseSel) { 555203955Srdivacky return RValue::get(0); 556203955Srdivacky } 557203955Srdivacky } 558198092Srdivacky CGBuilderTy &Builder = CGF.Builder; 559198092Srdivacky IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy)); 560193326Sed llvm::Value *cmd; 561193326Sed if (Method) 562198092Srdivacky cmd = GetSelector(Builder, Method); 563193326Sed else 564198092Srdivacky cmd = GetSelector(Builder, Sel); 565193326Sed CallArgList ActualArgs; 566193326Sed 567198092Srdivacky Receiver = Builder.CreateBitCast(Receiver, IdTy); 568193326Sed ActualArgs.push_back( 569198092Srdivacky std::make_pair(RValue::get(Receiver), ASTIdTy)); 570193326Sed ActualArgs.push_back(std::make_pair(RValue::get(cmd), 571193326Sed CGF.getContext().getObjCSelType())); 572193326Sed ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end()); 573193326Sed 574193326Sed CodeGenTypes &Types = CGM.getTypes(); 575203955Srdivacky const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs, 576203955Srdivacky CC_Default, false); 577198092Srdivacky const llvm::FunctionType *impType = 578198092Srdivacky Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false); 579193326Sed 580193326Sed llvm::Value *imp; 581193326Sed // For sender-aware dispatch, we pass the sender as the third argument to a 582193326Sed // lookup function. When sending messages from C code, the sender is nil. 583198092Srdivacky // objc_msg_lookup_sender(id *receiver, SEL selector, id sender); 584198092Srdivacky if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { 585198092Srdivacky 586198092Srdivacky std::vector<const llvm::Type*> Params; 587198092Srdivacky llvm::Value *ReceiverPtr = CGF.CreateTempAlloca(Receiver->getType()); 588198092Srdivacky Builder.CreateStore(Receiver, ReceiverPtr); 589198092Srdivacky Params.push_back(ReceiverPtr->getType()); 590198092Srdivacky Params.push_back(SelectorTy); 591193326Sed llvm::Value *self; 592193326Sed 593193326Sed if (isa<ObjCMethodDecl>(CGF.CurFuncDecl)) { 594193326Sed self = CGF.LoadObjCSelf(); 595193326Sed } else { 596193326Sed self = llvm::ConstantPointerNull::get(IdTy); 597193326Sed } 598198092Srdivacky 599193326Sed Params.push_back(self->getType()); 600198092Srdivacky 601198092Srdivacky // The lookup function returns a slot, which can be safely cached. 602198092Srdivacky llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy, 603198092Srdivacky IntTy, llvm::PointerType::getUnqual(impType), NULL); 604198092Srdivacky llvm::Constant *lookupFunction = 605193326Sed CGM.CreateRuntimeFunction(llvm::FunctionType::get( 606198092Srdivacky llvm::PointerType::getUnqual(SlotTy), Params, true), 607193326Sed "objc_msg_lookup_sender"); 608193326Sed 609198092Srdivacky // The lookup function is guaranteed not to capture the receiver pointer. 610198092Srdivacky if (llvm::Function *LookupFn = dyn_cast<llvm::Function>(lookupFunction)) { 611198092Srdivacky LookupFn->setDoesNotCapture(1); 612198092Srdivacky } 613198092Srdivacky 614198092Srdivacky llvm::Value *slot = 615198092Srdivacky Builder.CreateCall3(lookupFunction, ReceiverPtr, cmd, self); 616198092Srdivacky imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4)); 617198092Srdivacky // The lookup function may have changed the receiver, so make sure we use 618198092Srdivacky // the new one. 619198092Srdivacky ActualArgs[0] = 620198092Srdivacky std::make_pair(RValue::get(Builder.CreateLoad(ReceiverPtr)), ASTIdTy); 621193326Sed } else { 622198092Srdivacky std::vector<const llvm::Type*> Params; 623198092Srdivacky Params.push_back(Receiver->getType()); 624198092Srdivacky Params.push_back(SelectorTy); 625198092Srdivacky llvm::Constant *lookupFunction = 626193326Sed CGM.CreateRuntimeFunction(llvm::FunctionType::get( 627193326Sed llvm::PointerType::getUnqual(impType), Params, true), 628193326Sed "objc_msg_lookup"); 629193326Sed 630198092Srdivacky imp = Builder.CreateCall2(lookupFunction, Receiver, cmd); 631193326Sed } 632193326Sed 633201361Srdivacky return CGF.EmitCall(FnInfo, imp, ReturnValueSlot(), ActualArgs); 634193326Sed} 635193326Sed 636198092Srdivacky/// Generates a MethodList. Used in construction of a objc_class and 637193326Sed/// objc_category structures. 638193326Sedllvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName, 639198092Srdivacky const std::string &CategoryName, 640198092Srdivacky const llvm::SmallVectorImpl<Selector> &MethodSels, 641198092Srdivacky const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes, 642193326Sed bool isClassMethodList) { 643198092Srdivacky if (MethodSels.empty()) 644198092Srdivacky return NULLPtr; 645198092Srdivacky // Get the method structure type. 646198092Srdivacky llvm::StructType *ObjCMethodTy = llvm::StructType::get(VMContext, 647193326Sed PtrToInt8Ty, // Really a selector, but the runtime creates it us. 648193326Sed PtrToInt8Ty, // Method types 649193326Sed llvm::PointerType::getUnqual(IMPTy), //Method pointer 650193326Sed NULL); 651193326Sed std::vector<llvm::Constant*> Methods; 652193326Sed std::vector<llvm::Constant*> Elements; 653193326Sed for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) { 654193326Sed Elements.clear(); 655193326Sed if (llvm::Constant *Method = 656193326Sed TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName, 657193326Sed MethodSels[i].getAsString(), 658193326Sed isClassMethodList))) { 659198092Srdivacky llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString()); 660198092Srdivacky Elements.push_back(C); 661198092Srdivacky Elements.push_back(MethodTypes[i]); 662193326Sed Method = llvm::ConstantExpr::getBitCast(Method, 663193326Sed llvm::PointerType::getUnqual(IMPTy)); 664193326Sed Elements.push_back(Method); 665193326Sed Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements)); 666193326Sed } 667193326Sed } 668193326Sed 669193326Sed // Array of method structures 670193326Sed llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy, 671193326Sed Methods.size()); 672193326Sed llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy, 673193326Sed Methods); 674193326Sed 675193326Sed // Structure containing list pointer, array and array count 676193326Sed llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields; 677198092Srdivacky llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get(VMContext); 678193326Sed llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy); 679198092Srdivacky llvm::StructType *ObjCMethodListTy = llvm::StructType::get(VMContext, 680198092Srdivacky NextPtrTy, 681198092Srdivacky IntTy, 682193326Sed ObjCMethodArrayTy, 683193326Sed NULL); 684193326Sed // Refine next pointer type to concrete type 685193326Sed llvm::cast<llvm::OpaqueType>( 686193326Sed OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy); 687193326Sed ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get()); 688193326Sed 689193326Sed Methods.clear(); 690193326Sed Methods.push_back(llvm::ConstantPointerNull::get( 691193326Sed llvm::PointerType::getUnqual(ObjCMethodListTy))); 692198092Srdivacky Methods.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 693193326Sed MethodTypes.size())); 694193326Sed Methods.push_back(MethodArray); 695198092Srdivacky 696193326Sed // Create an instance of the structure 697193326Sed return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list"); 698193326Sed} 699193326Sed 700193326Sed/// Generates an IvarList. Used in construction of a objc_class. 701193326Sedllvm::Constant *CGObjCGNU::GenerateIvarList( 702193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames, 703193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes, 704193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) { 705199482Srdivacky if (IvarNames.size() == 0) 706199482Srdivacky return NULLPtr; 707198092Srdivacky // Get the method structure type. 708198092Srdivacky llvm::StructType *ObjCIvarTy = llvm::StructType::get(VMContext, 709193326Sed PtrToInt8Ty, 710193326Sed PtrToInt8Ty, 711193326Sed IntTy, 712193326Sed NULL); 713193326Sed std::vector<llvm::Constant*> Ivars; 714193326Sed std::vector<llvm::Constant*> Elements; 715193326Sed for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) { 716193326Sed Elements.clear(); 717198092Srdivacky Elements.push_back(IvarNames[i]); 718198092Srdivacky Elements.push_back(IvarTypes[i]); 719193326Sed Elements.push_back(IvarOffsets[i]); 720193326Sed Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements)); 721193326Sed } 722193326Sed 723193326Sed // Array of method structures 724193326Sed llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy, 725193326Sed IvarNames.size()); 726193326Sed 727198092Srdivacky 728193326Sed Elements.clear(); 729193326Sed Elements.push_back(llvm::ConstantInt::get(IntTy, (int)IvarNames.size())); 730193326Sed Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars)); 731193326Sed // Structure containing array and array count 732198092Srdivacky llvm::StructType *ObjCIvarListTy = llvm::StructType::get(VMContext, IntTy, 733193326Sed ObjCIvarArrayTy, 734193326Sed NULL); 735193326Sed 736193326Sed // Create an instance of the structure 737193326Sed return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list"); 738193326Sed} 739193326Sed 740193326Sed/// Generate a class structure 741193326Sedllvm::Constant *CGObjCGNU::GenerateClassStructure( 742193326Sed llvm::Constant *MetaClass, 743193326Sed llvm::Constant *SuperClass, 744193326Sed unsigned info, 745193326Sed const char *Name, 746193326Sed llvm::Constant *Version, 747193326Sed llvm::Constant *InstanceSize, 748193326Sed llvm::Constant *IVars, 749193326Sed llvm::Constant *Methods, 750198092Srdivacky llvm::Constant *Protocols, 751198092Srdivacky llvm::Constant *IvarOffsets, 752198092Srdivacky llvm::Constant *Properties) { 753193326Sed // Set up the class structure 754193326Sed // Note: Several of these are char*s when they should be ids. This is 755193326Sed // because the runtime performs this translation on load. 756198092Srdivacky // 757198092Srdivacky // Fields marked New ABI are part of the GNUstep runtime. We emit them 758198092Srdivacky // anyway; the classes will still work with the GNU runtime, they will just 759198092Srdivacky // be ignored. 760198092Srdivacky llvm::StructType *ClassTy = llvm::StructType::get(VMContext, 761193326Sed PtrToInt8Ty, // class_pointer 762193326Sed PtrToInt8Ty, // super_class 763193326Sed PtrToInt8Ty, // name 764193326Sed LongTy, // version 765193326Sed LongTy, // info 766193326Sed LongTy, // instance_size 767193326Sed IVars->getType(), // ivars 768193326Sed Methods->getType(), // methods 769198092Srdivacky // These are all filled in by the runtime, so we pretend 770193326Sed PtrTy, // dtable 771193326Sed PtrTy, // subclass_list 772193326Sed PtrTy, // sibling_class 773193326Sed PtrTy, // protocols 774193326Sed PtrTy, // gc_object_type 775198092Srdivacky // New ABI: 776198092Srdivacky LongTy, // abi_version 777198092Srdivacky IvarOffsets->getType(), // ivar_offsets 778198092Srdivacky Properties->getType(), // properties 779193326Sed NULL); 780193326Sed llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0); 781193326Sed // Fill in the structure 782193326Sed std::vector<llvm::Constant*> Elements; 783193326Sed Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty)); 784193326Sed Elements.push_back(SuperClass); 785193326Sed Elements.push_back(MakeConstantString(Name, ".class_name")); 786193326Sed Elements.push_back(Zero); 787193326Sed Elements.push_back(llvm::ConstantInt::get(LongTy, info)); 788193326Sed Elements.push_back(InstanceSize); 789193326Sed Elements.push_back(IVars); 790193326Sed Elements.push_back(Methods); 791198092Srdivacky Elements.push_back(NULLPtr); 792198092Srdivacky Elements.push_back(NULLPtr); 793198092Srdivacky Elements.push_back(NULLPtr); 794193326Sed Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy)); 795198092Srdivacky Elements.push_back(NULLPtr); 796198092Srdivacky Elements.push_back(Zero); 797198092Srdivacky Elements.push_back(IvarOffsets); 798198092Srdivacky Elements.push_back(Properties); 799193326Sed // Create an instance of the structure 800202379Srdivacky // This is now an externally visible symbol, so that we can speed up class 801202379Srdivacky // messages in the next ABI. 802202379Srdivacky return MakeGlobal(ClassTy, Elements, SymbolNameForClass(Name), 803202379Srdivacky llvm::GlobalValue::ExternalLinkage); 804193326Sed} 805193326Sed 806193326Sedllvm::Constant *CGObjCGNU::GenerateProtocolMethodList( 807193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames, 808193326Sed const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) { 809198092Srdivacky // Get the method structure type. 810198092Srdivacky llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(VMContext, 811193326Sed PtrToInt8Ty, // Really a selector, but the runtime does the casting for us. 812193326Sed PtrToInt8Ty, 813193326Sed NULL); 814193326Sed std::vector<llvm::Constant*> Methods; 815193326Sed std::vector<llvm::Constant*> Elements; 816193326Sed for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) { 817193326Sed Elements.clear(); 818198092Srdivacky Elements.push_back(MethodNames[i]); 819198092Srdivacky Elements.push_back(MethodTypes[i]); 820193326Sed Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements)); 821193326Sed } 822193326Sed llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy, 823193326Sed MethodNames.size()); 824198092Srdivacky llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy, 825198092Srdivacky Methods); 826198092Srdivacky llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(VMContext, 827193326Sed IntTy, ObjCMethodArrayTy, NULL); 828193326Sed Methods.clear(); 829193326Sed Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size())); 830193326Sed Methods.push_back(Array); 831193326Sed return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list"); 832193326Sed} 833198092Srdivacky 834193326Sed// Create the protocol list structure used in classes, categories and so on 835193326Sedllvm::Constant *CGObjCGNU::GenerateProtocolList( 836193326Sed const llvm::SmallVectorImpl<std::string> &Protocols) { 837193326Sed llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty, 838193326Sed Protocols.size()); 839198092Srdivacky llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext, 840193326Sed PtrTy, //Should be a recurisve pointer, but it's always NULL here. 841193326Sed LongTy,//FIXME: Should be size_t 842193326Sed ProtocolArrayTy, 843193326Sed NULL); 844198092Srdivacky std::vector<llvm::Constant*> Elements; 845193326Sed for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end(); 846193326Sed iter != endIter ; iter++) { 847199990Srdivacky llvm::Constant *protocol = 0; 848199990Srdivacky llvm::StringMap<llvm::Constant*>::iterator value = 849199990Srdivacky ExistingProtocols.find(*iter); 850199990Srdivacky if (value == ExistingProtocols.end()) { 851193326Sed protocol = GenerateEmptyProtocol(*iter); 852199990Srdivacky } else { 853199990Srdivacky protocol = value->getValue(); 854199990Srdivacky } 855198092Srdivacky llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(protocol, 856198092Srdivacky PtrToInt8Ty); 857193326Sed Elements.push_back(Ptr); 858193326Sed } 859193326Sed llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy, 860193326Sed Elements); 861193326Sed Elements.clear(); 862193326Sed Elements.push_back(NULLPtr); 863193326Sed Elements.push_back(llvm::ConstantInt::get(LongTy, Protocols.size())); 864193326Sed Elements.push_back(ProtocolArray); 865193326Sed return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list"); 866193326Sed} 867193326Sed 868198092Srdivackyllvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder, 869193326Sed const ObjCProtocolDecl *PD) { 870193326Sed llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()]; 871198092Srdivacky const llvm::Type *T = 872193326Sed CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType()); 873193326Sed return Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T)); 874193326Sed} 875193326Sed 876193326Sedllvm::Constant *CGObjCGNU::GenerateEmptyProtocol( 877193326Sed const std::string &ProtocolName) { 878193326Sed llvm::SmallVector<std::string, 0> EmptyStringVector; 879193326Sed llvm::SmallVector<llvm::Constant*, 0> EmptyConstantVector; 880193326Sed 881193326Sed llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector); 882198092Srdivacky llvm::Constant *MethodList = 883193326Sed GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector); 884193326Sed // Protocols are objects containing lists of the methods implemented and 885193326Sed // protocols adopted. 886198092Srdivacky llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy, 887193326Sed PtrToInt8Ty, 888193326Sed ProtocolList->getType(), 889198092Srdivacky MethodList->getType(), 890198092Srdivacky MethodList->getType(), 891198092Srdivacky MethodList->getType(), 892198092Srdivacky MethodList->getType(), 893193326Sed NULL); 894198092Srdivacky std::vector<llvm::Constant*> Elements; 895193326Sed // The isa pointer must be set to a magic number so the runtime knows it's 896193326Sed // the correct layout. 897198092Srdivacky int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ? 898198092Srdivacky NonFragileProtocolVersion : ProtocolVersion; 899193326Sed Elements.push_back(llvm::ConstantExpr::getIntToPtr( 900198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy)); 901193326Sed Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name")); 902193326Sed Elements.push_back(ProtocolList); 903198092Srdivacky Elements.push_back(MethodList); 904198092Srdivacky Elements.push_back(MethodList); 905198092Srdivacky Elements.push_back(MethodList); 906198092Srdivacky Elements.push_back(MethodList); 907193326Sed return MakeGlobal(ProtocolTy, Elements, ".objc_protocol"); 908193326Sed} 909193326Sed 910193326Sedvoid CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { 911193326Sed ASTContext &Context = CGM.getContext(); 912193326Sed std::string ProtocolName = PD->getNameAsString(); 913193326Sed llvm::SmallVector<std::string, 16> Protocols; 914193326Sed for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(), 915193326Sed E = PD->protocol_end(); PI != E; ++PI) 916193326Sed Protocols.push_back((*PI)->getNameAsString()); 917193326Sed llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames; 918193326Sed llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; 919198092Srdivacky llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodNames; 920198092Srdivacky llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodTypes; 921195341Sed for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(), 922195341Sed E = PD->instmeth_end(); iter != E; iter++) { 923193326Sed std::string TypeStr; 924193326Sed Context.getObjCEncodingForMethodDecl(*iter, TypeStr); 925198092Srdivacky if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) { 926198092Srdivacky InstanceMethodNames.push_back( 927198092Srdivacky MakeConstantString((*iter)->getSelector().getAsString())); 928198092Srdivacky InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); 929198092Srdivacky } else { 930198092Srdivacky OptionalInstanceMethodNames.push_back( 931198092Srdivacky MakeConstantString((*iter)->getSelector().getAsString())); 932198092Srdivacky OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr)); 933198092Srdivacky } 934193326Sed } 935193326Sed // Collect information about class methods: 936193326Sed llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames; 937193326Sed llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; 938198092Srdivacky llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodNames; 939198092Srdivacky llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodTypes; 940198092Srdivacky for (ObjCProtocolDecl::classmeth_iterator 941195341Sed iter = PD->classmeth_begin(), endIter = PD->classmeth_end(); 942195341Sed iter != endIter ; iter++) { 943193326Sed std::string TypeStr; 944193326Sed Context.getObjCEncodingForMethodDecl((*iter),TypeStr); 945198092Srdivacky if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) { 946198092Srdivacky ClassMethodNames.push_back( 947198092Srdivacky MakeConstantString((*iter)->getSelector().getAsString())); 948198092Srdivacky ClassMethodTypes.push_back(MakeConstantString(TypeStr)); 949198092Srdivacky } else { 950198092Srdivacky OptionalClassMethodNames.push_back( 951198092Srdivacky MakeConstantString((*iter)->getSelector().getAsString())); 952198092Srdivacky OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr)); 953198092Srdivacky } 954193326Sed } 955193326Sed 956193326Sed llvm::Constant *ProtocolList = GenerateProtocolList(Protocols); 957193326Sed llvm::Constant *InstanceMethodList = 958193326Sed GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes); 959193326Sed llvm::Constant *ClassMethodList = 960193326Sed GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes); 961198092Srdivacky llvm::Constant *OptionalInstanceMethodList = 962198092Srdivacky GenerateProtocolMethodList(OptionalInstanceMethodNames, 963198092Srdivacky OptionalInstanceMethodTypes); 964198092Srdivacky llvm::Constant *OptionalClassMethodList = 965198092Srdivacky GenerateProtocolMethodList(OptionalClassMethodNames, 966198092Srdivacky OptionalClassMethodTypes); 967198092Srdivacky 968198092Srdivacky // Property metadata: name, attributes, isSynthesized, setter name, setter 969198092Srdivacky // types, getter name, getter types. 970198092Srdivacky // The isSynthesized value is always set to 0 in a protocol. It exists to 971198092Srdivacky // simplify the runtime library by allowing it to use the same data 972198092Srdivacky // structures for protocol metadata everywhere. 973198092Srdivacky llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext, 974198092Srdivacky PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, 975198092Srdivacky PtrToInt8Ty, NULL); 976198092Srdivacky std::vector<llvm::Constant*> Properties; 977198092Srdivacky std::vector<llvm::Constant*> OptionalProperties; 978198092Srdivacky 979198092Srdivacky // Add all of the property methods need adding to the method list and to the 980198092Srdivacky // property metadata list. 981198092Srdivacky for (ObjCContainerDecl::prop_iterator 982198092Srdivacky iter = PD->prop_begin(), endIter = PD->prop_end(); 983198092Srdivacky iter != endIter ; iter++) { 984198092Srdivacky std::vector<llvm::Constant*> Fields; 985198092Srdivacky ObjCPropertyDecl *property = (*iter); 986198092Srdivacky 987198092Srdivacky Fields.push_back(MakeConstantString(property->getNameAsString())); 988198092Srdivacky Fields.push_back(llvm::ConstantInt::get(Int8Ty, 989198092Srdivacky property->getPropertyAttributes())); 990198092Srdivacky Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0)); 991198092Srdivacky if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) { 992198092Srdivacky std::string TypeStr; 993198092Srdivacky Context.getObjCEncodingForMethodDecl(getter,TypeStr); 994198092Srdivacky llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); 995198092Srdivacky InstanceMethodTypes.push_back(TypeEncoding); 996198092Srdivacky Fields.push_back(MakeConstantString(getter->getSelector().getAsString())); 997198092Srdivacky Fields.push_back(TypeEncoding); 998198092Srdivacky } else { 999198092Srdivacky Fields.push_back(NULLPtr); 1000198092Srdivacky Fields.push_back(NULLPtr); 1001198092Srdivacky } 1002198092Srdivacky if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) { 1003198092Srdivacky std::string TypeStr; 1004198092Srdivacky Context.getObjCEncodingForMethodDecl(setter,TypeStr); 1005198092Srdivacky llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); 1006198092Srdivacky InstanceMethodTypes.push_back(TypeEncoding); 1007198092Srdivacky Fields.push_back(MakeConstantString(setter->getSelector().getAsString())); 1008198092Srdivacky Fields.push_back(TypeEncoding); 1009198092Srdivacky } else { 1010198092Srdivacky Fields.push_back(NULLPtr); 1011198092Srdivacky Fields.push_back(NULLPtr); 1012198092Srdivacky } 1013198092Srdivacky if (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) { 1014198092Srdivacky OptionalProperties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields)); 1015198092Srdivacky } else { 1016198092Srdivacky Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields)); 1017198092Srdivacky } 1018198092Srdivacky } 1019198092Srdivacky llvm::Constant *PropertyArray = llvm::ConstantArray::get( 1020198092Srdivacky llvm::ArrayType::get(PropertyMetadataTy, Properties.size()), Properties); 1021198092Srdivacky llvm::Constant* PropertyListInitFields[] = 1022198092Srdivacky {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray}; 1023198092Srdivacky 1024198092Srdivacky llvm::Constant *PropertyListInit = 1025198092Srdivacky llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false); 1026198092Srdivacky llvm::Constant *PropertyList = new llvm::GlobalVariable(TheModule, 1027198092Srdivacky PropertyListInit->getType(), false, llvm::GlobalValue::InternalLinkage, 1028198092Srdivacky PropertyListInit, ".objc_property_list"); 1029198092Srdivacky 1030198092Srdivacky llvm::Constant *OptionalPropertyArray = 1031198092Srdivacky llvm::ConstantArray::get(llvm::ArrayType::get(PropertyMetadataTy, 1032198092Srdivacky OptionalProperties.size()) , OptionalProperties); 1033198092Srdivacky llvm::Constant* OptionalPropertyListInitFields[] = { 1034198092Srdivacky llvm::ConstantInt::get(IntTy, OptionalProperties.size()), NULLPtr, 1035198092Srdivacky OptionalPropertyArray }; 1036198092Srdivacky 1037198092Srdivacky llvm::Constant *OptionalPropertyListInit = 1038198092Srdivacky llvm::ConstantStruct::get(VMContext, OptionalPropertyListInitFields, 3, false); 1039198092Srdivacky llvm::Constant *OptionalPropertyList = new llvm::GlobalVariable(TheModule, 1040198092Srdivacky OptionalPropertyListInit->getType(), false, 1041198092Srdivacky llvm::GlobalValue::InternalLinkage, OptionalPropertyListInit, 1042198092Srdivacky ".objc_property_list"); 1043198092Srdivacky 1044193326Sed // Protocols are objects containing lists of the methods implemented and 1045193326Sed // protocols adopted. 1046198092Srdivacky llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy, 1047193326Sed PtrToInt8Ty, 1048193326Sed ProtocolList->getType(), 1049193326Sed InstanceMethodList->getType(), 1050193326Sed ClassMethodList->getType(), 1051198092Srdivacky OptionalInstanceMethodList->getType(), 1052198092Srdivacky OptionalClassMethodList->getType(), 1053198092Srdivacky PropertyList->getType(), 1054198092Srdivacky OptionalPropertyList->getType(), 1055193326Sed NULL); 1056198092Srdivacky std::vector<llvm::Constant*> Elements; 1057193326Sed // The isa pointer must be set to a magic number so the runtime knows it's 1058193326Sed // the correct layout. 1059198092Srdivacky int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ? 1060198092Srdivacky NonFragileProtocolVersion : ProtocolVersion; 1061193326Sed Elements.push_back(llvm::ConstantExpr::getIntToPtr( 1062198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy)); 1063193326Sed Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name")); 1064193326Sed Elements.push_back(ProtocolList); 1065193326Sed Elements.push_back(InstanceMethodList); 1066193326Sed Elements.push_back(ClassMethodList); 1067198092Srdivacky Elements.push_back(OptionalInstanceMethodList); 1068198092Srdivacky Elements.push_back(OptionalClassMethodList); 1069198092Srdivacky Elements.push_back(PropertyList); 1070198092Srdivacky Elements.push_back(OptionalPropertyList); 1071198092Srdivacky ExistingProtocols[ProtocolName] = 1072193326Sed llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements, 1073193326Sed ".objc_protocol"), IdTy); 1074193326Sed} 1075198092Srdivackyvoid CGObjCGNU::GenerateProtocolHolderCategory(void) { 1076198092Srdivacky // Collect information about instance methods 1077198092Srdivacky llvm::SmallVector<Selector, 1> MethodSels; 1078198092Srdivacky llvm::SmallVector<llvm::Constant*, 1> MethodTypes; 1079193326Sed 1080198092Srdivacky std::vector<llvm::Constant*> Elements; 1081198092Srdivacky const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack"; 1082198092Srdivacky const std::string CategoryName = "AnotherHack"; 1083198092Srdivacky Elements.push_back(MakeConstantString(CategoryName)); 1084198092Srdivacky Elements.push_back(MakeConstantString(ClassName)); 1085198092Srdivacky // Instance method list 1086198092Srdivacky Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( 1087198092Srdivacky ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy)); 1088198092Srdivacky // Class method list 1089198092Srdivacky Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( 1090198092Srdivacky ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy)); 1091198092Srdivacky // Protocol list 1092198092Srdivacky llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrTy, 1093198092Srdivacky ExistingProtocols.size()); 1094198092Srdivacky llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext, 1095198092Srdivacky PtrTy, //Should be a recurisve pointer, but it's always NULL here. 1096198092Srdivacky LongTy,//FIXME: Should be size_t 1097198092Srdivacky ProtocolArrayTy, 1098198092Srdivacky NULL); 1099198092Srdivacky std::vector<llvm::Constant*> ProtocolElements; 1100198092Srdivacky for (llvm::StringMapIterator<llvm::Constant*> iter = 1101198092Srdivacky ExistingProtocols.begin(), endIter = ExistingProtocols.end(); 1102198092Srdivacky iter != endIter ; iter++) { 1103198092Srdivacky llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(iter->getValue(), 1104198092Srdivacky PtrTy); 1105198092Srdivacky ProtocolElements.push_back(Ptr); 1106198092Srdivacky } 1107198092Srdivacky llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy, 1108198092Srdivacky ProtocolElements); 1109198092Srdivacky ProtocolElements.clear(); 1110198092Srdivacky ProtocolElements.push_back(NULLPtr); 1111198092Srdivacky ProtocolElements.push_back(llvm::ConstantInt::get(LongTy, 1112198092Srdivacky ExistingProtocols.size())); 1113198092Srdivacky ProtocolElements.push_back(ProtocolArray); 1114198092Srdivacky Elements.push_back(llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolListTy, 1115198092Srdivacky ProtocolElements, ".objc_protocol_list"), PtrTy)); 1116198092Srdivacky Categories.push_back(llvm::ConstantExpr::getBitCast( 1117198092Srdivacky MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, 1118198092Srdivacky PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy)); 1119198092Srdivacky} 1120198092Srdivacky 1121193326Sedvoid CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { 1122193326Sed std::string ClassName = OCD->getClassInterface()->getNameAsString(); 1123193326Sed std::string CategoryName = OCD->getNameAsString(); 1124193326Sed // Collect information about instance methods 1125193326Sed llvm::SmallVector<Selector, 16> InstanceMethodSels; 1126193326Sed llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; 1127193326Sed for (ObjCCategoryImplDecl::instmeth_iterator 1128195341Sed iter = OCD->instmeth_begin(), endIter = OCD->instmeth_end(); 1129193326Sed iter != endIter ; iter++) { 1130193326Sed InstanceMethodSels.push_back((*iter)->getSelector()); 1131193326Sed std::string TypeStr; 1132193326Sed CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr); 1133198092Srdivacky InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); 1134193326Sed } 1135193326Sed 1136193326Sed // Collect information about class methods 1137193326Sed llvm::SmallVector<Selector, 16> ClassMethodSels; 1138193326Sed llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; 1139198092Srdivacky for (ObjCCategoryImplDecl::classmeth_iterator 1140195341Sed iter = OCD->classmeth_begin(), endIter = OCD->classmeth_end(); 1141193326Sed iter != endIter ; iter++) { 1142193326Sed ClassMethodSels.push_back((*iter)->getSelector()); 1143193326Sed std::string TypeStr; 1144193326Sed CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr); 1145198092Srdivacky ClassMethodTypes.push_back(MakeConstantString(TypeStr)); 1146193326Sed } 1147193326Sed 1148193326Sed // Collect the names of referenced protocols 1149193326Sed llvm::SmallVector<std::string, 16> Protocols; 1150205219Srdivacky const ObjCCategoryDecl *CatDecl = OCD->getCategoryDecl(); 1151205219Srdivacky const ObjCList<ObjCProtocolDecl> &Protos = CatDecl->getReferencedProtocols(); 1152193326Sed for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(), 1153193326Sed E = Protos.end(); I != E; ++I) 1154193326Sed Protocols.push_back((*I)->getNameAsString()); 1155193326Sed 1156193326Sed std::vector<llvm::Constant*> Elements; 1157193326Sed Elements.push_back(MakeConstantString(CategoryName)); 1158193326Sed Elements.push_back(MakeConstantString(ClassName)); 1159198092Srdivacky // Instance method list 1160193326Sed Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( 1161193326Sed ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes, 1162193326Sed false), PtrTy)); 1163193326Sed // Class method list 1164193326Sed Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList( 1165193326Sed ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true), 1166193326Sed PtrTy)); 1167193326Sed // Protocol list 1168193326Sed Elements.push_back(llvm::ConstantExpr::getBitCast( 1169193326Sed GenerateProtocolList(Protocols), PtrTy)); 1170193326Sed Categories.push_back(llvm::ConstantExpr::getBitCast( 1171198092Srdivacky MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, 1172198092Srdivacky PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy)); 1173193326Sed} 1174193326Sed 1175198092Srdivackyllvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID, 1176198092Srdivacky llvm::SmallVectorImpl<Selector> &InstanceMethodSels, 1177198092Srdivacky llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes) { 1178198092Srdivacky ASTContext &Context = CGM.getContext(); 1179198092Srdivacky // 1180198092Srdivacky // Property metadata: name, attributes, isSynthesized, setter name, setter 1181198092Srdivacky // types, getter name, getter types. 1182198092Srdivacky llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext, 1183198092Srdivacky PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, 1184198092Srdivacky PtrToInt8Ty, NULL); 1185198092Srdivacky std::vector<llvm::Constant*> Properties; 1186198092Srdivacky 1187198092Srdivacky 1188198092Srdivacky // Add all of the property methods need adding to the method list and to the 1189198092Srdivacky // property metadata list. 1190198092Srdivacky for (ObjCImplDecl::propimpl_iterator 1191198092Srdivacky iter = OID->propimpl_begin(), endIter = OID->propimpl_end(); 1192198092Srdivacky iter != endIter ; iter++) { 1193198092Srdivacky std::vector<llvm::Constant*> Fields; 1194198092Srdivacky ObjCPropertyDecl *property = (*iter)->getPropertyDecl(); 1195204643Srdivacky ObjCPropertyImplDecl *propertyImpl = *iter; 1196204643Srdivacky bool isSynthesized = (propertyImpl->getPropertyImplementation() == 1197204643Srdivacky ObjCPropertyImplDecl::Synthesize); 1198198092Srdivacky 1199198092Srdivacky Fields.push_back(MakeConstantString(property->getNameAsString())); 1200198092Srdivacky Fields.push_back(llvm::ConstantInt::get(Int8Ty, 1201198092Srdivacky property->getPropertyAttributes())); 1202204643Srdivacky Fields.push_back(llvm::ConstantInt::get(Int8Ty, isSynthesized)); 1203198092Srdivacky if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) { 1204198092Srdivacky std::string TypeStr; 1205198092Srdivacky Context.getObjCEncodingForMethodDecl(getter,TypeStr); 1206198092Srdivacky llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); 1207204643Srdivacky if (isSynthesized) { 1208204643Srdivacky InstanceMethodTypes.push_back(TypeEncoding); 1209204643Srdivacky InstanceMethodSels.push_back(getter->getSelector()); 1210204643Srdivacky } 1211198092Srdivacky Fields.push_back(MakeConstantString(getter->getSelector().getAsString())); 1212198092Srdivacky Fields.push_back(TypeEncoding); 1213198092Srdivacky } else { 1214198092Srdivacky Fields.push_back(NULLPtr); 1215198092Srdivacky Fields.push_back(NULLPtr); 1216198092Srdivacky } 1217198092Srdivacky if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) { 1218198092Srdivacky std::string TypeStr; 1219198092Srdivacky Context.getObjCEncodingForMethodDecl(setter,TypeStr); 1220198092Srdivacky llvm::Constant *TypeEncoding = MakeConstantString(TypeStr); 1221204643Srdivacky if (isSynthesized) { 1222204643Srdivacky InstanceMethodTypes.push_back(TypeEncoding); 1223204643Srdivacky InstanceMethodSels.push_back(setter->getSelector()); 1224204643Srdivacky } 1225198092Srdivacky Fields.push_back(MakeConstantString(setter->getSelector().getAsString())); 1226198092Srdivacky Fields.push_back(TypeEncoding); 1227198092Srdivacky } else { 1228198092Srdivacky Fields.push_back(NULLPtr); 1229198092Srdivacky Fields.push_back(NULLPtr); 1230198092Srdivacky } 1231198092Srdivacky Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields)); 1232198092Srdivacky } 1233198092Srdivacky llvm::ArrayType *PropertyArrayTy = 1234198092Srdivacky llvm::ArrayType::get(PropertyMetadataTy, Properties.size()); 1235198092Srdivacky llvm::Constant *PropertyArray = llvm::ConstantArray::get(PropertyArrayTy, 1236198092Srdivacky Properties); 1237198092Srdivacky llvm::Constant* PropertyListInitFields[] = 1238198092Srdivacky {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray}; 1239198092Srdivacky 1240198092Srdivacky llvm::Constant *PropertyListInit = 1241198092Srdivacky llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false); 1242198092Srdivacky return new llvm::GlobalVariable(TheModule, PropertyListInit->getType(), false, 1243198092Srdivacky llvm::GlobalValue::InternalLinkage, PropertyListInit, 1244198092Srdivacky ".objc_property_list"); 1245198092Srdivacky} 1246198092Srdivacky 1247193326Sedvoid CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { 1248193326Sed ASTContext &Context = CGM.getContext(); 1249193326Sed 1250193326Sed // Get the superclass name. 1251198092Srdivacky const ObjCInterfaceDecl * SuperClassDecl = 1252193326Sed OID->getClassInterface()->getSuperClass(); 1253193326Sed std::string SuperClassName; 1254194613Sed if (SuperClassDecl) { 1255193326Sed SuperClassName = SuperClassDecl->getNameAsString(); 1256194613Sed EmitClassRef(SuperClassName); 1257194613Sed } 1258193326Sed 1259193326Sed // Get the class name 1260193326Sed ObjCInterfaceDecl *ClassDecl = 1261193326Sed const_cast<ObjCInterfaceDecl *>(OID->getClassInterface()); 1262193326Sed std::string ClassName = ClassDecl->getNameAsString(); 1263194613Sed // Emit the symbol that is used to generate linker errors if this class is 1264194613Sed // referenced in other modules but not declared. 1265195341Sed std::string classSymbolName = "__objc_class_name_" + ClassName; 1266198092Srdivacky if (llvm::GlobalVariable *symbol = 1267195341Sed TheModule.getGlobalVariable(classSymbolName)) { 1268195341Sed symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0)); 1269195341Sed } else { 1270198092Srdivacky new llvm::GlobalVariable(TheModule, LongTy, false, 1271198092Srdivacky llvm::GlobalValue::ExternalLinkage, llvm::ConstantInt::get(LongTy, 0), 1272198092Srdivacky classSymbolName); 1273195341Sed } 1274198092Srdivacky 1275193326Sed // Get the size of instances. 1276193326Sed int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8; 1277193326Sed 1278193326Sed // Collect information about instance variables. 1279193326Sed llvm::SmallVector<llvm::Constant*, 16> IvarNames; 1280193326Sed llvm::SmallVector<llvm::Constant*, 16> IvarTypes; 1281193326Sed llvm::SmallVector<llvm::Constant*, 16> IvarOffsets; 1282198092Srdivacky 1283198092Srdivacky std::vector<llvm::Constant*> IvarOffsetValues; 1284198092Srdivacky 1285198092Srdivacky int superInstanceSize = !SuperClassDecl ? 0 : 1286193326Sed Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize() / 8; 1287193326Sed // For non-fragile ivars, set the instance size to 0 - {the size of just this 1288193326Sed // class}. The runtime will then set this to the correct value on load. 1289193326Sed if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { 1290193326Sed instanceSize = 0 - (instanceSize - superInstanceSize); 1291193326Sed } 1292193326Sed for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(), 1293193326Sed endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) { 1294193326Sed // Store the name 1295198092Srdivacky IvarNames.push_back(MakeConstantString((*iter)->getNameAsString())); 1296193326Sed // Get the type encoding for this ivar 1297193326Sed std::string TypeStr; 1298193326Sed Context.getObjCEncodingForType((*iter)->getType(), TypeStr); 1299198092Srdivacky IvarTypes.push_back(MakeConstantString(TypeStr)); 1300193326Sed // Get the offset 1301198092Srdivacky uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, ClassDecl, *iter); 1302199482Srdivacky uint64_t Offset = BaseOffset; 1303193326Sed if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { 1304198092Srdivacky Offset = BaseOffset - superInstanceSize; 1305193326Sed } 1306193326Sed IvarOffsets.push_back( 1307198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset)); 1308198092Srdivacky IvarOffsetValues.push_back(new llvm::GlobalVariable(TheModule, IntTy, 1309198092Srdivacky false, llvm::GlobalValue::ExternalLinkage, 1310198092Srdivacky llvm::ConstantInt::get(IntTy, BaseOffset), 1311198092Srdivacky "__objc_ivar_offset_value_" + ClassName +"." + 1312198092Srdivacky (*iter)->getNameAsString())); 1313193326Sed } 1314198092Srdivacky llvm::Constant *IvarOffsetArrayInit = 1315198092Srdivacky llvm::ConstantArray::get(llvm::ArrayType::get(PtrToIntTy, 1316198092Srdivacky IvarOffsetValues.size()), IvarOffsetValues); 1317198092Srdivacky llvm::GlobalVariable *IvarOffsetArray = new llvm::GlobalVariable(TheModule, 1318198092Srdivacky IvarOffsetArrayInit->getType(), false, 1319198092Srdivacky llvm::GlobalValue::InternalLinkage, IvarOffsetArrayInit, 1320198092Srdivacky ".ivar.offsets"); 1321193326Sed 1322193326Sed // Collect information about instance methods 1323193326Sed llvm::SmallVector<Selector, 16> InstanceMethodSels; 1324193326Sed llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; 1325198092Srdivacky for (ObjCImplementationDecl::instmeth_iterator 1326195341Sed iter = OID->instmeth_begin(), endIter = OID->instmeth_end(); 1327193326Sed iter != endIter ; iter++) { 1328193326Sed InstanceMethodSels.push_back((*iter)->getSelector()); 1329193326Sed std::string TypeStr; 1330193326Sed Context.getObjCEncodingForMethodDecl((*iter),TypeStr); 1331198092Srdivacky InstanceMethodTypes.push_back(MakeConstantString(TypeStr)); 1332193326Sed } 1333193326Sed 1334198092Srdivacky llvm::Constant *Properties = GeneratePropertyList(OID, InstanceMethodSels, 1335198092Srdivacky InstanceMethodTypes); 1336198092Srdivacky 1337198092Srdivacky 1338193326Sed // Collect information about class methods 1339193326Sed llvm::SmallVector<Selector, 16> ClassMethodSels; 1340193326Sed llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; 1341193326Sed for (ObjCImplementationDecl::classmeth_iterator 1342195341Sed iter = OID->classmeth_begin(), endIter = OID->classmeth_end(); 1343193326Sed iter != endIter ; iter++) { 1344193326Sed ClassMethodSels.push_back((*iter)->getSelector()); 1345193326Sed std::string TypeStr; 1346193326Sed Context.getObjCEncodingForMethodDecl((*iter),TypeStr); 1347198092Srdivacky ClassMethodTypes.push_back(MakeConstantString(TypeStr)); 1348193326Sed } 1349193326Sed // Collect the names of referenced protocols 1350193326Sed llvm::SmallVector<std::string, 16> Protocols; 1351193326Sed const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols(); 1352193326Sed for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(), 1353193326Sed E = Protos.end(); I != E; ++I) 1354193326Sed Protocols.push_back((*I)->getNameAsString()); 1355193326Sed 1356193326Sed 1357193326Sed 1358193326Sed // Get the superclass pointer. 1359193326Sed llvm::Constant *SuperClass; 1360193326Sed if (!SuperClassName.empty()) { 1361193326Sed SuperClass = MakeConstantString(SuperClassName, ".super_class_name"); 1362193326Sed } else { 1363193326Sed SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty); 1364193326Sed } 1365193326Sed // Empty vector used to construct empty method lists 1366193326Sed llvm::SmallVector<llvm::Constant*, 1> empty; 1367193326Sed // Generate the method and instance variable lists 1368193326Sed llvm::Constant *MethodList = GenerateMethodList(ClassName, "", 1369193326Sed InstanceMethodSels, InstanceMethodTypes, false); 1370193326Sed llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "", 1371193326Sed ClassMethodSels, ClassMethodTypes, true); 1372193326Sed llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes, 1373193326Sed IvarOffsets); 1374198092Srdivacky // Irrespective of whether we are compiling for a fragile or non-fragile ABI, 1375198092Srdivacky // we emit a symbol containing the offset for each ivar in the class. This 1376198092Srdivacky // allows code compiled for the non-Fragile ABI to inherit from code compiled 1377198092Srdivacky // for the legacy ABI, without causing problems. The converse is also 1378198092Srdivacky // possible, but causes all ivar accesses to be fragile. 1379198092Srdivacky int i = 0; 1380198092Srdivacky // Offset pointer for getting at the correct field in the ivar list when 1381198092Srdivacky // setting up the alias. These are: The base address for the global, the 1382198092Srdivacky // ivar array (second field), the ivar in this list (set for each ivar), and 1383198092Srdivacky // the offset (third field in ivar structure) 1384198092Srdivacky const llvm::Type *IndexTy = llvm::Type::getInt32Ty(VMContext); 1385198092Srdivacky llvm::Constant *offsetPointerIndexes[] = {Zeros[0], 1386198092Srdivacky llvm::ConstantInt::get(IndexTy, 1), 0, 1387198092Srdivacky llvm::ConstantInt::get(IndexTy, 2) }; 1388198092Srdivacky 1389198092Srdivacky for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(), 1390198092Srdivacky endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) { 1391198092Srdivacky const std::string Name = "__objc_ivar_offset_" + ClassName + '.' 1392198092Srdivacky +(*iter)->getNameAsString(); 1393198092Srdivacky offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, i++); 1394198092Srdivacky // Get the correct ivar field 1395198092Srdivacky llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr( 1396198092Srdivacky IvarList, offsetPointerIndexes, 4); 1397198092Srdivacky // Get the existing alias, if one exists. 1398198092Srdivacky llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name); 1399198092Srdivacky if (offset) { 1400198092Srdivacky offset->setInitializer(offsetValue); 1401198092Srdivacky // If this is the real definition, change its linkage type so that 1402198092Srdivacky // different modules will use this one, rather than their private 1403198092Srdivacky // copy. 1404198092Srdivacky offset->setLinkage(llvm::GlobalValue::ExternalLinkage); 1405198092Srdivacky } else { 1406198092Srdivacky // Add a new alias if there isn't one already. 1407198092Srdivacky offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(), 1408198092Srdivacky false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name); 1409198092Srdivacky } 1410198092Srdivacky } 1411193326Sed //Generate metaclass for class methods 1412193326Sed llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr, 1413199482Srdivacky NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList( 1414198092Srdivacky empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr, NULLPtr); 1415193326Sed 1416193326Sed // Generate the class structure 1417193326Sed llvm::Constant *ClassStruct = 1418198092Srdivacky GenerateClassStructure(MetaClassStruct, SuperClass, 0x11L, 1419193326Sed ClassName.c_str(), 0, 1420193326Sed llvm::ConstantInt::get(LongTy, instanceSize), IvarList, 1421198092Srdivacky MethodList, GenerateProtocolList(Protocols), IvarOffsetArray, 1422198092Srdivacky Properties); 1423193326Sed 1424193326Sed // Resolve the class aliases, if they exist. 1425193326Sed if (ClassPtrAlias) { 1426193326Sed ClassPtrAlias->setAliasee( 1427193326Sed llvm::ConstantExpr::getBitCast(ClassStruct, IdTy)); 1428193326Sed ClassPtrAlias = 0; 1429193326Sed } 1430193326Sed if (MetaClassPtrAlias) { 1431193326Sed MetaClassPtrAlias->setAliasee( 1432193326Sed llvm::ConstantExpr::getBitCast(MetaClassStruct, IdTy)); 1433193326Sed MetaClassPtrAlias = 0; 1434193326Sed } 1435193326Sed 1436193326Sed // Add class structure to list to be added to the symtab later 1437193326Sed ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty); 1438193326Sed Classes.push_back(ClassStruct); 1439193326Sed} 1440193326Sed 1441195099Sed 1442198092Srdivackyllvm::Function *CGObjCGNU::ModuleInitFunction() { 1443193326Sed // Only emit an ObjC load function if no Objective-C stuff has been called 1444193326Sed if (Classes.empty() && Categories.empty() && ConstantStrings.empty() && 1445193326Sed ExistingProtocols.empty() && TypedSelectors.empty() && 1446193326Sed UntypedSelectors.empty()) 1447193326Sed return NULL; 1448193326Sed 1449198092Srdivacky // Add all referenced protocols to a category. 1450198092Srdivacky GenerateProtocolHolderCategory(); 1451198092Srdivacky 1452193326Sed const llvm::StructType *SelStructTy = dyn_cast<llvm::StructType>( 1453193326Sed SelectorTy->getElementType()); 1454193326Sed const llvm::Type *SelStructPtrTy = SelectorTy; 1455193326Sed bool isSelOpaque = false; 1456193326Sed if (SelStructTy == 0) { 1457198092Srdivacky SelStructTy = llvm::StructType::get(VMContext, PtrToInt8Ty, 1458198092Srdivacky PtrToInt8Ty, NULL); 1459193326Sed SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy); 1460193326Sed isSelOpaque = true; 1461193326Sed } 1462193326Sed 1463193326Sed // Name the ObjC types to make the IR a bit easier to read 1464193326Sed TheModule.addTypeName(".objc_selector", SelStructPtrTy); 1465193326Sed TheModule.addTypeName(".objc_id", IdTy); 1466193326Sed TheModule.addTypeName(".objc_imp", IMPTy); 1467193326Sed 1468193326Sed std::vector<llvm::Constant*> Elements; 1469193326Sed llvm::Constant *Statics = NULLPtr; 1470193326Sed // Generate statics list: 1471193326Sed if (ConstantStrings.size()) { 1472193326Sed llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty, 1473193326Sed ConstantStrings.size() + 1); 1474193326Sed ConstantStrings.push_back(NULLPtr); 1475198092Srdivacky 1476199990Srdivacky llvm::StringRef StringClass = CGM.getLangOptions().ObjCConstantStringClass; 1477199990Srdivacky if (StringClass.empty()) StringClass = "NXConstantString"; 1478198092Srdivacky Elements.push_back(MakeConstantString(StringClass, 1479198092Srdivacky ".objc_static_class_name")); 1480193326Sed Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy, 1481193326Sed ConstantStrings)); 1482198092Srdivacky llvm::StructType *StaticsListTy = 1483198092Srdivacky llvm::StructType::get(VMContext, PtrToInt8Ty, StaticsArrayTy, NULL); 1484198092Srdivacky llvm::Type *StaticsListPtrTy = 1485198092Srdivacky llvm::PointerType::getUnqual(StaticsListTy); 1486193326Sed Statics = MakeGlobal(StaticsListTy, Elements, ".objc_statics"); 1487193326Sed llvm::ArrayType *StaticsListArrayTy = 1488193326Sed llvm::ArrayType::get(StaticsListPtrTy, 2); 1489193326Sed Elements.clear(); 1490193326Sed Elements.push_back(Statics); 1491193326Sed Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy)); 1492193326Sed Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr"); 1493193326Sed Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy); 1494193326Sed } 1495193326Sed // Array of classes, categories, and constant objects 1496193326Sed llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty, 1497193326Sed Classes.size() + Categories.size() + 2); 1498198092Srdivacky llvm::StructType *SymTabTy = llvm::StructType::get(VMContext, 1499198092Srdivacky LongTy, SelStructPtrTy, 1500198092Srdivacky llvm::Type::getInt16Ty(VMContext), 1501198092Srdivacky llvm::Type::getInt16Ty(VMContext), 1502193326Sed ClassListTy, NULL); 1503193326Sed 1504193326Sed Elements.clear(); 1505193326Sed // Pointer to an array of selectors used in this module. 1506193326Sed std::vector<llvm::Constant*> Selectors; 1507193326Sed for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator 1508193326Sed iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end(); 1509193326Sed iter != iterEnd ; ++iter) { 1510198092Srdivacky Elements.push_back(ExportUniqueString(iter->first.first, ".objc_sel_name")); 1511193326Sed Elements.push_back(MakeConstantString(iter->first.second, 1512193326Sed ".objc_sel_types")); 1513193326Sed Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); 1514193326Sed Elements.clear(); 1515193326Sed } 1516193326Sed for (llvm::StringMap<llvm::GlobalAlias*>::iterator 1517193326Sed iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end(); 1518193326Sed iter != iterEnd; ++iter) { 1519193326Sed Elements.push_back( 1520198092Srdivacky ExportUniqueString(iter->getKeyData(), ".objc_sel_name")); 1521193326Sed Elements.push_back(NULLPtr); 1522193326Sed Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); 1523193326Sed Elements.clear(); 1524193326Sed } 1525193326Sed Elements.push_back(NULLPtr); 1526193326Sed Elements.push_back(NULLPtr); 1527193326Sed Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements)); 1528193326Sed Elements.clear(); 1529193326Sed // Number of static selectors 1530193326Sed Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() )); 1531193326Sed llvm::Constant *SelectorList = MakeGlobal( 1532193326Sed llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors, 1533193326Sed ".objc_selector_list"); 1534198092Srdivacky Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList, 1535193326Sed SelStructPtrTy)); 1536193326Sed 1537193326Sed // Now that all of the static selectors exist, create pointers to them. 1538193326Sed int index = 0; 1539193326Sed for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator 1540193326Sed iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end(); 1541193326Sed iter != iterEnd; ++iter) { 1542193326Sed llvm::Constant *Idxs[] = {Zeros[0], 1543198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]}; 1544198092Srdivacky llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy, 1545193326Sed true, llvm::GlobalValue::InternalLinkage, 1546193326Sed llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), 1547198092Srdivacky ".objc_sel_ptr"); 1548193326Sed // If selectors are defined as an opaque type, cast the pointer to this 1549193326Sed // type. 1550193326Sed if (isSelOpaque) { 1551193326Sed SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, 1552193326Sed llvm::PointerType::getUnqual(SelectorTy)); 1553193326Sed } 1554193326Sed (*iter).second->setAliasee(SelPtr); 1555193326Sed } 1556193326Sed for (llvm::StringMap<llvm::GlobalAlias*>::iterator 1557193326Sed iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end(); 1558193326Sed iter != iterEnd; iter++) { 1559193326Sed llvm::Constant *Idxs[] = {Zeros[0], 1560198092Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]}; 1561198092Srdivacky llvm::Constant *SelPtr = new llvm::GlobalVariable 1562198092Srdivacky (TheModule, SelStructPtrTy, 1563198092Srdivacky true, llvm::GlobalValue::InternalLinkage, 1564198092Srdivacky llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2), 1565198092Srdivacky ".objc_sel_ptr"); 1566193326Sed // If selectors are defined as an opaque type, cast the pointer to this 1567193326Sed // type. 1568193326Sed if (isSelOpaque) { 1569193326Sed SelPtr = llvm::ConstantExpr::getBitCast(SelPtr, 1570193326Sed llvm::PointerType::getUnqual(SelectorTy)); 1571193326Sed } 1572193326Sed (*iter).second->setAliasee(SelPtr); 1573193326Sed } 1574193326Sed // Number of classes defined. 1575198092Srdivacky Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext), 1576193326Sed Classes.size())); 1577193326Sed // Number of categories defined 1578198092Srdivacky Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext), 1579193326Sed Categories.size())); 1580193326Sed // Create an array of classes, then categories, then static object instances 1581193326Sed Classes.insert(Classes.end(), Categories.begin(), Categories.end()); 1582193326Sed // NULL-terminated list of static object instances (mainly constant strings) 1583193326Sed Classes.push_back(Statics); 1584193326Sed Classes.push_back(NULLPtr); 1585193326Sed llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes); 1586193326Sed Elements.push_back(ClassList); 1587198092Srdivacky // Construct the symbol table 1588193326Sed llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements); 1589193326Sed 1590193326Sed // The symbol table is contained in a module which has some version-checking 1591193326Sed // constants 1592198092Srdivacky llvm::StructType * ModuleTy = llvm::StructType::get(VMContext, LongTy, LongTy, 1593193326Sed PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL); 1594193326Sed Elements.clear(); 1595193326Sed // Runtime version used for compatibility checking. 1596193326Sed if (CGM.getContext().getLangOptions().ObjCNonFragileABI) { 1597198092Srdivacky Elements.push_back(llvm::ConstantInt::get(LongTy, 1598193326Sed NonFragileRuntimeVersion)); 1599193326Sed } else { 1600193326Sed Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion)); 1601193326Sed } 1602193326Sed // sizeof(ModuleTy) 1603203955Srdivacky llvm::TargetData td(&TheModule); 1604198092Srdivacky Elements.push_back(llvm::ConstantInt::get(LongTy, 1605198092Srdivacky td.getTypeSizeInBits(ModuleTy)/8)); 1606193326Sed //FIXME: Should be the path to the file where this module was declared 1607193326Sed Elements.push_back(NULLPtr); 1608193326Sed Elements.push_back(SymTab); 1609193326Sed llvm::Value *Module = MakeGlobal(ModuleTy, Elements); 1610193326Sed 1611193326Sed // Create the load function calling the runtime entry point with the module 1612193326Sed // structure 1613193326Sed llvm::Function * LoadFunction = llvm::Function::Create( 1614198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false), 1615193326Sed llvm::GlobalValue::InternalLinkage, ".objc_load_function", 1616193326Sed &TheModule); 1617198092Srdivacky llvm::BasicBlock *EntryBB = 1618198092Srdivacky llvm::BasicBlock::Create(VMContext, "entry", LoadFunction); 1619198092Srdivacky CGBuilderTy Builder(VMContext); 1620193326Sed Builder.SetInsertPoint(EntryBB); 1621193326Sed 1622193326Sed std::vector<const llvm::Type*> Params(1, 1623193326Sed llvm::PointerType::getUnqual(ModuleTy)); 1624193326Sed llvm::Value *Register = CGM.CreateRuntimeFunction(llvm::FunctionType::get( 1625198092Srdivacky llvm::Type::getVoidTy(VMContext), Params, true), "__objc_exec_class"); 1626193326Sed Builder.CreateCall(Register, Module); 1627193326Sed Builder.CreateRetVoid(); 1628193326Sed 1629193326Sed return LoadFunction; 1630193326Sed} 1631193326Sed 1632193326Sedllvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD, 1633198092Srdivacky const ObjCContainerDecl *CD) { 1634198092Srdivacky const ObjCCategoryImplDecl *OCD = 1635193326Sed dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext()); 1636193326Sed std::string CategoryName = OCD ? OCD->getNameAsString() : ""; 1637205408Srdivacky std::string ClassName = CD->getName(); 1638193326Sed std::string MethodName = OMD->getSelector().getAsString(); 1639193326Sed bool isClassMethod = !OMD->isInstanceMethod(); 1640193326Sed 1641193326Sed CodeGenTypes &Types = CGM.getTypes(); 1642198092Srdivacky const llvm::FunctionType *MethodTy = 1643193326Sed Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic()); 1644193326Sed std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName, 1645193326Sed MethodName, isClassMethod); 1646193326Sed 1647198092Srdivacky llvm::Function *Method 1648198092Srdivacky = llvm::Function::Create(MethodTy, 1649198092Srdivacky llvm::GlobalValue::InternalLinkage, 1650198092Srdivacky FunctionName, 1651198092Srdivacky &TheModule); 1652193326Sed return Method; 1653193326Sed} 1654193326Sed 1655193326Sedllvm::Function *CGObjCGNU::GetPropertyGetFunction() { 1656198092Srdivacky std::vector<const llvm::Type*> Params; 1657198092Srdivacky const llvm::Type *BoolTy = 1658198092Srdivacky CGM.getTypes().ConvertType(CGM.getContext().BoolTy); 1659198092Srdivacky Params.push_back(IdTy); 1660198092Srdivacky Params.push_back(SelectorTy); 1661198092Srdivacky // FIXME: Using LongTy for ptrdiff_t is probably broken on Win64 1662198092Srdivacky Params.push_back(LongTy); 1663198092Srdivacky Params.push_back(BoolTy); 1664198092Srdivacky // void objc_getProperty (id, SEL, ptrdiff_t, bool) 1665198092Srdivacky const llvm::FunctionType *FTy = 1666198092Srdivacky llvm::FunctionType::get(IdTy, Params, false); 1667198092Srdivacky return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy, 1668198092Srdivacky "objc_getProperty")); 1669193326Sed} 1670193326Sed 1671193326Sedllvm::Function *CGObjCGNU::GetPropertySetFunction() { 1672198092Srdivacky std::vector<const llvm::Type*> Params; 1673198092Srdivacky const llvm::Type *BoolTy = 1674198092Srdivacky CGM.getTypes().ConvertType(CGM.getContext().BoolTy); 1675198092Srdivacky Params.push_back(IdTy); 1676198092Srdivacky Params.push_back(SelectorTy); 1677198092Srdivacky // FIXME: Using LongTy for ptrdiff_t is probably broken on Win64 1678198092Srdivacky Params.push_back(LongTy); 1679198092Srdivacky Params.push_back(IdTy); 1680198092Srdivacky Params.push_back(BoolTy); 1681198092Srdivacky Params.push_back(BoolTy); 1682198092Srdivacky // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool) 1683198092Srdivacky const llvm::FunctionType *FTy = 1684198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); 1685198092Srdivacky return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy, 1686198092Srdivacky "objc_setProperty")); 1687193326Sed} 1688193326Sed 1689198092Srdivackyllvm::Constant *CGObjCGNU::EnumerationMutationFunction() { 1690198092Srdivacky CodeGen::CodeGenTypes &Types = CGM.getTypes(); 1691198092Srdivacky ASTContext &Ctx = CGM.getContext(); 1692198092Srdivacky // void objc_enumerationMutation (id) 1693204643Srdivacky llvm::SmallVector<CanQualType,1> Params; 1694198092Srdivacky Params.push_back(ASTIdTy); 1695198092Srdivacky const llvm::FunctionType *FTy = 1696203955Srdivacky Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params, 1697203955Srdivacky CC_Default, false), false); 1698198092Srdivacky return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); 1699193326Sed} 1700193326Sed 1701193326Sedvoid CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, 1702193326Sed const Stmt &S) { 1703193326Sed // Pointer to the personality function 1704193326Sed llvm::Constant *Personality = 1705198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext), 1706195341Sed true), 1707193326Sed "__gnu_objc_personality_v0"); 1708193326Sed Personality = llvm::ConstantExpr::getBitCast(Personality, PtrTy); 1709193326Sed std::vector<const llvm::Type*> Params; 1710193326Sed Params.push_back(PtrTy); 1711193326Sed llvm::Value *RethrowFn = 1712198092Srdivacky CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 1713202379Srdivacky Params, false), "_Unwind_Resume"); 1714193326Sed 1715193326Sed bool isTry = isa<ObjCAtTryStmt>(S); 1716193326Sed llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); 1717193326Sed llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest(); 1718193326Sed llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); 1719193326Sed llvm::BasicBlock *CatchInCatch = CGF.createBasicBlock("catch.rethrow"); 1720193326Sed llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally"); 1721193326Sed llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw"); 1722193326Sed llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end"); 1723193326Sed 1724201361Srdivacky // @synchronized() 1725193326Sed if (!isTry) { 1726193326Sed std::vector<const llvm::Type*> Args(1, IdTy); 1727193326Sed llvm::FunctionType *FTy = 1728198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 1729193326Sed llvm::Value *SyncEnter = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); 1730198092Srdivacky llvm::Value *SyncArg = 1731193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 1732193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy); 1733193326Sed CGF.Builder.CreateCall(SyncEnter, SyncArg); 1734193326Sed } 1735193326Sed 1736193326Sed 1737193326Sed // Push an EH context entry, used for handling rethrows and jumps 1738193326Sed // through finally. 1739193326Sed CGF.PushCleanupBlock(FinallyBlock); 1740193326Sed 1741193326Sed // Emit the statements in the @try {} block 1742193326Sed CGF.setInvokeDest(TryHandler); 1743193326Sed 1744193326Sed CGF.EmitBlock(TryBlock); 1745198092Srdivacky CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody() 1746193326Sed : cast<ObjCAtSynchronizedStmt>(S).getSynchBody()); 1747193326Sed 1748193326Sed // Jump to @finally if there is no exception 1749193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 1750193326Sed 1751193326Sed // Emit the handlers 1752193326Sed CGF.EmitBlock(TryHandler); 1753193326Sed 1754193326Sed // Get the correct versions of the exception handling intrinsics 1755198092Srdivacky llvm::Value *llvm_eh_exception = 1756193326Sed CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 1757198092Srdivacky llvm::Value *llvm_eh_selector = 1758198092Srdivacky CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 1759198092Srdivacky llvm::Value *llvm_eh_typeid_for = 1760198092Srdivacky CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); 1761193326Sed 1762193326Sed // Exception object 1763193326Sed llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 1764193326Sed llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow"); 1765193326Sed 1766193326Sed llvm::SmallVector<llvm::Value*, 8> ESelArgs; 1767193326Sed llvm::SmallVector<std::pair<const ParmVarDecl*, const Stmt*>, 8> Handlers; 1768193326Sed 1769193326Sed ESelArgs.push_back(Exc); 1770193326Sed ESelArgs.push_back(Personality); 1771193326Sed 1772193326Sed bool HasCatchAll = false; 1773193326Sed // Only @try blocks are allowed @catch blocks, but both can have @finally 1774193326Sed if (isTry) { 1775193326Sed if (const ObjCAtCatchStmt* CatchStmt = 1776193326Sed cast<ObjCAtTryStmt>(S).getCatchStmts()) { 1777193326Sed CGF.setInvokeDest(CatchInCatch); 1778193326Sed 1779193326Sed for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) { 1780193326Sed const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl(); 1781198092Srdivacky Handlers.push_back(std::make_pair(CatchDecl, 1782198092Srdivacky CatchStmt->getCatchBody())); 1783193326Sed 1784193326Sed // @catch() and @catch(id) both catch any ObjC exception 1785198092Srdivacky if (!CatchDecl || CatchDecl->getType()->isObjCIdType() 1786193326Sed || CatchDecl->getType()->isObjCQualifiedIdType()) { 1787193326Sed // Use i8* null here to signal this is a catch all, not a cleanup. 1788193326Sed ESelArgs.push_back(NULLPtr); 1789193326Sed HasCatchAll = true; 1790193326Sed // No further catches after this one will ever by reached 1791193326Sed break; 1792198092Srdivacky } 1793193326Sed 1794193326Sed // All other types should be Objective-C interface pointer types. 1795198092Srdivacky const ObjCObjectPointerType *OPT = 1796198092Srdivacky CatchDecl->getType()->getAs<ObjCObjectPointerType>(); 1797198092Srdivacky assert(OPT && "Invalid @catch type."); 1798198092Srdivacky const ObjCInterfaceType *IT = 1799198092Srdivacky OPT->getPointeeType()->getAs<ObjCInterfaceType>(); 1800193326Sed assert(IT && "Invalid @catch type."); 1801193326Sed llvm::Value *EHType = 1802193326Sed MakeConstantString(IT->getDecl()->getNameAsString()); 1803193326Sed ESelArgs.push_back(EHType); 1804193326Sed } 1805193326Sed } 1806193326Sed } 1807193326Sed 1808193326Sed // We use a cleanup unless there was already a catch all. 1809193326Sed if (!HasCatchAll) { 1810198092Srdivacky ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); 1811193326Sed Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0)); 1812193326Sed } 1813193326Sed 1814193326Sed // Find which handler was matched. 1815193326Sed llvm::Value *ESelector = CGF.Builder.CreateCall(llvm_eh_selector, 1816193326Sed ESelArgs.begin(), ESelArgs.end(), "selector"); 1817193326Sed 1818193326Sed for (unsigned i = 0, e = Handlers.size(); i != e; ++i) { 1819193326Sed const ParmVarDecl *CatchParam = Handlers[i].first; 1820193326Sed const Stmt *CatchBody = Handlers[i].second; 1821193326Sed 1822193326Sed llvm::BasicBlock *Next = 0; 1823193326Sed 1824193326Sed // The last handler always matches. 1825193326Sed if (i + 1 != e) { 1826193326Sed assert(CatchParam && "Only last handler can be a catch all."); 1827193326Sed 1828193326Sed // Test whether this block matches the type for the selector and branch 1829193326Sed // to Match if it does, or to the next BB if it doesn't. 1830193326Sed llvm::BasicBlock *Match = CGF.createBasicBlock("match"); 1831193326Sed Next = CGF.createBasicBlock("catch.next"); 1832193326Sed llvm::Value *Id = CGF.Builder.CreateCall(llvm_eh_typeid_for, 1833193326Sed CGF.Builder.CreateBitCast(ESelArgs[i+2], PtrTy)); 1834193326Sed CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(ESelector, Id), Match, 1835193326Sed Next); 1836193326Sed 1837193326Sed CGF.EmitBlock(Match); 1838193326Sed } 1839198092Srdivacky 1840193326Sed if (CatchBody) { 1841193326Sed llvm::Value *ExcObject = CGF.Builder.CreateBitCast(Exc, 1842193326Sed CGF.ConvertType(CatchParam->getType())); 1843198092Srdivacky 1844193326Sed // Bind the catch parameter if it exists. 1845193326Sed if (CatchParam) { 1846193326Sed // CatchParam is a ParmVarDecl because of the grammar 1847193326Sed // construction used to handle this, but for codegen purposes 1848193326Sed // we treat this as a local decl. 1849193326Sed CGF.EmitLocalBlockVarDecl(*CatchParam); 1850193326Sed CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(CatchParam)); 1851193326Sed } 1852193326Sed 1853193326Sed CGF.ObjCEHValueStack.push_back(ExcObject); 1854193326Sed CGF.EmitStmt(CatchBody); 1855193326Sed CGF.ObjCEHValueStack.pop_back(); 1856193326Sed 1857193326Sed CGF.EmitBranchThroughCleanup(FinallyEnd); 1858193326Sed 1859193326Sed if (Next) 1860193326Sed CGF.EmitBlock(Next); 1861193326Sed } else { 1862193326Sed assert(!Next && "catchup should be last handler."); 1863193326Sed 1864193326Sed CGF.Builder.CreateStore(Exc, RethrowPtr); 1865193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 1866193326Sed } 1867193326Sed } 1868193326Sed // The @finally block is a secondary landing pad for any exceptions thrown in 1869193326Sed // @catch() blocks 1870193326Sed CGF.EmitBlock(CatchInCatch); 1871193326Sed Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 1872193326Sed ESelArgs.clear(); 1873193326Sed ESelArgs.push_back(Exc); 1874193326Sed ESelArgs.push_back(Personality); 1875201361Srdivacky // If there is a @catch or @finally clause in outside of this one then we 1876201361Srdivacky // need to make sure that we catch and rethrow it. 1877201361Srdivacky if (PrevLandingPad) { 1878201361Srdivacky ESelArgs.push_back(NULLPtr); 1879201361Srdivacky } else { 1880201361Srdivacky ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0)); 1881201361Srdivacky } 1882193326Sed CGF.Builder.CreateCall(llvm_eh_selector, ESelArgs.begin(), ESelArgs.end(), 1883193326Sed "selector"); 1884193326Sed CGF.Builder.CreateCall(llvm_eh_typeid_for, 1885193326Sed CGF.Builder.CreateIntToPtr(ESelArgs[2], PtrTy)); 1886193326Sed CGF.Builder.CreateStore(Exc, RethrowPtr); 1887193326Sed CGF.EmitBranchThroughCleanup(FinallyRethrow); 1888193326Sed 1889193326Sed CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock(); 1890193326Sed 1891193326Sed CGF.setInvokeDest(PrevLandingPad); 1892193326Sed 1893193326Sed CGF.EmitBlock(FinallyBlock); 1894193326Sed 1895193326Sed 1896193326Sed if (isTry) { 1897198092Srdivacky if (const ObjCAtFinallyStmt* FinallyStmt = 1898193326Sed cast<ObjCAtTryStmt>(S).getFinallyStmt()) 1899193326Sed CGF.EmitStmt(FinallyStmt->getFinallyBody()); 1900193326Sed } else { 1901193326Sed // Emit 'objc_sync_exit(expr)' as finally's sole statement for 1902193326Sed // @synchronized. 1903193326Sed std::vector<const llvm::Type*> Args(1, IdTy); 1904193326Sed llvm::FunctionType *FTy = 1905198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 1906193326Sed llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); 1907198092Srdivacky llvm::Value *SyncArg = 1908193326Sed CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr()); 1909193326Sed SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy); 1910193326Sed CGF.Builder.CreateCall(SyncExit, SyncArg); 1911193326Sed } 1912193326Sed 1913193326Sed if (Info.SwitchBlock) 1914193326Sed CGF.EmitBlock(Info.SwitchBlock); 1915193326Sed if (Info.EndBlock) 1916193326Sed CGF.EmitBlock(Info.EndBlock); 1917193326Sed 1918193326Sed // Branch around the rethrow code. 1919193326Sed CGF.EmitBranch(FinallyEnd); 1920193326Sed 1921193326Sed CGF.EmitBlock(FinallyRethrow); 1922198092Srdivacky 1923201361Srdivacky llvm::Value *ExceptionObject = CGF.Builder.CreateLoad(RethrowPtr); 1924201361Srdivacky llvm::BasicBlock *UnwindBB = CGF.getInvokeDest(); 1925201361Srdivacky if (!UnwindBB) { 1926201361Srdivacky CGF.Builder.CreateCall(RethrowFn, ExceptionObject); 1927201361Srdivacky // Exception always thrown, next instruction is never reached. 1928201361Srdivacky CGF.Builder.CreateUnreachable(); 1929201361Srdivacky } else { 1930201361Srdivacky // If there is a @catch block outside this scope, we invoke instead of 1931201361Srdivacky // calling because we may return to this function. This is very slow, but 1932201361Srdivacky // some people still do it. It would be nice to add an optimised path for 1933201361Srdivacky // this. 1934201361Srdivacky CGF.Builder.CreateInvoke(RethrowFn, UnwindBB, UnwindBB, &ExceptionObject, 1935201361Srdivacky &ExceptionObject+1); 1936201361Srdivacky } 1937201361Srdivacky 1938193326Sed CGF.EmitBlock(FinallyEnd); 1939193326Sed} 1940193326Sed 1941193326Sedvoid CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, 1942193326Sed const ObjCAtThrowStmt &S) { 1943193326Sed llvm::Value *ExceptionAsObject; 1944193326Sed 1945193326Sed std::vector<const llvm::Type*> Args(1, IdTy); 1946193326Sed llvm::FunctionType *FTy = 1947198092Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false); 1948198092Srdivacky llvm::Value *ThrowFn = 1949193326Sed CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); 1950198092Srdivacky 1951193326Sed if (const Expr *ThrowExpr = S.getThrowExpr()) { 1952193326Sed llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr); 1953193326Sed ExceptionAsObject = Exception; 1954193326Sed } else { 1955198092Srdivacky assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && 1956193326Sed "Unexpected rethrow outside @catch block."); 1957193326Sed ExceptionAsObject = CGF.ObjCEHValueStack.back(); 1958193326Sed } 1959193326Sed ExceptionAsObject = 1960193326Sed CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy, "tmp"); 1961198092Srdivacky 1962193326Sed // Note: This may have to be an invoke, if we want to support constructs like: 1963193326Sed // @try { 1964193326Sed // @throw(obj); 1965193326Sed // } 1966193326Sed // @catch(id) ... 1967193326Sed // 1968193326Sed // This is effectively turning @throw into an incredibly-expensive goto, but 1969193326Sed // it may happen as a result of inlining followed by missed optimizations, or 1970193326Sed // as a result of stupidity. 1971193326Sed llvm::BasicBlock *UnwindBB = CGF.getInvokeDest(); 1972193326Sed if (!UnwindBB) { 1973193326Sed CGF.Builder.CreateCall(ThrowFn, ExceptionAsObject); 1974193326Sed CGF.Builder.CreateUnreachable(); 1975193326Sed } else { 1976193326Sed CGF.Builder.CreateInvoke(ThrowFn, UnwindBB, UnwindBB, &ExceptionAsObject, 1977193326Sed &ExceptionAsObject+1); 1978193326Sed } 1979193326Sed // Clear the insertion point to indicate we are in unreachable code. 1980193326Sed CGF.Builder.ClearInsertionPoint(); 1981193326Sed} 1982193326Sed 1983193326Sedllvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, 1984198092Srdivacky llvm::Value *AddrWeakObj) { 1985203955Srdivacky CGBuilderTy B = CGF.Builder; 1986203955Srdivacky AddrWeakObj = EnforceType(B, AddrWeakObj, IdTy); 1987203955Srdivacky return B.CreateCall(WeakReadFn, AddrWeakObj); 1988193326Sed} 1989193326Sed 1990193326Sedvoid CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, 1991198092Srdivacky llvm::Value *src, llvm::Value *dst) { 1992203955Srdivacky CGBuilderTy B = CGF.Builder; 1993203955Srdivacky src = EnforceType(B, src, IdTy); 1994203955Srdivacky dst = EnforceType(B, dst, PtrToIdTy); 1995203955Srdivacky B.CreateCall2(WeakAssignFn, src, dst); 1996193326Sed} 1997193326Sed 1998193326Sedvoid CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, 1999198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2000203955Srdivacky CGBuilderTy B = CGF.Builder; 2001203955Srdivacky src = EnforceType(B, src, IdTy); 2002203955Srdivacky dst = EnforceType(B, dst, PtrToIdTy); 2003203955Srdivacky B.CreateCall2(GlobalAssignFn, src, dst); 2004193326Sed} 2005193326Sed 2006193326Sedvoid CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, 2007198092Srdivacky llvm::Value *src, llvm::Value *dst, 2008198092Srdivacky llvm::Value *ivarOffset) { 2009203955Srdivacky CGBuilderTy B = CGF.Builder; 2010203955Srdivacky src = EnforceType(B, src, IdTy); 2011203955Srdivacky dst = EnforceType(B, dst, PtrToIdTy); 2012203955Srdivacky B.CreateCall3(IvarAssignFn, src, dst, ivarOffset); 2013193326Sed} 2014193326Sed 2015193326Sedvoid CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, 2016198092Srdivacky llvm::Value *src, llvm::Value *dst) { 2017203955Srdivacky CGBuilderTy B = CGF.Builder; 2018203955Srdivacky src = EnforceType(B, src, IdTy); 2019203955Srdivacky dst = EnforceType(B, dst, PtrToIdTy); 2020203955Srdivacky B.CreateCall2(StrongCastAssignFn, src, dst); 2021193326Sed} 2022193326Sed 2023198092Srdivackyvoid CGObjCGNU::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, 2024198092Srdivacky llvm::Value *DestPtr, 2025198092Srdivacky llvm::Value *SrcPtr, 2026198092Srdivacky QualType Ty) { 2027203955Srdivacky CGBuilderTy B = CGF.Builder; 2028203955Srdivacky DestPtr = EnforceType(B, DestPtr, IdTy); 2029203955Srdivacky SrcPtr = EnforceType(B, SrcPtr, PtrToIdTy); 2030203955Srdivacky 2031203955Srdivacky std::pair<uint64_t, unsigned> TypeInfo = CGM.getContext().getTypeInfo(Ty); 2032203955Srdivacky unsigned long size = TypeInfo.first/8; 2033203955Srdivacky // FIXME: size_t 2034203955Srdivacky llvm::Value *N = llvm::ConstantInt::get(LongTy, size); 2035203955Srdivacky 2036203955Srdivacky B.CreateCall3(MemMoveFn, DestPtr, SrcPtr, N); 2037198092Srdivacky} 2038198092Srdivacky 2039193326Sedllvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable( 2040193326Sed const ObjCInterfaceDecl *ID, 2041193326Sed const ObjCIvarDecl *Ivar) { 2042193326Sed const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString() 2043193326Sed + '.' + Ivar->getNameAsString(); 2044193326Sed // Emit the variable and initialize it with what we think the correct value 2045193326Sed // is. This allows code compiled with non-fragile ivars to work correctly 2046193326Sed // when linked against code which isn't (most of the time). 2047198092Srdivacky llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name); 2048198092Srdivacky if (!IvarOffsetPointer) { 2049193326Sed uint64_t Offset = ComputeIvarBaseOffset(CGM, ID, Ivar); 2050193326Sed llvm::ConstantInt *OffsetGuess = 2051202379Srdivacky llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset, "ivar"); 2052198092Srdivacky // Don't emit the guess in non-PIC code because the linker will not be able 2053198092Srdivacky // to replace it with the real version for a library. In non-PIC code you 2054198092Srdivacky // must compile with the fragile ABI if you want to use ivars from a 2055198092Srdivacky // GCC-compiled class. 2056198092Srdivacky if (CGM.getLangOptions().PICLevel) { 2057198092Srdivacky llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule, 2058198092Srdivacky llvm::Type::getInt32Ty(VMContext), false, 2059198092Srdivacky llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess"); 2060198092Srdivacky IvarOffsetPointer = new llvm::GlobalVariable(TheModule, 2061198092Srdivacky IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage, 2062198092Srdivacky IvarOffsetGV, Name); 2063198092Srdivacky } else { 2064198092Srdivacky IvarOffsetPointer = new llvm::GlobalVariable(TheModule, 2065198092Srdivacky llvm::Type::getInt32PtrTy(VMContext), false, 2066198092Srdivacky llvm::GlobalValue::ExternalLinkage, 0, Name); 2067198092Srdivacky } 2068193326Sed } 2069198092Srdivacky return IvarOffsetPointer; 2070193326Sed} 2071193326Sed 2072193326SedLValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, 2073193326Sed QualType ObjectTy, 2074193326Sed llvm::Value *BaseValue, 2075193326Sed const ObjCIvarDecl *Ivar, 2076193326Sed unsigned CVRQualifiers) { 2077198092Srdivacky const ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCInterfaceType>()->getDecl(); 2078193326Sed return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, 2079193326Sed EmitIvarOffset(CGF, ID, Ivar)); 2080193326Sed} 2081198092Srdivacky 2082193326Sedstatic const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context, 2083193326Sed const ObjCInterfaceDecl *OID, 2084193326Sed const ObjCIvarDecl *OIVD) { 2085193326Sed llvm::SmallVector<ObjCIvarDecl*, 16> Ivars; 2086193576Sed Context.ShallowCollectObjCIvars(OID, Ivars); 2087193326Sed for (unsigned k = 0, e = Ivars.size(); k != e; ++k) { 2088193326Sed if (OIVD == Ivars[k]) 2089193326Sed return OID; 2090193326Sed } 2091198092Srdivacky 2092193326Sed // Otherwise check in the super class. 2093193326Sed if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 2094193326Sed return FindIvarInterface(Context, Super, OIVD); 2095198092Srdivacky 2096193326Sed return 0; 2097193326Sed} 2098193326Sed 2099193326Sedllvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, 2100193326Sed const ObjCInterfaceDecl *Interface, 2101193326Sed const ObjCIvarDecl *Ivar) { 2102198092Srdivacky if (CGM.getLangOptions().ObjCNonFragileABI) { 2103193326Sed Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar); 2104198092Srdivacky return CGF.Builder.CreateLoad(CGF.Builder.CreateLoad( 2105198092Srdivacky ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar")); 2106193326Sed } 2107193326Sed uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar); 2108193326Sed return llvm::ConstantInt::get(LongTy, Offset, "ivar"); 2109193326Sed} 2110193326Sed 2111198092SrdivackyCodeGen::CGObjCRuntime * 2112198092SrdivackyCodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM) { 2113193326Sed return new CGObjCGNU(CGM); 2114193326Sed} 2115