blob: f3c80bcf08e3eea6bb7962b88cab582419033e0f [file] [log] [blame]
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
Chris Lattner0f984262008-03-01 08:50:34 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000010// This provides Objective-C code generation targetting the GNU runtime. The
11// class in this file generates structures used by the GNU Objective-C runtime
12// library. These structures are defined in objc/objc.h and objc/objc-api.h in
13// the GNU runtime distribution.
Chris Lattner0f984262008-03-01 08:50:34 +000014//
15//===----------------------------------------------------------------------===//
16
17#include "CGObjCRuntime.h"
Chris Lattnerdce14062008-06-26 04:19:03 +000018#include "CodeGenModule.h"
Daniel Dunbar8f2926b2008-08-23 03:46:30 +000019#include "CodeGenFunction.h"
John McCallf1549f62010-07-06 01:34:17 +000020#include "CGException.h"
Chris Lattner5dc08672009-05-08 00:11:50 +000021
Chris Lattnerdce14062008-06-26 04:19:03 +000022#include "clang/AST/ASTContext.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000023#include "clang/AST/Decl.h"
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +000024#include "clang/AST/DeclObjC.h"
Anders Carlsson19cc4ab2009-07-18 19:43:29 +000025#include "clang/AST/RecordLayout.h"
Chris Lattner16f00492009-04-26 01:32:48 +000026#include "clang/AST/StmtObjC.h"
Chris Lattner5dc08672009-05-08 00:11:50 +000027
28#include "llvm/Intrinsics.h"
Chris Lattner0f984262008-03-01 08:50:34 +000029#include "llvm/Module.h"
David Chisnallc6cd5fd2010-04-28 19:33:36 +000030#include "llvm/LLVMContext.h"
Chris Lattner0f984262008-03-01 08:50:34 +000031#include "llvm/ADT/SmallVector.h"
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000032#include "llvm/ADT/StringMap.h"
Daniel Dunbar7ded7f42008-08-15 22:20:32 +000033#include "llvm/Support/Compiler.h"
Daniel Dunbar7ded7f42008-08-15 22:20:32 +000034#include "llvm/Target/TargetData.h"
Chris Lattner5dc08672009-05-08 00:11:50 +000035
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000036#include <map>
Chris Lattnere160c9b2009-01-27 05:06:01 +000037
38
Chris Lattnerdce14062008-06-26 04:19:03 +000039using namespace clang;
Daniel Dunbar46f45b92008-09-09 01:06:48 +000040using namespace CodeGen;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000041using llvm::dyn_cast;
42
43// The version of the runtime that this class targets. Must match the version
44// in the runtime.
45static const int RuntimeVersion = 8;
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +000046static const int NonFragileRuntimeVersion = 9;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000047static const int ProtocolVersion = 2;
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +000048static const int NonFragileProtocolVersion = 3;
Chris Lattner0f984262008-03-01 08:50:34 +000049
Chris Lattner0f984262008-03-01 08:50:34 +000050namespace {
Chris Lattnerdce14062008-06-26 04:19:03 +000051class CGObjCGNU : public CodeGen::CGObjCRuntime {
Chris Lattner0f984262008-03-01 08:50:34 +000052private:
Chris Lattnerdce14062008-06-26 04:19:03 +000053 CodeGen::CodeGenModule &CGM;
Chris Lattner0f984262008-03-01 08:50:34 +000054 llvm::Module &TheModule;
Chris Lattnere160c9b2009-01-27 05:06:01 +000055 const llvm::PointerType *SelectorTy;
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +000056 const llvm::IntegerType *Int8Ty;
Chris Lattnere160c9b2009-01-27 05:06:01 +000057 const llvm::PointerType *PtrToInt8Ty;
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +000058 const llvm::FunctionType *IMPTy;
Chris Lattnere160c9b2009-01-27 05:06:01 +000059 const llvm::PointerType *IdTy;
David Chisnallef6e0f32010-02-03 15:59:02 +000060 const llvm::PointerType *PtrToIdTy;
John McCallead608a2010-02-26 00:48:12 +000061 CanQualType ASTIdTy;
Chris Lattnere160c9b2009-01-27 05:06:01 +000062 const llvm::IntegerType *IntTy;
63 const llvm::PointerType *PtrTy;
64 const llvm::IntegerType *LongTy;
65 const llvm::PointerType *PtrToIntTy;
Daniel Dunbar5efccb12009-05-04 15:31:17 +000066 llvm::GlobalAlias *ClassPtrAlias;
67 llvm::GlobalAlias *MetaClassPtrAlias;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000068 std::vector<llvm::Constant*> Classes;
69 std::vector<llvm::Constant*> Categories;
70 std::vector<llvm::Constant*> ConstantStrings;
David Chisnall48272a02010-01-27 12:49:23 +000071 llvm::StringMap<llvm::Constant*> ObjCStrings;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000072 llvm::Function *LoadFunction;
73 llvm::StringMap<llvm::Constant*> ExistingProtocols;
74 typedef std::pair<std::string, std::string> TypedSelector;
75 std::map<TypedSelector, llvm::GlobalAlias*> TypedSelectors;
76 llvm::StringMap<llvm::GlobalAlias*> UntypedSelectors;
David Chisnallef6e0f32010-02-03 15:59:02 +000077 // Selectors that we don't emit in GC mode
78 Selector RetainSel, ReleaseSel, AutoreleaseSel;
79 // Functions used for GC.
80 llvm::Constant *IvarAssignFn, *StrongCastAssignFn, *MemMoveFn, *WeakReadFn,
81 *WeakAssignFn, *GlobalAssignFn;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000082 // Some zeros used for GEPs in lots of places.
83 llvm::Constant *Zeros[2];
84 llvm::Constant *NULLPtr;
Owen Andersona1cf15f2009-07-14 23:10:40 +000085 llvm::LLVMContext &VMContext;
David Chisnallc6cd5fd2010-04-28 19:33:36 +000086 /// Metadata kind used to tie method lookups to message sends.
87 unsigned msgSendMDKind;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000088private:
89 llvm::Constant *GenerateIvarList(
90 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
91 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
92 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets);
93 llvm::Constant *GenerateMethodList(const std::string &ClassName,
94 const std::string &CategoryName,
Mike Stump1eb44332009-09-09 15:08:12 +000095 const llvm::SmallVectorImpl<Selector> &MethodSels,
96 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +000097 bool isClassMethodList);
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +000098 llvm::Constant *GenerateEmptyProtocol(const std::string &ProtocolName);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +000099 llvm::Constant *GeneratePropertyList(const ObjCImplementationDecl *OID,
100 llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
101 llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000102 llvm::Constant *GenerateProtocolList(
103 const llvm::SmallVectorImpl<std::string> &Protocols);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000104 // To ensure that all protocols are seen by the runtime, we add a category on
105 // a class defined in the runtime, declaring no methods, but adopting the
106 // protocols.
107 void GenerateProtocolHolderCategory(void);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000108 llvm::Constant *GenerateClassStructure(
109 llvm::Constant *MetaClass,
110 llvm::Constant *SuperClass,
111 unsigned info,
Chris Lattnerd002cc62008-06-26 04:47:04 +0000112 const char *Name,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000113 llvm::Constant *Version,
114 llvm::Constant *InstanceSize,
115 llvm::Constant *IVars,
116 llvm::Constant *Methods,
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000117 llvm::Constant *Protocols,
118 llvm::Constant *IvarOffsets,
David Chisnall8c757f92010-04-28 14:29:56 +0000119 llvm::Constant *Properties,
120 bool isMeta=false);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000121 llvm::Constant *GenerateProtocolMethodList(
122 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
123 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes);
124 llvm::Constant *MakeConstantString(const std::string &Str, const std::string
125 &Name="");
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000126 llvm::Constant *ExportUniqueString(const std::string &Str, const std::string
127 prefix);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000128 llvm::Constant *MakeGlobal(const llvm::StructType *Ty,
Benjamin Kramer74a8bbf2010-02-09 19:31:24 +0000129 std::vector<llvm::Constant*> &V, llvm::StringRef Name="",
David Chisnall41d63ed2010-01-08 00:14:31 +0000130 llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000131 llvm::Constant *MakeGlobal(const llvm::ArrayType *Ty,
Benjamin Kramer74a8bbf2010-02-09 19:31:24 +0000132 std::vector<llvm::Constant*> &V, llvm::StringRef Name="",
David Chisnall41d63ed2010-01-08 00:14:31 +0000133 llvm::GlobalValue::LinkageTypes linkage=llvm::GlobalValue::InternalLinkage);
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +0000134 llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
135 const ObjCIvarDecl *Ivar);
Chris Lattner2a8e4e12009-06-15 01:09:11 +0000136 void EmitClassRef(const std::string &className);
David Chisnallef6e0f32010-02-03 15:59:02 +0000137 llvm::Value* EnforceType(CGBuilderTy B, llvm::Value *V, const llvm::Type *Ty){
138 if (V->getType() == Ty) return V;
139 return B.CreateBitCast(V, Ty);
140 }
Chris Lattner0f984262008-03-01 08:50:34 +0000141public:
Chris Lattnerdce14062008-06-26 04:19:03 +0000142 CGObjCGNU(CodeGen::CodeGenModule &cgm);
David Chisnall0d13f6f2010-01-23 02:40:42 +0000143 virtual llvm::Constant *GenerateConstantString(const StringLiteral *);
Mike Stump1eb44332009-09-09 15:08:12 +0000144 virtual CodeGen::RValue
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000145 GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +0000146 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000147 QualType ResultType,
148 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000149 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000150 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +0000151 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000152 const ObjCMethodDecl *Method);
Mike Stump1eb44332009-09-09 15:08:12 +0000153 virtual CodeGen::RValue
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000154 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +0000155 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000156 QualType ResultType,
157 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000158 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +0000159 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000160 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000161 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +0000162 const CallArgList &CallArgs,
163 const ObjCMethodDecl *Method);
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000164 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +0000165 const ObjCInterfaceDecl *OID);
Fariborz Jahanian03b29602010-06-17 19:56:20 +0000166 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
167 bool lval = false);
Daniel Dunbar6d5a1c22010-02-03 20:11:42 +0000168 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
169 *Method);
Mike Stump1eb44332009-09-09 15:08:12 +0000170
171 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
Fariborz Jahanian679a5022009-01-10 21:06:09 +0000172 const ObjCContainerDecl *CD);
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000173 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
174 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000175 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000176 const ObjCProtocolDecl *PD);
177 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000178 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar49f66022008-09-24 03:38:44 +0000179 virtual llvm::Function *GetPropertyGetFunction();
180 virtual llvm::Function *GetPropertySetFunction();
Fariborz Jahanian6cc59062010-04-12 18:18:10 +0000181 virtual llvm::Function *GetCopyStructFunction();
Daniel Dunbar309a4362009-07-24 07:40:24 +0000182 virtual llvm::Constant *EnumerationMutationFunction();
Mike Stump1eb44332009-09-09 15:08:12 +0000183
John McCallf1549f62010-07-06 01:34:17 +0000184 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
185 const ObjCAtTryStmt &S);
186 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
187 const ObjCAtSynchronizedStmt &S);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +0000188 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
189 const ObjCAtThrowStmt &S);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +0000190 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6dc23172008-11-18 21:45:40 +0000191 llvm::Value *AddrWeakObj);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +0000192 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
193 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +0000194 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
195 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +0000196 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +0000197 llvm::Value *src, llvm::Value *dest,
198 llvm::Value *ivarOffset);
Fariborz Jahanian58626502008-11-19 00:59:10 +0000199 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
200 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000201 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +0000202 llvm::Value *DestPtr,
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000203 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +0000204 llvm::Value *Size);
Fariborz Jahanian598d3f62009-02-03 19:03:09 +0000205 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
206 QualType ObjectTy,
207 llvm::Value *BaseValue,
208 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +0000209 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +0000210 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +0000211 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +0000212 const ObjCIvarDecl *Ivar);
Chris Lattner0f984262008-03-01 08:50:34 +0000213};
214} // end anonymous namespace
215
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000216
Chris Lattner2a8e4e12009-06-15 01:09:11 +0000217/// Emits a reference to a dummy variable which is emitted with each class.
218/// This ensures that a linker error will be generated when trying to link
219/// together modules where a referenced class is not defined.
Mike Stumpbb1c8602009-07-31 21:31:32 +0000220void CGObjCGNU::EmitClassRef(const std::string &className) {
Chris Lattner2a8e4e12009-06-15 01:09:11 +0000221 std::string symbolRef = "__objc_class_ref_" + className;
222 // Don't emit two copies of the same symbol
Mike Stumpbb1c8602009-07-31 21:31:32 +0000223 if (TheModule.getGlobalVariable(symbolRef))
224 return;
Chris Lattner2a8e4e12009-06-15 01:09:11 +0000225 std::string symbolName = "__objc_class_name_" + className;
226 llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
227 if (!ClassSymbol) {
Owen Anderson1c431b32009-07-08 19:05:04 +0000228 ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
229 llvm::GlobalValue::ExternalLinkage, 0, symbolName);
Chris Lattner2a8e4e12009-06-15 01:09:11 +0000230 }
Owen Anderson1c431b32009-07-08 19:05:04 +0000231 new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true,
Chris Lattnerf35271b2009-08-05 05:25:18 +0000232 llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
Chris Lattner2a8e4e12009-06-15 01:09:11 +0000233}
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000234
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000235static std::string SymbolNameForMethod(const std::string &ClassName, const
236 std::string &CategoryName, const std::string &MethodName, bool isClassMethod)
237{
David Chisnalld3467362010-01-14 14:08:19 +0000238 std::string MethodNameColonStripped = MethodName;
239 std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(),
240 ':', '_');
241 return std::string(isClassMethod ? "_c_" : "_i_") + ClassName + "_" +
242 CategoryName + "_" + MethodNameColonStripped;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000243}
David Chisnall87935a82010-05-08 20:58:05 +0000244static std::string MangleSelectorTypes(const std::string &TypeString) {
245 std::string Mangled = TypeString;
David Chisnall22b88272010-05-09 01:01:43 +0000246 // Simple mangling to avoid breaking when we mix JIT / static code.
247 // Not part of the ABI, subject to change without notice.
David Chisnall87935a82010-05-08 20:58:05 +0000248 std::replace(Mangled.begin(), Mangled.end(), '@', '_');
David Chisnall22b88272010-05-09 01:01:43 +0000249 std::replace(Mangled.begin(), Mangled.end(), ':', 'J');
250 std::replace(Mangled.begin(), Mangled.end(), '*', 'e');
251 std::replace(Mangled.begin(), Mangled.end(), '#', 'E');
252 std::replace(Mangled.begin(), Mangled.end(), ':', 'j');
253 std::replace(Mangled.begin(), Mangled.end(), '(', 'g');
254 std::replace(Mangled.begin(), Mangled.end(), ')', 'G');
255 std::replace(Mangled.begin(), Mangled.end(), '[', 'h');
256 std::replace(Mangled.begin(), Mangled.end(), ']', 'H');
David Chisnall87935a82010-05-08 20:58:05 +0000257 return Mangled;
258}
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000259
Chris Lattnerdce14062008-06-26 04:19:03 +0000260CGObjCGNU::CGObjCGNU(CodeGen::CodeGenModule &cgm)
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000261 : CGM(cgm), TheModule(CGM.getModule()), ClassPtrAlias(0),
Owen Andersona1cf15f2009-07-14 23:10:40 +0000262 MetaClassPtrAlias(0), VMContext(cgm.getLLVMContext()) {
David Chisnallc6cd5fd2010-04-28 19:33:36 +0000263
264 msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
265
Chris Lattnere160c9b2009-01-27 05:06:01 +0000266 IntTy = cast<llvm::IntegerType>(
267 CGM.getTypes().ConvertType(CGM.getContext().IntTy));
268 LongTy = cast<llvm::IntegerType>(
269 CGM.getTypes().ConvertType(CGM.getContext().LongTy));
Mike Stump1eb44332009-09-09 15:08:12 +0000270
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000271 Int8Ty = llvm::Type::getInt8Ty(VMContext);
272 // C string type. Used in lots of places.
273 PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
274
Owen Anderson4a28d5d2009-07-24 23:12:58 +0000275 Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000276 Zeros[1] = Zeros[0];
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000277 NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
Chris Lattner391d77a2008-03-30 23:03:07 +0000278 // Get the selector Type.
David Chisnall0d13f6f2010-01-23 02:40:42 +0000279 QualType selTy = CGM.getContext().getObjCSelType();
280 if (QualType() == selTy) {
281 SelectorTy = PtrToInt8Ty;
282 } else {
283 SelectorTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(selTy));
284 }
Chris Lattnere160c9b2009-01-27 05:06:01 +0000285
Owen Anderson96e0fc72009-07-29 22:16:19 +0000286 PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
Chris Lattner391d77a2008-03-30 23:03:07 +0000287 PtrTy = PtrToInt8Ty;
Mike Stump1eb44332009-09-09 15:08:12 +0000288
Chris Lattner391d77a2008-03-30 23:03:07 +0000289 // Object type
John McCallead608a2010-02-26 00:48:12 +0000290 ASTIdTy = CGM.getContext().getCanonicalType(CGM.getContext().getObjCIdType());
David Chisnall0d13f6f2010-01-23 02:40:42 +0000291 if (QualType() == ASTIdTy) {
292 IdTy = PtrToInt8Ty;
293 } else {
294 IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
295 }
David Chisnallef6e0f32010-02-03 15:59:02 +0000296 PtrToIdTy = llvm::PointerType::getUnqual(IdTy);
Mike Stump1eb44332009-09-09 15:08:12 +0000297
Chris Lattner391d77a2008-03-30 23:03:07 +0000298 // IMP type
299 std::vector<const llvm::Type*> IMPArgs;
300 IMPArgs.push_back(IdTy);
301 IMPArgs.push_back(SelectorTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000302 IMPTy = llvm::FunctionType::get(IdTy, IMPArgs, true);
David Chisnallef6e0f32010-02-03 15:59:02 +0000303
304 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
305 // Get selectors needed in GC mode
306 RetainSel = GetNullarySelector("retain", CGM.getContext());
307 ReleaseSel = GetNullarySelector("release", CGM.getContext());
308 AutoreleaseSel = GetNullarySelector("autorelease", CGM.getContext());
309
310 // Get functions needed in GC mode
311
312 // id objc_assign_ivar(id, id, ptrdiff_t);
313 std::vector<const llvm::Type*> Args(1, IdTy);
314 Args.push_back(PtrToIdTy);
315 // FIXME: ptrdiff_t
316 Args.push_back(LongTy);
317 llvm::FunctionType *FTy = llvm::FunctionType::get(IdTy, Args, false);
318 IvarAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
319 // id objc_assign_strongCast (id, id*)
320 Args.pop_back();
321 FTy = llvm::FunctionType::get(IdTy, Args, false);
322 StrongCastAssignFn =
323 CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
324 // id objc_assign_global(id, id*);
325 FTy = llvm::FunctionType::get(IdTy, Args, false);
326 GlobalAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
327 // id objc_assign_weak(id, id*);
328 FTy = llvm::FunctionType::get(IdTy, Args, false);
329 WeakAssignFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
330 // id objc_read_weak(id*);
331 Args.clear();
332 Args.push_back(PtrToIdTy);
333 FTy = llvm::FunctionType::get(IdTy, Args, false);
334 WeakReadFn = CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
335 // void *objc_memmove_collectable(void*, void *, size_t);
336 Args.clear();
337 Args.push_back(PtrToInt8Ty);
338 Args.push_back(PtrToInt8Ty);
339 // FIXME: size_t
340 Args.push_back(LongTy);
341 FTy = llvm::FunctionType::get(IdTy, Args, false);
342 MemMoveFn = CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
343 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000344}
Mike Stumpbb1c8602009-07-31 21:31:32 +0000345
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000346// This has to perform the lookup every time, since posing and related
347// techniques can modify the name -> class mapping.
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000348llvm::Value *CGObjCGNU::GetClass(CGBuilderTy &Builder,
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +0000349 const ObjCInterfaceDecl *OID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000350 llvm::Value *ClassName = CGM.GetAddrOfConstantCString(OID->getNameAsString());
David Chisnall41d63ed2010-01-08 00:14:31 +0000351 // With the incompatible ABI, this will need to be replaced with a direct
352 // reference to the class symbol. For the compatible nonfragile ABI we are
353 // still performing this lookup at run time but emitting the symbol for the
354 // class externally so that we can make the switch later.
Chris Lattner2a8e4e12009-06-15 01:09:11 +0000355 EmitClassRef(OID->getNameAsString());
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +0000356 ClassName = Builder.CreateStructGEP(ClassName, 0);
357
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000358 std::vector<const llvm::Type*> Params(1, PtrToInt8Ty);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000359 llvm::Constant *ClassLookupFn =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000360 CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy,
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000361 Params,
362 true),
363 "objc_lookup_class");
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000364 return Builder.CreateCall(ClassLookupFn, ClassName);
Chris Lattner391d77a2008-03-30 23:03:07 +0000365}
366
Fariborz Jahanian03b29602010-06-17 19:56:20 +0000367llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, Selector Sel,
368 bool lval) {
Chris Lattner077bf5e2008-11-24 03:33:13 +0000369 llvm::GlobalAlias *&US = UntypedSelectors[Sel.getAsString()];
Chris Lattner8e67b632008-06-26 04:37:12 +0000370 if (US == 0)
Daniel Dunbar6d5a1c22010-02-03 20:11:42 +0000371 US = new llvm::GlobalAlias(llvm::PointerType::getUnqual(SelectorTy),
David Chisnall0f436562009-08-17 16:35:33 +0000372 llvm::GlobalValue::PrivateLinkage,
373 ".objc_untyped_selector_alias"+Sel.getAsString(),
Chris Lattner8e67b632008-06-26 04:37:12 +0000374 NULL, &TheModule);
Fariborz Jahanian03b29602010-06-17 19:56:20 +0000375 if (lval)
376 return US;
Daniel Dunbar6d5a1c22010-02-03 20:11:42 +0000377 return Builder.CreateLoad(US);
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000378}
379
Daniel Dunbar6d5a1c22010-02-03 20:11:42 +0000380llvm::Value *CGObjCGNU::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000381 *Method) {
382
383 std::string SelName = Method->getSelector().getAsString();
384 std::string SelTypes;
385 CGM.getContext().getObjCEncodingForMethodDecl(Method, SelTypes);
386 // Typed selectors
387 TypedSelector Selector = TypedSelector(SelName,
388 SelTypes);
389
390 // If it's already cached, return it.
Mike Stumpbb1c8602009-07-31 21:31:32 +0000391 if (TypedSelectors[Selector]) {
Daniel Dunbar6d5a1c22010-02-03 20:11:42 +0000392 return Builder.CreateLoad(TypedSelectors[Selector]);
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000393 }
394
395 // If it isn't, cache it.
396 llvm::GlobalAlias *Sel = new llvm::GlobalAlias(
Daniel Dunbar6d5a1c22010-02-03 20:11:42 +0000397 llvm::PointerType::getUnqual(SelectorTy),
David Chisnall0f436562009-08-17 16:35:33 +0000398 llvm::GlobalValue::PrivateLinkage, ".objc_selector_alias" + SelName,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000399 NULL, &TheModule);
400 TypedSelectors[Selector] = Sel;
401
Daniel Dunbar6d5a1c22010-02-03 20:11:42 +0000402 return Builder.CreateLoad(Sel);
Chris Lattner8e67b632008-06-26 04:37:12 +0000403}
404
Chris Lattner5e7dcc62008-06-26 04:44:19 +0000405llvm::Constant *CGObjCGNU::MakeConstantString(const std::string &Str,
406 const std::string &Name) {
David Chisnall8a5a9aa2009-08-31 16:41:57 +0000407 llvm::Constant *ConstStr = CGM.GetAddrOfConstantCString(Str, Name.c_str());
Owen Anderson3c4972d2009-07-29 18:54:39 +0000408 return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000409}
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000410llvm::Constant *CGObjCGNU::ExportUniqueString(const std::string &Str,
411 const std::string prefix) {
412 std::string name = prefix + Str;
413 llvm::Constant *ConstStr = TheModule.getGlobalVariable(name);
414 if (!ConstStr) {
415 llvm::Constant *value = llvm::ConstantArray::get(VMContext, Str, true);
416 ConstStr = new llvm::GlobalVariable(TheModule, value->getType(), true,
417 llvm::GlobalValue::LinkOnceODRLinkage, value, prefix + Str);
418 }
419 return llvm::ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2);
420}
Mike Stumpbb1c8602009-07-31 21:31:32 +0000421
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000422llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::StructType *Ty,
Benjamin Kramer74a8bbf2010-02-09 19:31:24 +0000423 std::vector<llvm::Constant*> &V, llvm::StringRef Name,
David Chisnall41d63ed2010-01-08 00:14:31 +0000424 llvm::GlobalValue::LinkageTypes linkage) {
Owen Anderson08e25242009-07-27 22:29:56 +0000425 llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
Owen Anderson1c431b32009-07-08 19:05:04 +0000426 return new llvm::GlobalVariable(TheModule, Ty, false,
427 llvm::GlobalValue::InternalLinkage, C, Name);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000428}
Mike Stumpbb1c8602009-07-31 21:31:32 +0000429
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000430llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty,
Benjamin Kramer74a8bbf2010-02-09 19:31:24 +0000431 std::vector<llvm::Constant*> &V, llvm::StringRef Name,
David Chisnall41d63ed2010-01-08 00:14:31 +0000432 llvm::GlobalValue::LinkageTypes linkage) {
Owen Anderson7db6d832009-07-28 18:33:04 +0000433 llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
Owen Anderson1c431b32009-07-08 19:05:04 +0000434 return new llvm::GlobalVariable(TheModule, Ty, false,
Mike Stumpbb1c8602009-07-31 21:31:32 +0000435 llvm::GlobalValue::InternalLinkage, C, Name);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000436}
437
438/// Generate an NSConstantString object.
David Chisnall0d13f6f2010-01-23 02:40:42 +0000439llvm::Constant *CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {
David Chisnall48272a02010-01-27 12:49:23 +0000440
David Chisnall0d13f6f2010-01-23 02:40:42 +0000441 std::string Str(SL->getStrData(), SL->getByteLength());
442
David Chisnall48272a02010-01-27 12:49:23 +0000443 // Look for an existing one
444 llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
445 if (old != ObjCStrings.end())
446 return old->getValue();
447
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000448 std::vector<llvm::Constant*> Ivars;
449 Ivars.push_back(NULLPtr);
Chris Lattner13fd7e52008-06-21 21:44:18 +0000450 Ivars.push_back(MakeConstantString(Str));
Owen Anderson4a28d5d2009-07-24 23:12:58 +0000451 Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000452 llvm::Constant *ObjCStr = MakeGlobal(
Owen Anderson47a434f2009-08-05 23:18:46 +0000453 llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty, IntTy, NULL),
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000454 Ivars, ".objc_str");
David Chisnall48272a02010-01-27 12:49:23 +0000455 ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty);
456 ObjCStrings[Str] = ObjCStr;
457 ConstantStrings.push_back(ObjCStr);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000458 return ObjCStr;
459}
460
461///Generates a message send where the super is the receiver. This is a message
462///send to self with special delivery semantics indicating which class's method
463///should be called.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000464CodeGen::RValue
465CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +0000466 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000467 QualType ResultType,
468 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000469 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +0000470 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000471 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000472 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +0000473 const CallArgList &CallArgs,
474 const ObjCMethodDecl *Method) {
David Chisnallef6e0f32010-02-03 15:59:02 +0000475 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
476 if (Sel == RetainSel || Sel == AutoreleaseSel) {
477 return RValue::get(Receiver);
478 }
479 if (Sel == ReleaseSel) {
480 return RValue::get(0);
481 }
482 }
David Chisnalldb831942010-05-01 12:37:16 +0000483
484 CGBuilderTy &Builder = CGF.Builder;
485 llvm::Value *cmd = GetSelector(Builder, Sel);
486
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000487
488 CallArgList ActualArgs;
489
490 ActualArgs.push_back(
David Chisnalldb831942010-05-01 12:37:16 +0000491 std::make_pair(RValue::get(Builder.CreateBitCast(Receiver, IdTy)),
David Chisnall0f436562009-08-17 16:35:33 +0000492 ASTIdTy));
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000493 ActualArgs.push_back(std::make_pair(RValue::get(cmd),
494 CGF.getContext().getObjCSelType()));
495 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
496
497 CodeGenTypes &Types = CGM.getTypes();
John McCall04a67a62010-02-05 21:31:56 +0000498 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindola264ba482010-03-30 20:24:48 +0000499 FunctionType::ExtInfo());
Daniel Dunbar67939662009-09-17 04:01:40 +0000500 const llvm::FunctionType *impType =
501 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000502
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000503 llvm::Value *ReceiverClass = 0;
Chris Lattner48e6e7e2009-05-08 15:39:58 +0000504 if (isCategoryImpl) {
505 llvm::Constant *classLookupFunction = 0;
506 std::vector<const llvm::Type*> Params;
507 Params.push_back(PtrTy);
508 if (IsClassMessage) {
Owen Anderson96e0fc72009-07-29 22:16:19 +0000509 classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
Chris Lattner48e6e7e2009-05-08 15:39:58 +0000510 IdTy, Params, true), "objc_get_meta_class");
511 } else {
Owen Anderson96e0fc72009-07-29 22:16:19 +0000512 classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
Chris Lattner48e6e7e2009-05-08 15:39:58 +0000513 IdTy, Params, true), "objc_get_class");
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000514 }
David Chisnalldb831942010-05-01 12:37:16 +0000515 ReceiverClass = Builder.CreateCall(classLookupFunction,
Chris Lattner48e6e7e2009-05-08 15:39:58 +0000516 MakeConstantString(Class->getNameAsString()));
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000517 } else {
Chris Lattner48e6e7e2009-05-08 15:39:58 +0000518 // Set up global aliases for the metaclass or class pointer if they do not
519 // already exist. These will are forward-references which will be set to
Mike Stumpbb1c8602009-07-31 21:31:32 +0000520 // pointers to the class and metaclass structure created for the runtime
521 // load function. To send a message to super, we look up the value of the
Chris Lattner48e6e7e2009-05-08 15:39:58 +0000522 // super_class pointer from either the class or metaclass structure.
523 if (IsClassMessage) {
524 if (!MetaClassPtrAlias) {
525 MetaClassPtrAlias = new llvm::GlobalAlias(IdTy,
526 llvm::GlobalValue::InternalLinkage, ".objc_metaclass_ref" +
527 Class->getNameAsString(), NULL, &TheModule);
528 }
529 ReceiverClass = MetaClassPtrAlias;
530 } else {
531 if (!ClassPtrAlias) {
532 ClassPtrAlias = new llvm::GlobalAlias(IdTy,
533 llvm::GlobalValue::InternalLinkage, ".objc_class_ref" +
534 Class->getNameAsString(), NULL, &TheModule);
535 }
536 ReceiverClass = ClassPtrAlias;
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000537 }
Chris Lattner71238f62009-04-25 23:19:45 +0000538 }
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000539 // Cast the pointer to a simplified version of the class structure
David Chisnalldb831942010-05-01 12:37:16 +0000540 ReceiverClass = Builder.CreateBitCast(ReceiverClass,
Owen Anderson96e0fc72009-07-29 22:16:19 +0000541 llvm::PointerType::getUnqual(
Owen Anderson47a434f2009-08-05 23:18:46 +0000542 llvm::StructType::get(VMContext, IdTy, IdTy, NULL)));
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000543 // Get the superclass pointer
David Chisnalldb831942010-05-01 12:37:16 +0000544 ReceiverClass = Builder.CreateStructGEP(ReceiverClass, 1);
Daniel Dunbar5efccb12009-05-04 15:31:17 +0000545 // Load the superclass pointer
David Chisnalldb831942010-05-01 12:37:16 +0000546 ReceiverClass = Builder.CreateLoad(ReceiverClass);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000547 // Construct the structure used to look up the IMP
Owen Anderson47a434f2009-08-05 23:18:46 +0000548 llvm::StructType *ObjCSuperTy = llvm::StructType::get(VMContext,
549 Receiver->getType(), IdTy, NULL);
David Chisnalldb831942010-05-01 12:37:16 +0000550 llvm::Value *ObjCSuper = Builder.CreateAlloca(ObjCSuperTy);
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000551
David Chisnalldb831942010-05-01 12:37:16 +0000552 Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
553 Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000554
555 // Get the IMP
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000556 std::vector<const llvm::Type*> Params;
Owen Anderson96e0fc72009-07-29 22:16:19 +0000557 Params.push_back(llvm::PointerType::getUnqual(ObjCSuperTy));
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000558 Params.push_back(SelectorTy);
David Chisnalldb831942010-05-01 12:37:16 +0000559
560 llvm::Value *lookupArgs[] = {ObjCSuper, cmd};
561 llvm::Value *imp;
562
563 if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
564 // The lookup function returns a slot, which can be safely cached.
565 llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy,
566 IntTy, llvm::PointerType::getUnqual(impType), NULL);
567
568 llvm::Constant *lookupFunction =
569 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
570 llvm::PointerType::getUnqual(SlotTy), Params, true),
571 "objc_slot_lookup_super");
572
573 llvm::CallInst *slot = Builder.CreateCall(lookupFunction, lookupArgs,
574 lookupArgs+2);
575 slot->setOnlyReadsMemory();
576
577 imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4));
578 } else {
Mike Stump1eb44332009-09-09 15:08:12 +0000579 llvm::Constant *lookupFunction =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000580 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
581 llvm::PointerType::getUnqual(impType), Params, true),
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000582 "objc_msg_lookup_super");
David Chisnalldb831942010-05-01 12:37:16 +0000583 imp = Builder.CreateCall(lookupFunction, lookupArgs, lookupArgs+2);
584 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000585
David Chisnalldd5c98f2010-05-01 11:15:56 +0000586 llvm::Value *impMD[] = {
587 llvm::MDString::get(VMContext, Sel.getAsString()),
588 llvm::MDString::get(VMContext, Class->getSuperClass()->getNameAsString()),
589 llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsClassMessage)
590 };
591 llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD, 3);
592
David Chisnall4b02afc2010-05-02 13:41:58 +0000593 llvm::Instruction *call;
John McCallef072fd2010-05-22 01:48:05 +0000594 RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs,
David Chisnall4b02afc2010-05-02 13:41:58 +0000595 0, &call);
596 call->setMetadata(msgSendMDKind, node);
597 return msgRet;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000598}
599
Mike Stump1eb44332009-09-09 15:08:12 +0000600/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000601CodeGen::RValue
602CGObjCGNU::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +0000603 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000604 QualType ResultType,
605 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000606 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000607 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +0000608 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000609 const ObjCMethodDecl *Method) {
David Chisnall664b7c72010-04-27 15:08:48 +0000610 // Strip out message sends to retain / release in GC mode
David Chisnallef6e0f32010-02-03 15:59:02 +0000611 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
612 if (Sel == RetainSel || Sel == AutoreleaseSel) {
613 return RValue::get(Receiver);
614 }
615 if (Sel == ReleaseSel) {
616 return RValue::get(0);
617 }
618 }
David Chisnall664b7c72010-04-27 15:08:48 +0000619
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000620 CGBuilderTy &Builder = CGF.Builder;
David Chisnall664b7c72010-04-27 15:08:48 +0000621
622 // If the return type is something that goes in an integer register, the
623 // runtime will handle 0 returns. For other cases, we fill in the 0 value
624 // ourselves.
625 //
626 // The language spec says the result of this kind of message send is
627 // undefined, but lots of people seem to have forgotten to read that
628 // paragraph and insist on sending messages to nil that have structure
629 // returns. With GCC, this generates a random return value (whatever happens
630 // to be on the stack / in those registers at the time) on most platforms,
631 // and generates a SegV on SPARC. With LLVM it corrupts the stack.
632 bool isPointerSizedReturn = false;
Douglas Gregor9d3347a2010-06-16 00:35:25 +0000633 if (ResultType->isAnyPointerType() ||
634 ResultType->isIntegralOrEnumerationType() || ResultType->isVoidType())
David Chisnall664b7c72010-04-27 15:08:48 +0000635 isPointerSizedReturn = true;
636
637 llvm::BasicBlock *startBB = 0;
638 llvm::BasicBlock *messageBB = 0;
David Chisnalla54da052010-05-20 13:45:48 +0000639 llvm::BasicBlock *continueBB = 0;
David Chisnall664b7c72010-04-27 15:08:48 +0000640
641 if (!isPointerSizedReturn) {
642 startBB = Builder.GetInsertBlock();
643 messageBB = CGF.createBasicBlock("msgSend");
David Chisnalla54da052010-05-20 13:45:48 +0000644 continueBB = CGF.createBasicBlock("continue");
David Chisnall664b7c72010-04-27 15:08:48 +0000645
646 llvm::Value *isNil = Builder.CreateICmpEQ(Receiver,
647 llvm::Constant::getNullValue(Receiver->getType()));
David Chisnalla54da052010-05-20 13:45:48 +0000648 Builder.CreateCondBr(isNil, continueBB, messageBB);
David Chisnall664b7c72010-04-27 15:08:48 +0000649 CGF.EmitBlock(messageBB);
650 }
651
David Chisnall0f436562009-08-17 16:35:33 +0000652 IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000653 llvm::Value *cmd;
654 if (Method)
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000655 cmd = GetSelector(Builder, Method);
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +0000656 else
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000657 cmd = GetSelector(Builder, Sel);
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000658 CallArgList ActualArgs;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000659
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000660 Receiver = Builder.CreateBitCast(Receiver, IdTy);
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000661 ActualArgs.push_back(
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000662 std::make_pair(RValue::get(Receiver), ASTIdTy));
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000663 ActualArgs.push_back(std::make_pair(RValue::get(cmd),
664 CGF.getContext().getObjCSelType()));
665 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
666
667 CodeGenTypes &Types = CGM.getTypes();
John McCall04a67a62010-02-05 21:31:56 +0000668 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindola264ba482010-03-30 20:24:48 +0000669 FunctionType::ExtInfo());
Daniel Dunbar67939662009-09-17 04:01:40 +0000670 const llvm::FunctionType *impType =
671 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Fariborz Jahanianb3716ef2009-02-04 20:31:19 +0000672
David Chisnall63e742b2010-05-01 12:56:56 +0000673 llvm::Value *impMD[] = {
674 llvm::MDString::get(VMContext, Sel.getAsString()),
675 llvm::MDString::get(VMContext, Class ? Class->getNameAsString() :""),
676 llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), Class!=0)
677 };
678 llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD, 3);
679
680
Fariborz Jahanian34e65772009-05-22 20:17:16 +0000681 llvm::Value *imp;
Fariborz Jahanian34e65772009-05-22 20:17:16 +0000682 // For sender-aware dispatch, we pass the sender as the third argument to a
683 // lookup function. When sending messages from C code, the sender is nil.
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000684 // objc_msg_lookup_sender(id *receiver, SEL selector, id sender);
685 if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
686
687 std::vector<const llvm::Type*> Params;
688 llvm::Value *ReceiverPtr = CGF.CreateTempAlloca(Receiver->getType());
689 Builder.CreateStore(Receiver, ReceiverPtr);
690 Params.push_back(ReceiverPtr->getType());
691 Params.push_back(SelectorTy);
Fariborz Jahanian34e65772009-05-22 20:17:16 +0000692 llvm::Value *self;
Fariborz Jahanian26c82942009-03-30 18:02:14 +0000693
Fariborz Jahanian34e65772009-05-22 20:17:16 +0000694 if (isa<ObjCMethodDecl>(CGF.CurFuncDecl)) {
695 self = CGF.LoadObjCSelf();
696 } else {
Owen Anderson03e20502009-07-30 23:11:26 +0000697 self = llvm::ConstantPointerNull::get(IdTy);
Fariborz Jahanian34e65772009-05-22 20:17:16 +0000698 }
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000699
Fariborz Jahanian34e65772009-05-22 20:17:16 +0000700 Params.push_back(self->getType());
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000701
702 // The lookup function returns a slot, which can be safely cached.
703 llvm::Type *SlotTy = llvm::StructType::get(VMContext, PtrTy, PtrTy, PtrTy,
704 IntTy, llvm::PointerType::getUnqual(impType), NULL);
Mike Stump1eb44332009-09-09 15:08:12 +0000705 llvm::Constant *lookupFunction =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000706 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000707 llvm::PointerType::getUnqual(SlotTy), Params, true),
Fariborz Jahanian34e65772009-05-22 20:17:16 +0000708 "objc_msg_lookup_sender");
709
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000710 // The lookup function is guaranteed not to capture the receiver pointer.
711 if (llvm::Function *LookupFn = dyn_cast<llvm::Function>(lookupFunction)) {
712 LookupFn->setDoesNotCapture(1);
713 }
714
David Chisnall866163b2010-04-30 13:36:12 +0000715 llvm::CallInst *slot =
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000716 Builder.CreateCall3(lookupFunction, ReceiverPtr, cmd, self);
David Chisnall866163b2010-04-30 13:36:12 +0000717 slot->setOnlyReadsMemory();
David Chisnall63e742b2010-05-01 12:56:56 +0000718 slot->setMetadata(msgSendMDKind, node);
David Chisnall866163b2010-04-30 13:36:12 +0000719
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000720 imp = Builder.CreateLoad(Builder.CreateStructGEP(slot, 4));
David Chisnallc6cd5fd2010-04-28 19:33:36 +0000721
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000722 // The lookup function may have changed the receiver, so make sure we use
723 // the new one.
724 ActualArgs[0] =
725 std::make_pair(RValue::get(Builder.CreateLoad(ReceiverPtr)), ASTIdTy);
Fariborz Jahanian34e65772009-05-22 20:17:16 +0000726 } else {
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000727 std::vector<const llvm::Type*> Params;
728 Params.push_back(Receiver->getType());
729 Params.push_back(SelectorTy);
Mike Stump1eb44332009-09-09 15:08:12 +0000730 llvm::Constant *lookupFunction =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000731 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
732 llvm::PointerType::getUnqual(impType), Params, true),
Fariborz Jahanian34e65772009-05-22 20:17:16 +0000733 "objc_msg_lookup");
734
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000735 imp = Builder.CreateCall2(lookupFunction, Receiver, cmd);
David Chisnall63e742b2010-05-01 12:56:56 +0000736 cast<llvm::CallInst>(imp)->setMetadata(msgSendMDKind, node);
Fariborz Jahanian34e65772009-05-22 20:17:16 +0000737 }
David Chisnall4b02afc2010-05-02 13:41:58 +0000738 llvm::Instruction *call;
John McCallef072fd2010-05-22 01:48:05 +0000739 RValue msgRet = CGF.EmitCall(FnInfo, imp, Return, ActualArgs,
David Chisnall4b02afc2010-05-02 13:41:58 +0000740 0, &call);
741 call->setMetadata(msgSendMDKind, node);
David Chisnall664b7c72010-04-27 15:08:48 +0000742
David Chisnalla54da052010-05-20 13:45:48 +0000743
David Chisnall664b7c72010-04-27 15:08:48 +0000744 if (!isPointerSizedReturn) {
David Chisnalla54da052010-05-20 13:45:48 +0000745 messageBB = CGF.Builder.GetInsertBlock();
746 CGF.Builder.CreateBr(continueBB);
747 CGF.EmitBlock(continueBB);
David Chisnall664b7c72010-04-27 15:08:48 +0000748 if (msgRet.isScalar()) {
749 llvm::Value *v = msgRet.getScalarVal();
750 llvm::PHINode *phi = Builder.CreatePHI(v->getType());
751 phi->addIncoming(v, messageBB);
752 phi->addIncoming(llvm::Constant::getNullValue(v->getType()), startBB);
753 msgRet = RValue::get(phi);
754 } else if (msgRet.isAggregate()) {
755 llvm::Value *v = msgRet.getAggregateAddr();
756 llvm::PHINode *phi = Builder.CreatePHI(v->getType());
757 const llvm::PointerType *RetTy = cast<llvm::PointerType>(v->getType());
David Chisnall866163b2010-04-30 13:36:12 +0000758 llvm::AllocaInst *NullVal =
759 CGF.CreateTempAlloca(RetTy->getElementType(), "null");
David Chisnall664b7c72010-04-27 15:08:48 +0000760 CGF.InitTempAlloca(NullVal,
761 llvm::Constant::getNullValue(RetTy->getElementType()));
762 phi->addIncoming(v, messageBB);
763 phi->addIncoming(NullVal, startBB);
764 msgRet = RValue::getAggregate(phi);
765 } else /* isComplex() */ {
766 std::pair<llvm::Value*,llvm::Value*> v = msgRet.getComplexVal();
767 llvm::PHINode *phi = Builder.CreatePHI(v.first->getType());
768 phi->addIncoming(v.first, messageBB);
769 phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()),
770 startBB);
771 llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType());
772 phi2->addIncoming(v.second, messageBB);
773 phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()),
774 startBB);
775 msgRet = RValue::getComplex(phi, phi2);
776 }
777 }
778 return msgRet;
Chris Lattner0f984262008-03-01 08:50:34 +0000779}
780
Mike Stump1eb44332009-09-09 15:08:12 +0000781/// Generates a MethodList. Used in construction of a objc_class and
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000782/// objc_category structures.
783llvm::Constant *CGObjCGNU::GenerateMethodList(const std::string &ClassName,
Mike Stump1eb44332009-09-09 15:08:12 +0000784 const std::string &CategoryName,
785 const llvm::SmallVectorImpl<Selector> &MethodSels,
786 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000787 bool isClassMethodList) {
David Chisnall0f436562009-08-17 16:35:33 +0000788 if (MethodSels.empty())
789 return NULLPtr;
Mike Stump1eb44332009-09-09 15:08:12 +0000790 // Get the method structure type.
Owen Anderson47a434f2009-08-05 23:18:46 +0000791 llvm::StructType *ObjCMethodTy = llvm::StructType::get(VMContext,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000792 PtrToInt8Ty, // Really a selector, but the runtime creates it us.
793 PtrToInt8Ty, // Method types
Owen Anderson96e0fc72009-07-29 22:16:19 +0000794 llvm::PointerType::getUnqual(IMPTy), //Method pointer
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000795 NULL);
796 std::vector<llvm::Constant*> Methods;
797 std::vector<llvm::Constant*> Elements;
798 for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
799 Elements.clear();
Fariborz Jahanian1e64a952009-05-17 16:49:27 +0000800 if (llvm::Constant *Method =
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000801 TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
Chris Lattner077bf5e2008-11-24 03:33:13 +0000802 MethodSels[i].getAsString(),
Fariborz Jahanian1e64a952009-05-17 16:49:27 +0000803 isClassMethodList))) {
David Chisnall8a5a9aa2009-08-31 16:41:57 +0000804 llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString());
805 Elements.push_back(C);
806 Elements.push_back(MethodTypes[i]);
Owen Anderson3c4972d2009-07-29 18:54:39 +0000807 Method = llvm::ConstantExpr::getBitCast(Method,
Owen Anderson96e0fc72009-07-29 22:16:19 +0000808 llvm::PointerType::getUnqual(IMPTy));
Fariborz Jahanian1e64a952009-05-17 16:49:27 +0000809 Elements.push_back(Method);
Owen Anderson08e25242009-07-27 22:29:56 +0000810 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodTy, Elements));
Fariborz Jahanian1e64a952009-05-17 16:49:27 +0000811 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000812 }
813
814 // Array of method structures
Owen Anderson96e0fc72009-07-29 22:16:19 +0000815 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
Fariborz Jahanian1e64a952009-05-17 16:49:27 +0000816 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +0000817 llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
Chris Lattnerfba67632008-06-26 04:52:29 +0000818 Methods);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000819
820 // Structure containing list pointer, array and array count
821 llvm::SmallVector<const llvm::Type*, 16> ObjCMethodListFields;
Owen Anderson8c8f69e2009-08-13 23:27:53 +0000822 llvm::PATypeHolder OpaqueNextTy = llvm::OpaqueType::get(VMContext);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000823 llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(OpaqueNextTy);
Owen Anderson47a434f2009-08-05 23:18:46 +0000824 llvm::StructType *ObjCMethodListTy = llvm::StructType::get(VMContext,
Mike Stump1eb44332009-09-09 15:08:12 +0000825 NextPtrTy,
826 IntTy,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000827 ObjCMethodArrayTy,
828 NULL);
829 // Refine next pointer type to concrete type
830 llvm::cast<llvm::OpaqueType>(
831 OpaqueNextTy.get())->refineAbstractTypeTo(ObjCMethodListTy);
832 ObjCMethodListTy = llvm::cast<llvm::StructType>(OpaqueNextTy.get());
833
834 Methods.clear();
Owen Anderson03e20502009-07-30 23:11:26 +0000835 Methods.push_back(llvm::ConstantPointerNull::get(
Owen Anderson96e0fc72009-07-29 22:16:19 +0000836 llvm::PointerType::getUnqual(ObjCMethodListTy)));
Owen Anderson0032b272009-08-13 21:57:51 +0000837 Methods.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000838 MethodTypes.size()));
839 Methods.push_back(MethodArray);
Mike Stump1eb44332009-09-09 15:08:12 +0000840
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000841 // Create an instance of the structure
842 return MakeGlobal(ObjCMethodListTy, Methods, ".objc_method_list");
843}
844
845/// Generates an IvarList. Used in construction of a objc_class.
846llvm::Constant *CGObjCGNU::GenerateIvarList(
847 const llvm::SmallVectorImpl<llvm::Constant *> &IvarNames,
848 const llvm::SmallVectorImpl<llvm::Constant *> &IvarTypes,
849 const llvm::SmallVectorImpl<llvm::Constant *> &IvarOffsets) {
David Chisnall18044632009-11-16 19:05:54 +0000850 if (IvarNames.size() == 0)
851 return NULLPtr;
Mike Stump1eb44332009-09-09 15:08:12 +0000852 // Get the method structure type.
Owen Anderson47a434f2009-08-05 23:18:46 +0000853 llvm::StructType *ObjCIvarTy = llvm::StructType::get(VMContext,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000854 PtrToInt8Ty,
855 PtrToInt8Ty,
856 IntTy,
857 NULL);
858 std::vector<llvm::Constant*> Ivars;
859 std::vector<llvm::Constant*> Elements;
860 for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
861 Elements.clear();
David Chisnall8a5a9aa2009-08-31 16:41:57 +0000862 Elements.push_back(IvarNames[i]);
863 Elements.push_back(IvarTypes[i]);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000864 Elements.push_back(IvarOffsets[i]);
Owen Anderson08e25242009-07-27 22:29:56 +0000865 Ivars.push_back(llvm::ConstantStruct::get(ObjCIvarTy, Elements));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000866 }
867
868 // Array of method structures
Owen Anderson96e0fc72009-07-29 22:16:19 +0000869 llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000870 IvarNames.size());
871
Mike Stump1eb44332009-09-09 15:08:12 +0000872
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000873 Elements.clear();
Owen Anderson4a28d5d2009-07-24 23:12:58 +0000874 Elements.push_back(llvm::ConstantInt::get(IntTy, (int)IvarNames.size()));
Owen Anderson7db6d832009-07-28 18:33:04 +0000875 Elements.push_back(llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000876 // Structure containing array and array count
Owen Anderson47a434f2009-08-05 23:18:46 +0000877 llvm::StructType *ObjCIvarListTy = llvm::StructType::get(VMContext, IntTy,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000878 ObjCIvarArrayTy,
879 NULL);
880
881 // Create an instance of the structure
882 return MakeGlobal(ObjCIvarListTy, Elements, ".objc_ivar_list");
883}
884
885/// Generate a class structure
886llvm::Constant *CGObjCGNU::GenerateClassStructure(
887 llvm::Constant *MetaClass,
888 llvm::Constant *SuperClass,
889 unsigned info,
Chris Lattnerd002cc62008-06-26 04:47:04 +0000890 const char *Name,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000891 llvm::Constant *Version,
892 llvm::Constant *InstanceSize,
893 llvm::Constant *IVars,
894 llvm::Constant *Methods,
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000895 llvm::Constant *Protocols,
896 llvm::Constant *IvarOffsets,
David Chisnall8c757f92010-04-28 14:29:56 +0000897 llvm::Constant *Properties,
898 bool isMeta) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000899 // Set up the class structure
900 // Note: Several of these are char*s when they should be ids. This is
901 // because the runtime performs this translation on load.
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000902 //
903 // Fields marked New ABI are part of the GNUstep runtime. We emit them
904 // anyway; the classes will still work with the GNU runtime, they will just
905 // be ignored.
Owen Anderson47a434f2009-08-05 23:18:46 +0000906 llvm::StructType *ClassTy = llvm::StructType::get(VMContext,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000907 PtrToInt8Ty, // class_pointer
908 PtrToInt8Ty, // super_class
909 PtrToInt8Ty, // name
910 LongTy, // version
911 LongTy, // info
912 LongTy, // instance_size
913 IVars->getType(), // ivars
914 Methods->getType(), // methods
Mike Stump1eb44332009-09-09 15:08:12 +0000915 // These are all filled in by the runtime, so we pretend
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000916 PtrTy, // dtable
917 PtrTy, // subclass_list
918 PtrTy, // sibling_class
919 PtrTy, // protocols
920 PtrTy, // gc_object_type
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000921 // New ABI:
922 LongTy, // abi_version
923 IvarOffsets->getType(), // ivar_offsets
924 Properties->getType(), // properties
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000925 NULL);
Owen Anderson4a28d5d2009-07-24 23:12:58 +0000926 llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000927 // Fill in the structure
928 std::vector<llvm::Constant*> Elements;
Owen Anderson3c4972d2009-07-29 18:54:39 +0000929 Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000930 Elements.push_back(SuperClass);
Chris Lattnerd002cc62008-06-26 04:47:04 +0000931 Elements.push_back(MakeConstantString(Name, ".class_name"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000932 Elements.push_back(Zero);
Owen Anderson4a28d5d2009-07-24 23:12:58 +0000933 Elements.push_back(llvm::ConstantInt::get(LongTy, info));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000934 Elements.push_back(InstanceSize);
935 Elements.push_back(IVars);
936 Elements.push_back(Methods);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000937 Elements.push_back(NULLPtr);
938 Elements.push_back(NULLPtr);
939 Elements.push_back(NULLPtr);
Owen Anderson3c4972d2009-07-29 18:54:39 +0000940 Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +0000941 Elements.push_back(NULLPtr);
942 Elements.push_back(Zero);
943 Elements.push_back(IvarOffsets);
944 Elements.push_back(Properties);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000945 // Create an instance of the structure
David Chisnall41d63ed2010-01-08 00:14:31 +0000946 // This is now an externally visible symbol, so that we can speed up class
947 // messages in the next ABI.
David Chisnall8c757f92010-04-28 14:29:56 +0000948 return MakeGlobal(ClassTy, Elements, (isMeta ? "_OBJC_METACLASS_":
949 "_OBJC_CLASS_") + std::string(Name), llvm::GlobalValue::ExternalLinkage);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000950}
951
952llvm::Constant *CGObjCGNU::GenerateProtocolMethodList(
953 const llvm::SmallVectorImpl<llvm::Constant *> &MethodNames,
954 const llvm::SmallVectorImpl<llvm::Constant *> &MethodTypes) {
Mike Stump1eb44332009-09-09 15:08:12 +0000955 // Get the method structure type.
Owen Anderson47a434f2009-08-05 23:18:46 +0000956 llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(VMContext,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000957 PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
958 PtrToInt8Ty,
959 NULL);
960 std::vector<llvm::Constant*> Methods;
961 std::vector<llvm::Constant*> Elements;
962 for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
963 Elements.clear();
Mike Stump1eb44332009-09-09 15:08:12 +0000964 Elements.push_back(MethodNames[i]);
David Chisnall8a5a9aa2009-08-31 16:41:57 +0000965 Elements.push_back(MethodTypes[i]);
Owen Anderson08e25242009-07-27 22:29:56 +0000966 Methods.push_back(llvm::ConstantStruct::get(ObjCMethodDescTy, Elements));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000967 }
Owen Anderson96e0fc72009-07-29 22:16:19 +0000968 llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000969 MethodNames.size());
Owen Anderson7db6d832009-07-28 18:33:04 +0000970 llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy,
Mike Stumpbb1c8602009-07-31 21:31:32 +0000971 Methods);
Owen Anderson47a434f2009-08-05 23:18:46 +0000972 llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(VMContext,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000973 IntTy, ObjCMethodArrayTy, NULL);
974 Methods.clear();
Owen Anderson4a28d5d2009-07-24 23:12:58 +0000975 Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000976 Methods.push_back(Array);
977 return MakeGlobal(ObjCMethodDescListTy, Methods, ".objc_method_list");
978}
Mike Stumpbb1c8602009-07-31 21:31:32 +0000979
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000980// Create the protocol list structure used in classes, categories and so on
981llvm::Constant *CGObjCGNU::GenerateProtocolList(
982 const llvm::SmallVectorImpl<std::string> &Protocols) {
Owen Anderson96e0fc72009-07-29 22:16:19 +0000983 llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000984 Protocols.size());
Owen Anderson47a434f2009-08-05 23:18:46 +0000985 llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000986 PtrTy, //Should be a recurisve pointer, but it's always NULL here.
987 LongTy,//FIXME: Should be size_t
988 ProtocolArrayTy,
989 NULL);
Mike Stump1eb44332009-09-09 15:08:12 +0000990 std::vector<llvm::Constant*> Elements;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +0000991 for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
992 iter != endIter ; iter++) {
David Chisnallff80fab2009-11-20 14:50:59 +0000993 llvm::Constant *protocol = 0;
994 llvm::StringMap<llvm::Constant*>::iterator value =
995 ExistingProtocols.find(*iter);
996 if (value == ExistingProtocols.end()) {
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +0000997 protocol = GenerateEmptyProtocol(*iter);
David Chisnallff80fab2009-11-20 14:50:59 +0000998 } else {
999 protocol = value->getValue();
1000 }
Owen Anderson3c4972d2009-07-29 18:54:39 +00001001 llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(protocol,
Owen Andersona1cf15f2009-07-14 23:10:40 +00001002 PtrToInt8Ty);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001003 Elements.push_back(Ptr);
1004 }
Owen Anderson7db6d832009-07-28 18:33:04 +00001005 llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001006 Elements);
1007 Elements.clear();
1008 Elements.push_back(NULLPtr);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001009 Elements.push_back(llvm::ConstantInt::get(LongTy, Protocols.size()));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001010 Elements.push_back(ProtocolArray);
1011 return MakeGlobal(ProtocolListTy, Elements, ".objc_protocol_list");
1012}
1013
Mike Stump1eb44332009-09-09 15:08:12 +00001014llvm::Value *CGObjCGNU::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001015 const ObjCProtocolDecl *PD) {
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +00001016 llvm::Value *protocol = ExistingProtocols[PD->getNameAsString()];
Mike Stump1eb44332009-09-09 15:08:12 +00001017 const llvm::Type *T =
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +00001018 CGM.getTypes().ConvertType(CGM.getContext().getObjCProtoType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00001019 return Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +00001020}
1021
1022llvm::Constant *CGObjCGNU::GenerateEmptyProtocol(
1023 const std::string &ProtocolName) {
1024 llvm::SmallVector<std::string, 0> EmptyStringVector;
1025 llvm::SmallVector<llvm::Constant*, 0> EmptyConstantVector;
1026
1027 llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001028 llvm::Constant *MethodList =
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +00001029 GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector);
1030 // Protocols are objects containing lists of the methods implemented and
1031 // protocols adopted.
Owen Anderson47a434f2009-08-05 23:18:46 +00001032 llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy,
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +00001033 PtrToInt8Ty,
1034 ProtocolList->getType(),
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001035 MethodList->getType(),
1036 MethodList->getType(),
1037 MethodList->getType(),
1038 MethodList->getType(),
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +00001039 NULL);
Mike Stump1eb44332009-09-09 15:08:12 +00001040 std::vector<llvm::Constant*> Elements;
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +00001041 // The isa pointer must be set to a magic number so the runtime knows it's
1042 // the correct layout.
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001043 int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ?
1044 NonFragileProtocolVersion : ProtocolVersion;
Owen Anderson3c4972d2009-07-29 18:54:39 +00001045 Elements.push_back(llvm::ConstantExpr::getIntToPtr(
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001046 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy));
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +00001047 Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
1048 Elements.push_back(ProtocolList);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001049 Elements.push_back(MethodList);
1050 Elements.push_back(MethodList);
1051 Elements.push_back(MethodList);
1052 Elements.push_back(MethodList);
Fariborz Jahanianf8c4f542009-03-31 18:27:22 +00001053 return MakeGlobal(ProtocolTy, Elements, ".objc_protocol");
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001054}
1055
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001056void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
1057 ASTContext &Context = CGM.getContext();
Chris Lattner8ec03f52008-11-24 03:54:41 +00001058 std::string ProtocolName = PD->getNameAsString();
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001059 llvm::SmallVector<std::string, 16> Protocols;
1060 for (ObjCProtocolDecl::protocol_iterator PI = PD->protocol_begin(),
1061 E = PD->protocol_end(); PI != E; ++PI)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00001062 Protocols.push_back((*PI)->getNameAsString());
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001063 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames;
1064 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001065 llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodNames;
1066 llvm::SmallVector<llvm::Constant*, 16> OptionalInstanceMethodTypes;
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001067 for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(),
1068 E = PD->instmeth_end(); iter != E; iter++) {
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001069 std::string TypeStr;
1070 Context.getObjCEncodingForMethodDecl(*iter, TypeStr);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001071 if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) {
1072 InstanceMethodNames.push_back(
1073 MakeConstantString((*iter)->getSelector().getAsString()));
1074 InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
1075 } else {
1076 OptionalInstanceMethodNames.push_back(
1077 MakeConstantString((*iter)->getSelector().getAsString()));
1078 OptionalInstanceMethodTypes.push_back(MakeConstantString(TypeStr));
1079 }
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001080 }
1081 // Collect information about class methods:
1082 llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames;
1083 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001084 llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodNames;
1085 llvm::SmallVector<llvm::Constant*, 16> OptionalClassMethodTypes;
Mike Stump1eb44332009-09-09 15:08:12 +00001086 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001087 iter = PD->classmeth_begin(), endIter = PD->classmeth_end();
1088 iter != endIter ; iter++) {
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001089 std::string TypeStr;
1090 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001091 if ((*iter)->getImplementationControl() == ObjCMethodDecl::Optional) {
1092 ClassMethodNames.push_back(
1093 MakeConstantString((*iter)->getSelector().getAsString()));
1094 ClassMethodTypes.push_back(MakeConstantString(TypeStr));
1095 } else {
1096 OptionalClassMethodNames.push_back(
1097 MakeConstantString((*iter)->getSelector().getAsString()));
1098 OptionalClassMethodTypes.push_back(MakeConstantString(TypeStr));
1099 }
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001100 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001101
1102 llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
1103 llvm::Constant *InstanceMethodList =
1104 GenerateProtocolMethodList(InstanceMethodNames, InstanceMethodTypes);
1105 llvm::Constant *ClassMethodList =
1106 GenerateProtocolMethodList(ClassMethodNames, ClassMethodTypes);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001107 llvm::Constant *OptionalInstanceMethodList =
1108 GenerateProtocolMethodList(OptionalInstanceMethodNames,
1109 OptionalInstanceMethodTypes);
1110 llvm::Constant *OptionalClassMethodList =
1111 GenerateProtocolMethodList(OptionalClassMethodNames,
1112 OptionalClassMethodTypes);
1113
1114 // Property metadata: name, attributes, isSynthesized, setter name, setter
1115 // types, getter name, getter types.
1116 // The isSynthesized value is always set to 0 in a protocol. It exists to
1117 // simplify the runtime library by allowing it to use the same data
1118 // structures for protocol metadata everywhere.
1119 llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext,
1120 PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty,
1121 PtrToInt8Ty, NULL);
1122 std::vector<llvm::Constant*> Properties;
1123 std::vector<llvm::Constant*> OptionalProperties;
1124
1125 // Add all of the property methods need adding to the method list and to the
1126 // property metadata list.
1127 for (ObjCContainerDecl::prop_iterator
1128 iter = PD->prop_begin(), endIter = PD->prop_end();
1129 iter != endIter ; iter++) {
1130 std::vector<llvm::Constant*> Fields;
1131 ObjCPropertyDecl *property = (*iter);
1132
1133 Fields.push_back(MakeConstantString(property->getNameAsString()));
1134 Fields.push_back(llvm::ConstantInt::get(Int8Ty,
1135 property->getPropertyAttributes()));
1136 Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0));
1137 if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
1138 std::string TypeStr;
1139 Context.getObjCEncodingForMethodDecl(getter,TypeStr);
1140 llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
1141 InstanceMethodTypes.push_back(TypeEncoding);
1142 Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
1143 Fields.push_back(TypeEncoding);
1144 } else {
1145 Fields.push_back(NULLPtr);
1146 Fields.push_back(NULLPtr);
1147 }
1148 if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
1149 std::string TypeStr;
1150 Context.getObjCEncodingForMethodDecl(setter,TypeStr);
1151 llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
1152 InstanceMethodTypes.push_back(TypeEncoding);
1153 Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
1154 Fields.push_back(TypeEncoding);
1155 } else {
1156 Fields.push_back(NULLPtr);
1157 Fields.push_back(NULLPtr);
1158 }
1159 if (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) {
1160 OptionalProperties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
1161 } else {
1162 Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
1163 }
1164 }
1165 llvm::Constant *PropertyArray = llvm::ConstantArray::get(
1166 llvm::ArrayType::get(PropertyMetadataTy, Properties.size()), Properties);
1167 llvm::Constant* PropertyListInitFields[] =
1168 {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
1169
1170 llvm::Constant *PropertyListInit =
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001171 llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001172 llvm::Constant *PropertyList = new llvm::GlobalVariable(TheModule,
1173 PropertyListInit->getType(), false, llvm::GlobalValue::InternalLinkage,
1174 PropertyListInit, ".objc_property_list");
1175
1176 llvm::Constant *OptionalPropertyArray =
1177 llvm::ConstantArray::get(llvm::ArrayType::get(PropertyMetadataTy,
1178 OptionalProperties.size()) , OptionalProperties);
1179 llvm::Constant* OptionalPropertyListInitFields[] = {
1180 llvm::ConstantInt::get(IntTy, OptionalProperties.size()), NULLPtr,
1181 OptionalPropertyArray };
1182
1183 llvm::Constant *OptionalPropertyListInit =
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001184 llvm::ConstantStruct::get(VMContext, OptionalPropertyListInitFields, 3, false);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001185 llvm::Constant *OptionalPropertyList = new llvm::GlobalVariable(TheModule,
1186 OptionalPropertyListInit->getType(), false,
1187 llvm::GlobalValue::InternalLinkage, OptionalPropertyListInit,
1188 ".objc_property_list");
1189
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001190 // Protocols are objects containing lists of the methods implemented and
1191 // protocols adopted.
Owen Anderson47a434f2009-08-05 23:18:46 +00001192 llvm::StructType *ProtocolTy = llvm::StructType::get(VMContext, IdTy,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001193 PtrToInt8Ty,
1194 ProtocolList->getType(),
1195 InstanceMethodList->getType(),
1196 ClassMethodList->getType(),
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001197 OptionalInstanceMethodList->getType(),
1198 OptionalClassMethodList->getType(),
1199 PropertyList->getType(),
1200 OptionalPropertyList->getType(),
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001201 NULL);
Mike Stump1eb44332009-09-09 15:08:12 +00001202 std::vector<llvm::Constant*> Elements;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001203 // The isa pointer must be set to a magic number so the runtime knows it's
1204 // the correct layout.
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001205 int Version = CGM.getContext().getLangOptions().ObjCNonFragileABI ?
1206 NonFragileProtocolVersion : ProtocolVersion;
Owen Anderson3c4972d2009-07-29 18:54:39 +00001207 Elements.push_back(llvm::ConstantExpr::getIntToPtr(
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001208 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Version), IdTy));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001209 Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
1210 Elements.push_back(ProtocolList);
1211 Elements.push_back(InstanceMethodList);
1212 Elements.push_back(ClassMethodList);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001213 Elements.push_back(OptionalInstanceMethodList);
1214 Elements.push_back(OptionalClassMethodList);
1215 Elements.push_back(PropertyList);
1216 Elements.push_back(OptionalPropertyList);
Mike Stump1eb44332009-09-09 15:08:12 +00001217 ExistingProtocols[ProtocolName] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00001218 llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001219 ".objc_protocol"), IdTy);
1220}
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001221void CGObjCGNU::GenerateProtocolHolderCategory(void) {
1222 // Collect information about instance methods
1223 llvm::SmallVector<Selector, 1> MethodSels;
1224 llvm::SmallVector<llvm::Constant*, 1> MethodTypes;
1225
1226 std::vector<llvm::Constant*> Elements;
1227 const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack";
1228 const std::string CategoryName = "AnotherHack";
1229 Elements.push_back(MakeConstantString(CategoryName));
1230 Elements.push_back(MakeConstantString(ClassName));
1231 // Instance method list
1232 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
1233 ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy));
1234 // Class method list
1235 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
1236 ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy));
1237 // Protocol list
1238 llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrTy,
1239 ExistingProtocols.size());
1240 llvm::StructType *ProtocolListTy = llvm::StructType::get(VMContext,
1241 PtrTy, //Should be a recurisve pointer, but it's always NULL here.
1242 LongTy,//FIXME: Should be size_t
1243 ProtocolArrayTy,
1244 NULL);
1245 std::vector<llvm::Constant*> ProtocolElements;
1246 for (llvm::StringMapIterator<llvm::Constant*> iter =
1247 ExistingProtocols.begin(), endIter = ExistingProtocols.end();
1248 iter != endIter ; iter++) {
1249 llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(iter->getValue(),
1250 PtrTy);
1251 ProtocolElements.push_back(Ptr);
1252 }
1253 llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
1254 ProtocolElements);
1255 ProtocolElements.clear();
1256 ProtocolElements.push_back(NULLPtr);
1257 ProtocolElements.push_back(llvm::ConstantInt::get(LongTy,
1258 ExistingProtocols.size()));
1259 ProtocolElements.push_back(ProtocolArray);
1260 Elements.push_back(llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolListTy,
1261 ProtocolElements, ".objc_protocol_list"), PtrTy));
1262 Categories.push_back(llvm::ConstantExpr::getBitCast(
1263 MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty,
1264 PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
1265}
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001266
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001267void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Chris Lattner8ec03f52008-11-24 03:54:41 +00001268 std::string ClassName = OCD->getClassInterface()->getNameAsString();
1269 std::string CategoryName = OCD->getNameAsString();
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001270 // Collect information about instance methods
1271 llvm::SmallVector<Selector, 16> InstanceMethodSels;
1272 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
Douglas Gregor653f1b12009-04-23 01:02:12 +00001273 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001274 iter = OCD->instmeth_begin(), endIter = OCD->instmeth_end();
Douglas Gregor653f1b12009-04-23 01:02:12 +00001275 iter != endIter ; iter++) {
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001276 InstanceMethodSels.push_back((*iter)->getSelector());
1277 std::string TypeStr;
1278 CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
David Chisnall8a5a9aa2009-08-31 16:41:57 +00001279 InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001280 }
1281
1282 // Collect information about class methods
1283 llvm::SmallVector<Selector, 16> ClassMethodSels;
1284 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
Mike Stump1eb44332009-09-09 15:08:12 +00001285 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001286 iter = OCD->classmeth_begin(), endIter = OCD->classmeth_end();
Douglas Gregor653f1b12009-04-23 01:02:12 +00001287 iter != endIter ; iter++) {
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001288 ClassMethodSels.push_back((*iter)->getSelector());
1289 std::string TypeStr;
1290 CGM.getContext().getObjCEncodingForMethodDecl(*iter,TypeStr);
David Chisnall8a5a9aa2009-08-31 16:41:57 +00001291 ClassMethodTypes.push_back(MakeConstantString(TypeStr));
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001292 }
1293
1294 // Collect the names of referenced protocols
1295 llvm::SmallVector<std::string, 16> Protocols;
David Chisnallad9e06d2010-03-13 22:20:45 +00001296 const ObjCCategoryDecl *CatDecl = OCD->getCategoryDecl();
1297 const ObjCList<ObjCProtocolDecl> &Protos = CatDecl->getReferencedProtocols();
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001298 for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
1299 E = Protos.end(); I != E; ++I)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00001300 Protocols.push_back((*I)->getNameAsString());
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001301
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001302 std::vector<llvm::Constant*> Elements;
1303 Elements.push_back(MakeConstantString(CategoryName));
1304 Elements.push_back(MakeConstantString(ClassName));
Mike Stump1eb44332009-09-09 15:08:12 +00001305 // Instance method list
Owen Anderson3c4972d2009-07-29 18:54:39 +00001306 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattnera4210072008-06-26 05:08:00 +00001307 ClassName, CategoryName, InstanceMethodSels, InstanceMethodTypes,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001308 false), PtrTy));
1309 // Class method list
Owen Anderson3c4972d2009-07-29 18:54:39 +00001310 Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
Chris Lattnera4210072008-06-26 05:08:00 +00001311 ClassName, CategoryName, ClassMethodSels, ClassMethodTypes, true),
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001312 PtrTy));
1313 // Protocol list
Owen Anderson3c4972d2009-07-29 18:54:39 +00001314 Elements.push_back(llvm::ConstantExpr::getBitCast(
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001315 GenerateProtocolList(Protocols), PtrTy));
Owen Anderson3c4972d2009-07-29 18:54:39 +00001316 Categories.push_back(llvm::ConstantExpr::getBitCast(
Mike Stump1eb44332009-09-09 15:08:12 +00001317 MakeGlobal(llvm::StructType::get(VMContext, PtrToInt8Ty, PtrToInt8Ty,
Owen Anderson47a434f2009-08-05 23:18:46 +00001318 PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001319}
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001320
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001321llvm::Constant *CGObjCGNU::GeneratePropertyList(const ObjCImplementationDecl *OID,
1322 llvm::SmallVectorImpl<Selector> &InstanceMethodSels,
1323 llvm::SmallVectorImpl<llvm::Constant*> &InstanceMethodTypes) {
1324 ASTContext &Context = CGM.getContext();
1325 //
1326 // Property metadata: name, attributes, isSynthesized, setter name, setter
1327 // types, getter name, getter types.
1328 llvm::StructType *PropertyMetadataTy = llvm::StructType::get(VMContext,
1329 PtrToInt8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty,
1330 PtrToInt8Ty, NULL);
1331 std::vector<llvm::Constant*> Properties;
1332
1333
1334 // Add all of the property methods need adding to the method list and to the
1335 // property metadata list.
1336 for (ObjCImplDecl::propimpl_iterator
1337 iter = OID->propimpl_begin(), endIter = OID->propimpl_end();
1338 iter != endIter ; iter++) {
1339 std::vector<llvm::Constant*> Fields;
1340 ObjCPropertyDecl *property = (*iter)->getPropertyDecl();
David Chisnall42ba04a2010-02-26 01:11:38 +00001341 ObjCPropertyImplDecl *propertyImpl = *iter;
1342 bool isSynthesized = (propertyImpl->getPropertyImplementation() ==
1343 ObjCPropertyImplDecl::Synthesize);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001344
1345 Fields.push_back(MakeConstantString(property->getNameAsString()));
1346 Fields.push_back(llvm::ConstantInt::get(Int8Ty,
1347 property->getPropertyAttributes()));
David Chisnall42ba04a2010-02-26 01:11:38 +00001348 Fields.push_back(llvm::ConstantInt::get(Int8Ty, isSynthesized));
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001349 if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001350 std::string TypeStr;
1351 Context.getObjCEncodingForMethodDecl(getter,TypeStr);
1352 llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
David Chisnall42ba04a2010-02-26 01:11:38 +00001353 if (isSynthesized) {
1354 InstanceMethodTypes.push_back(TypeEncoding);
1355 InstanceMethodSels.push_back(getter->getSelector());
1356 }
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001357 Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
1358 Fields.push_back(TypeEncoding);
1359 } else {
1360 Fields.push_back(NULLPtr);
1361 Fields.push_back(NULLPtr);
1362 }
1363 if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001364 std::string TypeStr;
1365 Context.getObjCEncodingForMethodDecl(setter,TypeStr);
1366 llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
David Chisnall42ba04a2010-02-26 01:11:38 +00001367 if (isSynthesized) {
1368 InstanceMethodTypes.push_back(TypeEncoding);
1369 InstanceMethodSels.push_back(setter->getSelector());
1370 }
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001371 Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
1372 Fields.push_back(TypeEncoding);
1373 } else {
1374 Fields.push_back(NULLPtr);
1375 Fields.push_back(NULLPtr);
1376 }
1377 Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
1378 }
1379 llvm::ArrayType *PropertyArrayTy =
1380 llvm::ArrayType::get(PropertyMetadataTy, Properties.size());
1381 llvm::Constant *PropertyArray = llvm::ConstantArray::get(PropertyArrayTy,
1382 Properties);
1383 llvm::Constant* PropertyListInitFields[] =
1384 {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
1385
1386 llvm::Constant *PropertyListInit =
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001387 llvm::ConstantStruct::get(VMContext, PropertyListInitFields, 3, false);
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001388 return new llvm::GlobalVariable(TheModule, PropertyListInit->getType(), false,
1389 llvm::GlobalValue::InternalLinkage, PropertyListInit,
1390 ".objc_property_list");
1391}
1392
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001393void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
1394 ASTContext &Context = CGM.getContext();
1395
1396 // Get the superclass name.
Mike Stump1eb44332009-09-09 15:08:12 +00001397 const ObjCInterfaceDecl * SuperClassDecl =
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001398 OID->getClassInterface()->getSuperClass();
Chris Lattner8ec03f52008-11-24 03:54:41 +00001399 std::string SuperClassName;
Chris Lattner2a8e4e12009-06-15 01:09:11 +00001400 if (SuperClassDecl) {
Chris Lattner8ec03f52008-11-24 03:54:41 +00001401 SuperClassName = SuperClassDecl->getNameAsString();
Chris Lattner2a8e4e12009-06-15 01:09:11 +00001402 EmitClassRef(SuperClassName);
1403 }
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001404
1405 // Get the class name
Chris Lattner09dc6662009-04-01 02:00:48 +00001406 ObjCInterfaceDecl *ClassDecl =
1407 const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
Chris Lattner8ec03f52008-11-24 03:54:41 +00001408 std::string ClassName = ClassDecl->getNameAsString();
Chris Lattner2a8e4e12009-06-15 01:09:11 +00001409 // Emit the symbol that is used to generate linker errors if this class is
1410 // referenced in other modules but not declared.
Fariborz Jahanianc51db232009-07-03 15:10:14 +00001411 std::string classSymbolName = "__objc_class_name_" + ClassName;
Mike Stump1eb44332009-09-09 15:08:12 +00001412 if (llvm::GlobalVariable *symbol =
Fariborz Jahanianc51db232009-07-03 15:10:14 +00001413 TheModule.getGlobalVariable(classSymbolName)) {
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001414 symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
Fariborz Jahanianc51db232009-07-03 15:10:14 +00001415 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00001416 new llvm::GlobalVariable(TheModule, LongTy, false,
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001417 llvm::GlobalValue::ExternalLinkage, llvm::ConstantInt::get(LongTy, 0),
Owen Anderson1c431b32009-07-08 19:05:04 +00001418 classSymbolName);
Fariborz Jahanianc51db232009-07-03 15:10:14 +00001419 }
Mike Stump1eb44332009-09-09 15:08:12 +00001420
Daniel Dunbar2bebbf02009-05-03 10:46:44 +00001421 // Get the size of instances.
1422 int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8;
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001423
1424 // Collect information about instance variables.
1425 llvm::SmallVector<llvm::Constant*, 16> IvarNames;
1426 llvm::SmallVector<llvm::Constant*, 16> IvarTypes;
1427 llvm::SmallVector<llvm::Constant*, 16> IvarOffsets;
Mike Stump1eb44332009-09-09 15:08:12 +00001428
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001429 std::vector<llvm::Constant*> IvarOffsetValues;
1430
Mike Stump1eb44332009-09-09 15:08:12 +00001431 int superInstanceSize = !SuperClassDecl ? 0 :
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00001432 Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize() / 8;
1433 // For non-fragile ivars, set the instance size to 0 - {the size of just this
1434 // class}. The runtime will then set this to the correct value on load.
1435 if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
1436 instanceSize = 0 - (instanceSize - superInstanceSize);
1437 }
David Chisnall7f63cb02010-04-19 00:45:34 +00001438
1439 // Collect declared and synthesized ivars.
1440 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
1441 CGM.getContext().ShallowCollectObjCIvars(ClassDecl, OIvars);
1442
1443 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
1444 ObjCIvarDecl *IVD = OIvars[i];
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001445 // Store the name
David Chisnall7f63cb02010-04-19 00:45:34 +00001446 IvarNames.push_back(MakeConstantString(IVD->getNameAsString()));
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001447 // Get the type encoding for this ivar
1448 std::string TypeStr;
David Chisnall7f63cb02010-04-19 00:45:34 +00001449 Context.getObjCEncodingForType(IVD->getType(), TypeStr);
David Chisnall8a5a9aa2009-08-31 16:41:57 +00001450 IvarTypes.push_back(MakeConstantString(TypeStr));
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001451 // Get the offset
David Chisnalld901da52010-04-19 01:37:25 +00001452 uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
David Chisnallaecbf242009-11-17 19:32:15 +00001453 uint64_t Offset = BaseOffset;
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00001454 if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001455 Offset = BaseOffset - superInstanceSize;
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00001456 }
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001457 IvarOffsets.push_back(
Owen Anderson0032b272009-08-13 21:57:51 +00001458 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset));
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001459 IvarOffsetValues.push_back(new llvm::GlobalVariable(TheModule, IntTy,
1460 false, llvm::GlobalValue::ExternalLinkage,
1461 llvm::ConstantInt::get(IntTy, BaseOffset),
1462 "__objc_ivar_offset_value_" + ClassName +"." +
David Chisnall7f63cb02010-04-19 00:45:34 +00001463 IVD->getNameAsString()));
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001464 }
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001465 llvm::Constant *IvarOffsetArrayInit =
1466 llvm::ConstantArray::get(llvm::ArrayType::get(PtrToIntTy,
1467 IvarOffsetValues.size()), IvarOffsetValues);
1468 llvm::GlobalVariable *IvarOffsetArray = new llvm::GlobalVariable(TheModule,
1469 IvarOffsetArrayInit->getType(), false,
1470 llvm::GlobalValue::InternalLinkage, IvarOffsetArrayInit,
1471 ".ivar.offsets");
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001472
1473 // Collect information about instance methods
1474 llvm::SmallVector<Selector, 16> InstanceMethodSels;
1475 llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes;
Mike Stump1eb44332009-09-09 15:08:12 +00001476 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001477 iter = OID->instmeth_begin(), endIter = OID->instmeth_end();
Douglas Gregor653f1b12009-04-23 01:02:12 +00001478 iter != endIter ; iter++) {
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001479 InstanceMethodSels.push_back((*iter)->getSelector());
1480 std::string TypeStr;
1481 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
David Chisnall8a5a9aa2009-08-31 16:41:57 +00001482 InstanceMethodTypes.push_back(MakeConstantString(TypeStr));
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001483 }
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001484
1485 llvm::Constant *Properties = GeneratePropertyList(OID, InstanceMethodSels,
1486 InstanceMethodTypes);
1487
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001488
1489 // Collect information about class methods
1490 llvm::SmallVector<Selector, 16> ClassMethodSels;
1491 llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes;
Douglas Gregor653f1b12009-04-23 01:02:12 +00001492 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001493 iter = OID->classmeth_begin(), endIter = OID->classmeth_end();
Douglas Gregor653f1b12009-04-23 01:02:12 +00001494 iter != endIter ; iter++) {
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001495 ClassMethodSels.push_back((*iter)->getSelector());
1496 std::string TypeStr;
1497 Context.getObjCEncodingForMethodDecl((*iter),TypeStr);
David Chisnall8a5a9aa2009-08-31 16:41:57 +00001498 ClassMethodTypes.push_back(MakeConstantString(TypeStr));
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001499 }
1500 // Collect the names of referenced protocols
1501 llvm::SmallVector<std::string, 16> Protocols;
1502 const ObjCList<ObjCProtocolDecl> &Protos =ClassDecl->getReferencedProtocols();
1503 for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
1504 E = Protos.end(); I != E; ++I)
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00001505 Protocols.push_back((*I)->getNameAsString());
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001506
1507
1508
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001509 // Get the superclass pointer.
1510 llvm::Constant *SuperClass;
Chris Lattner8ec03f52008-11-24 03:54:41 +00001511 if (!SuperClassName.empty()) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001512 SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
1513 } else {
Owen Anderson03e20502009-07-30 23:11:26 +00001514 SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001515 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001516 // Empty vector used to construct empty method lists
1517 llvm::SmallVector<llvm::Constant*, 1> empty;
1518 // Generate the method and instance variable lists
1519 llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
Chris Lattnera4210072008-06-26 05:08:00 +00001520 InstanceMethodSels, InstanceMethodTypes, false);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001521 llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
Chris Lattnera4210072008-06-26 05:08:00 +00001522 ClassMethodSels, ClassMethodTypes, true);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001523 llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
1524 IvarOffsets);
Mike Stump1eb44332009-09-09 15:08:12 +00001525 // Irrespective of whether we are compiling for a fragile or non-fragile ABI,
David Chisnall8a5a9aa2009-08-31 16:41:57 +00001526 // we emit a symbol containing the offset for each ivar in the class. This
1527 // allows code compiled for the non-Fragile ABI to inherit from code compiled
1528 // for the legacy ABI, without causing problems. The converse is also
1529 // possible, but causes all ivar accesses to be fragile.
1530 int i = 0;
1531 // Offset pointer for getting at the correct field in the ivar list when
1532 // setting up the alias. These are: The base address for the global, the
1533 // ivar array (second field), the ivar in this list (set for each ivar), and
1534 // the offset (third field in ivar structure)
1535 const llvm::Type *IndexTy = llvm::Type::getInt32Ty(VMContext);
1536 llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
Mike Stump1eb44332009-09-09 15:08:12 +00001537 llvm::ConstantInt::get(IndexTy, 1), 0,
David Chisnall8a5a9aa2009-08-31 16:41:57 +00001538 llvm::ConstantInt::get(IndexTy, 2) };
1539
1540 for (ObjCInterfaceDecl::ivar_iterator iter = ClassDecl->ivar_begin(),
1541 endIter = ClassDecl->ivar_end() ; iter != endIter ; iter++) {
1542 const std::string Name = "__objc_ivar_offset_" + ClassName + '.'
1543 +(*iter)->getNameAsString();
1544 offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, i++);
1545 // Get the correct ivar field
1546 llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
1547 IvarList, offsetPointerIndexes, 4);
1548 // Get the existing alias, if one exists.
1549 llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
1550 if (offset) {
1551 offset->setInitializer(offsetValue);
1552 // If this is the real definition, change its linkage type so that
1553 // different modules will use this one, rather than their private
1554 // copy.
1555 offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
1556 } else {
1557 // Add a new alias if there isn't one already.
1558 offset = new llvm::GlobalVariable(TheModule, offsetValue->getType(),
1559 false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
1560 }
1561 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001562 //Generate metaclass for class methods
1563 llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
David Chisnall18044632009-11-16 19:05:54 +00001564 NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList(
David Chisnall8c757f92010-04-28 14:29:56 +00001565 empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr, NULLPtr, true);
Daniel Dunbar5efccb12009-05-04 15:31:17 +00001566
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001567 // Generate the class structure
Chris Lattner8ec03f52008-11-24 03:54:41 +00001568 llvm::Constant *ClassStruct =
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001569 GenerateClassStructure(MetaClassStruct, SuperClass, 0x11L,
Chris Lattner8ec03f52008-11-24 03:54:41 +00001570 ClassName.c_str(), 0,
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001571 llvm::ConstantInt::get(LongTy, instanceSize), IvarList,
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001572 MethodList, GenerateProtocolList(Protocols), IvarOffsetArray,
1573 Properties);
Daniel Dunbar5efccb12009-05-04 15:31:17 +00001574
1575 // Resolve the class aliases, if they exist.
1576 if (ClassPtrAlias) {
1577 ClassPtrAlias->setAliasee(
Owen Anderson3c4972d2009-07-29 18:54:39 +00001578 llvm::ConstantExpr::getBitCast(ClassStruct, IdTy));
Daniel Dunbar5efccb12009-05-04 15:31:17 +00001579 ClassPtrAlias = 0;
1580 }
1581 if (MetaClassPtrAlias) {
1582 MetaClassPtrAlias->setAliasee(
Owen Anderson3c4972d2009-07-29 18:54:39 +00001583 llvm::ConstantExpr::getBitCast(MetaClassStruct, IdTy));
Daniel Dunbar5efccb12009-05-04 15:31:17 +00001584 MetaClassPtrAlias = 0;
1585 }
1586
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001587 // Add class structure to list to be added to the symtab later
Owen Anderson3c4972d2009-07-29 18:54:39 +00001588 ClassStruct = llvm::ConstantExpr::getBitCast(ClassStruct, PtrToInt8Ty);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001589 Classes.push_back(ClassStruct);
1590}
1591
Fariborz Jahanianc38e9af2009-06-23 21:47:46 +00001592
Mike Stump1eb44332009-09-09 15:08:12 +00001593llvm::Function *CGObjCGNU::ModuleInitFunction() {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001594 // Only emit an ObjC load function if no Objective-C stuff has been called
1595 if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
1596 ExistingProtocols.empty() && TypedSelectors.empty() &&
Anton Korobeynikov5f58b912008-06-01 15:14:46 +00001597 UntypedSelectors.empty())
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001598 return NULL;
Eli Friedman1b8956e2008-06-01 16:00:02 +00001599
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001600 // Add all referenced protocols to a category.
1601 GenerateProtocolHolderCategory();
1602
Chris Lattnere160c9b2009-01-27 05:06:01 +00001603 const llvm::StructType *SelStructTy = dyn_cast<llvm::StructType>(
1604 SelectorTy->getElementType());
1605 const llvm::Type *SelStructPtrTy = SelectorTy;
1606 bool isSelOpaque = false;
1607 if (SelStructTy == 0) {
Owen Anderson47a434f2009-08-05 23:18:46 +00001608 SelStructTy = llvm::StructType::get(VMContext, PtrToInt8Ty,
1609 PtrToInt8Ty, NULL);
Owen Anderson96e0fc72009-07-29 22:16:19 +00001610 SelStructPtrTy = llvm::PointerType::getUnqual(SelStructTy);
Chris Lattnere160c9b2009-01-27 05:06:01 +00001611 isSelOpaque = true;
1612 }
1613
Eli Friedman1b8956e2008-06-01 16:00:02 +00001614 // Name the ObjC types to make the IR a bit easier to read
Chris Lattnere160c9b2009-01-27 05:06:01 +00001615 TheModule.addTypeName(".objc_selector", SelStructPtrTy);
Eli Friedman1b8956e2008-06-01 16:00:02 +00001616 TheModule.addTypeName(".objc_id", IdTy);
1617 TheModule.addTypeName(".objc_imp", IMPTy);
1618
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001619 std::vector<llvm::Constant*> Elements;
Chris Lattner71238f62009-04-25 23:19:45 +00001620 llvm::Constant *Statics = NULLPtr;
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001621 // Generate statics list:
Chris Lattner71238f62009-04-25 23:19:45 +00001622 if (ConstantStrings.size()) {
Owen Anderson96e0fc72009-07-29 22:16:19 +00001623 llvm::ArrayType *StaticsArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
Chris Lattner71238f62009-04-25 23:19:45 +00001624 ConstantStrings.size() + 1);
1625 ConstantStrings.push_back(NULLPtr);
David Chisnall8a5a9aa2009-08-31 16:41:57 +00001626
Daniel Dunbar1b096952009-11-29 02:38:47 +00001627 llvm::StringRef StringClass = CGM.getLangOptions().ObjCConstantStringClass;
1628 if (StringClass.empty()) StringClass = "NXConstantString";
David Chisnall8a5a9aa2009-08-31 16:41:57 +00001629 Elements.push_back(MakeConstantString(StringClass,
1630 ".objc_static_class_name"));
Owen Anderson7db6d832009-07-28 18:33:04 +00001631 Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy,
Chris Lattner71238f62009-04-25 23:19:45 +00001632 ConstantStrings));
Mike Stump1eb44332009-09-09 15:08:12 +00001633 llvm::StructType *StaticsListTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00001634 llvm::StructType::get(VMContext, PtrToInt8Ty, StaticsArrayTy, NULL);
Owen Andersona1cf15f2009-07-14 23:10:40 +00001635 llvm::Type *StaticsListPtrTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +00001636 llvm::PointerType::getUnqual(StaticsListTy);
Chris Lattner71238f62009-04-25 23:19:45 +00001637 Statics = MakeGlobal(StaticsListTy, Elements, ".objc_statics");
Mike Stump1eb44332009-09-09 15:08:12 +00001638 llvm::ArrayType *StaticsListArrayTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +00001639 llvm::ArrayType::get(StaticsListPtrTy, 2);
Chris Lattner71238f62009-04-25 23:19:45 +00001640 Elements.clear();
1641 Elements.push_back(Statics);
Owen Andersonc9c88b42009-07-31 20:28:54 +00001642 Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
Chris Lattner71238f62009-04-25 23:19:45 +00001643 Statics = MakeGlobal(StaticsListArrayTy, Elements, ".objc_statics_ptr");
Owen Anderson3c4972d2009-07-29 18:54:39 +00001644 Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
Chris Lattner71238f62009-04-25 23:19:45 +00001645 }
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001646 // Array of classes, categories, and constant objects
Owen Anderson96e0fc72009-07-29 22:16:19 +00001647 llvm::ArrayType *ClassListTy = llvm::ArrayType::get(PtrToInt8Ty,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001648 Classes.size() + Categories.size() + 2);
Mike Stump1eb44332009-09-09 15:08:12 +00001649 llvm::StructType *SymTabTy = llvm::StructType::get(VMContext,
Owen Anderson47a434f2009-08-05 23:18:46 +00001650 LongTy, SelStructPtrTy,
Owen Anderson0032b272009-08-13 21:57:51 +00001651 llvm::Type::getInt16Ty(VMContext),
1652 llvm::Type::getInt16Ty(VMContext),
Chris Lattner630404b2008-06-26 04:10:42 +00001653 ClassListTy, NULL);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001654
1655 Elements.clear();
1656 // Pointer to an array of selectors used in this module.
1657 std::vector<llvm::Constant*> Selectors;
1658 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
1659 iter = TypedSelectors.begin(), iterEnd = TypedSelectors.end();
1660 iter != iterEnd ; ++iter) {
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001661 Elements.push_back(ExportUniqueString(iter->first.first, ".objc_sel_name"));
David Chisnalla7c5b082009-09-14 19:04:10 +00001662 Elements.push_back(MakeConstantString(iter->first.second,
Chris Lattner630404b2008-06-26 04:10:42 +00001663 ".objc_sel_types"));
Owen Anderson08e25242009-07-27 22:29:56 +00001664 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001665 Elements.clear();
1666 }
1667 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
1668 iter = UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
Chris Lattner630404b2008-06-26 04:10:42 +00001669 iter != iterEnd; ++iter) {
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001670 Elements.push_back(
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001671 ExportUniqueString(iter->getKeyData(), ".objc_sel_name"));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001672 Elements.push_back(NULLPtr);
Owen Anderson08e25242009-07-27 22:29:56 +00001673 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001674 Elements.clear();
1675 }
1676 Elements.push_back(NULLPtr);
1677 Elements.push_back(NULLPtr);
Owen Anderson08e25242009-07-27 22:29:56 +00001678 Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001679 Elements.clear();
1680 // Number of static selectors
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001681 Elements.push_back(llvm::ConstantInt::get(LongTy, Selectors.size() ));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001682 llvm::Constant *SelectorList = MakeGlobal(
Owen Anderson96e0fc72009-07-29 22:16:19 +00001683 llvm::ArrayType::get(SelStructTy, Selectors.size()), Selectors,
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001684 ".objc_selector_list");
Mike Stump1eb44332009-09-09 15:08:12 +00001685 Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList,
Chris Lattnere160c9b2009-01-27 05:06:01 +00001686 SelStructPtrTy));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001687
1688 // Now that all of the static selectors exist, create pointers to them.
1689 int index = 0;
1690 for (std::map<TypedSelector, llvm::GlobalAlias*>::iterator
1691 iter=TypedSelectors.begin(), iterEnd =TypedSelectors.end();
1692 iter != iterEnd; ++iter) {
1693 llvm::Constant *Idxs[] = {Zeros[0],
Owen Anderson0032b272009-08-13 21:57:51 +00001694 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]};
Daniel Dunbar6d5a1c22010-02-03 20:11:42 +00001695 llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy,
David Chisnall22b88272010-05-09 01:01:43 +00001696 true, llvm::GlobalValue::LinkOnceODRLinkage,
1697 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
1698 MangleSelectorTypes(".objc_sel_ptr"+iter->first.first+"."+
1699 iter->first.second));
Chris Lattnere160c9b2009-01-27 05:06:01 +00001700 // If selectors are defined as an opaque type, cast the pointer to this
1701 // type.
1702 if (isSelOpaque) {
Daniel Dunbar6d5a1c22010-02-03 20:11:42 +00001703 SelPtr = llvm::ConstantExpr::getBitCast(SelPtr,
1704 llvm::PointerType::getUnqual(SelectorTy));
Chris Lattnere160c9b2009-01-27 05:06:01 +00001705 }
David Chisnall87935a82010-05-08 20:58:05 +00001706 (*iter).second->replaceAllUsesWith(SelPtr);
1707 (*iter).second->eraseFromParent();
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001708 }
1709 for (llvm::StringMap<llvm::GlobalAlias*>::iterator
1710 iter=UntypedSelectors.begin(), iterEnd = UntypedSelectors.end();
1711 iter != iterEnd; iter++) {
1712 llvm::Constant *Idxs[] = {Zeros[0],
Owen Anderson0032b272009-08-13 21:57:51 +00001713 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), index++), Zeros[0]};
David Chisnall87935a82010-05-08 20:58:05 +00001714 llvm::Constant *SelPtr = new llvm::GlobalVariable(TheModule, SelStructPtrTy,
David Chisnall22b88272010-05-09 01:01:43 +00001715 true, llvm::GlobalValue::LinkOnceODRLinkage,
1716 llvm::ConstantExpr::getGetElementPtr(SelectorList, Idxs, 2),
1717 MangleSelectorTypes(std::string(".objc_sel_ptr")+iter->getKey().str()));
Chris Lattnere160c9b2009-01-27 05:06:01 +00001718 // If selectors are defined as an opaque type, cast the pointer to this
1719 // type.
1720 if (isSelOpaque) {
Daniel Dunbar6d5a1c22010-02-03 20:11:42 +00001721 SelPtr = llvm::ConstantExpr::getBitCast(SelPtr,
1722 llvm::PointerType::getUnqual(SelectorTy));
Chris Lattnere160c9b2009-01-27 05:06:01 +00001723 }
David Chisnall87935a82010-05-08 20:58:05 +00001724 (*iter).second->replaceAllUsesWith(SelPtr);
1725 (*iter).second->eraseFromParent();
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001726 }
1727 // Number of classes defined.
Mike Stump1eb44332009-09-09 15:08:12 +00001728 Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext),
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001729 Classes.size()));
1730 // Number of categories defined
Mike Stump1eb44332009-09-09 15:08:12 +00001731 Elements.push_back(llvm::ConstantInt::get(llvm::Type::getInt16Ty(VMContext),
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001732 Categories.size()));
1733 // Create an array of classes, then categories, then static object instances
1734 Classes.insert(Classes.end(), Categories.begin(), Categories.end());
1735 // NULL-terminated list of static object instances (mainly constant strings)
1736 Classes.push_back(Statics);
1737 Classes.push_back(NULLPtr);
Owen Anderson7db6d832009-07-28 18:33:04 +00001738 llvm::Constant *ClassList = llvm::ConstantArray::get(ClassListTy, Classes);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001739 Elements.push_back(ClassList);
Mike Stump1eb44332009-09-09 15:08:12 +00001740 // Construct the symbol table
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001741 llvm::Constant *SymTab= MakeGlobal(SymTabTy, Elements);
1742
1743 // The symbol table is contained in a module which has some version-checking
1744 // constants
Owen Anderson47a434f2009-08-05 23:18:46 +00001745 llvm::StructType * ModuleTy = llvm::StructType::get(VMContext, LongTy, LongTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00001746 PtrToInt8Ty, llvm::PointerType::getUnqual(SymTabTy), NULL);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001747 Elements.clear();
1748 // Runtime version used for compatibility checking.
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00001749 if (CGM.getContext().getLangOptions().ObjCNonFragileABI) {
Mike Stump1eb44332009-09-09 15:08:12 +00001750 Elements.push_back(llvm::ConstantInt::get(LongTy,
Fariborz Jahaniand9a1db32009-09-10 21:48:21 +00001751 NonFragileRuntimeVersion));
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00001752 } else {
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001753 Elements.push_back(llvm::ConstantInt::get(LongTy, RuntimeVersion));
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00001754 }
Fariborz Jahanian91a0b512009-04-01 19:49:42 +00001755 // sizeof(ModuleTy)
Benjamin Kramer74a8bbf2010-02-09 19:31:24 +00001756 llvm::TargetData td(&TheModule);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001757 Elements.push_back(llvm::ConstantInt::get(LongTy,
Owen Andersona1cf15f2009-07-14 23:10:40 +00001758 td.getTypeSizeInBits(ModuleTy)/8));
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001759 //FIXME: Should be the path to the file where this module was declared
1760 Elements.push_back(NULLPtr);
1761 Elements.push_back(SymTab);
1762 llvm::Value *Module = MakeGlobal(ModuleTy, Elements);
1763
1764 // Create the load function calling the runtime entry point with the module
1765 // structure
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001766 llvm::Function * LoadFunction = llvm::Function::Create(
Owen Anderson0032b272009-08-13 21:57:51 +00001767 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001768 llvm::GlobalValue::InternalLinkage, ".objc_load_function",
1769 &TheModule);
Owen Anderson0032b272009-08-13 21:57:51 +00001770 llvm::BasicBlock *EntryBB =
1771 llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
Owen Andersona1cf15f2009-07-14 23:10:40 +00001772 CGBuilderTy Builder(VMContext);
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001773 Builder.SetInsertPoint(EntryBB);
Fariborz Jahanian26c82942009-03-30 18:02:14 +00001774
1775 std::vector<const llvm::Type*> Params(1,
Owen Anderson96e0fc72009-07-29 22:16:19 +00001776 llvm::PointerType::getUnqual(ModuleTy));
1777 llvm::Value *Register = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
Owen Anderson0032b272009-08-13 21:57:51 +00001778 llvm::Type::getVoidTy(VMContext), Params, true), "__objc_exec_class");
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001779 Builder.CreateCall(Register, Module);
1780 Builder.CreateRetVoid();
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00001781
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001782 return LoadFunction;
1783}
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001784
Fariborz Jahanian679a5022009-01-10 21:06:09 +00001785llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
Mike Stump1eb44332009-09-09 15:08:12 +00001786 const ObjCContainerDecl *CD) {
1787 const ObjCCategoryImplDecl *OCD =
Steve Naroff3e0a5402009-01-08 19:41:02 +00001788 dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext());
Chris Lattner077bf5e2008-11-24 03:33:13 +00001789 std::string CategoryName = OCD ? OCD->getNameAsString() : "";
David Chisnall4c8c8e92010-03-20 19:53:29 +00001790 std::string ClassName = CD->getName();
Chris Lattner077bf5e2008-11-24 03:33:13 +00001791 std::string MethodName = OMD->getSelector().getAsString();
Douglas Gregorf8d49f62009-01-09 17:18:27 +00001792 bool isClassMethod = !OMD->isInstanceMethod();
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001793
Daniel Dunbar541b63b2009-02-02 23:23:47 +00001794 CodeGenTypes &Types = CGM.getTypes();
Mike Stump1eb44332009-09-09 15:08:12 +00001795 const llvm::FunctionType *MethodTy =
Daniel Dunbar541b63b2009-02-02 23:23:47 +00001796 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Anton Korobeynikov20ff3102008-06-01 14:13:53 +00001797 std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
1798 MethodName, isClassMethod);
1799
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001800 llvm::Function *Method
Mike Stump1eb44332009-09-09 15:08:12 +00001801 = llvm::Function::Create(MethodTy,
1802 llvm::GlobalValue::InternalLinkage,
1803 FunctionName,
1804 &TheModule);
Chris Lattner391d77a2008-03-30 23:03:07 +00001805 return Method;
1806}
1807
Daniel Dunbar49f66022008-09-24 03:38:44 +00001808llvm::Function *CGObjCGNU::GetPropertyGetFunction() {
Mike Stump1eb44332009-09-09 15:08:12 +00001809 std::vector<const llvm::Type*> Params;
1810 const llvm::Type *BoolTy =
1811 CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
1812 Params.push_back(IdTy);
1813 Params.push_back(SelectorTy);
David Chisnall7f63cb02010-04-19 00:45:34 +00001814 Params.push_back(IntTy);
Mike Stump1eb44332009-09-09 15:08:12 +00001815 Params.push_back(BoolTy);
David Chisnall7f63cb02010-04-19 00:45:34 +00001816 // void objc_getProperty (id, SEL, int, bool)
Mike Stump1eb44332009-09-09 15:08:12 +00001817 const llvm::FunctionType *FTy =
1818 llvm::FunctionType::get(IdTy, Params, false);
1819 return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
1820 "objc_getProperty"));
Daniel Dunbar49f66022008-09-24 03:38:44 +00001821}
1822
1823llvm::Function *CGObjCGNU::GetPropertySetFunction() {
Mike Stump1eb44332009-09-09 15:08:12 +00001824 std::vector<const llvm::Type*> Params;
1825 const llvm::Type *BoolTy =
1826 CGM.getTypes().ConvertType(CGM.getContext().BoolTy);
1827 Params.push_back(IdTy);
1828 Params.push_back(SelectorTy);
David Chisnall7f63cb02010-04-19 00:45:34 +00001829 Params.push_back(IntTy);
Mike Stump1eb44332009-09-09 15:08:12 +00001830 Params.push_back(IdTy);
1831 Params.push_back(BoolTy);
1832 Params.push_back(BoolTy);
David Chisnall7f63cb02010-04-19 00:45:34 +00001833 // void objc_setProperty (id, SEL, int, id, bool, bool)
Mike Stump1eb44332009-09-09 15:08:12 +00001834 const llvm::FunctionType *FTy =
1835 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false);
1836 return cast<llvm::Function>(CGM.CreateRuntimeFunction(FTy,
1837 "objc_setProperty"));
Daniel Dunbar49f66022008-09-24 03:38:44 +00001838}
1839
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001840// FIXME. Implement this.
1841llvm::Function *CGObjCGNU::GetCopyStructFunction() {
1842 return 0;
1843}
1844
Daniel Dunbar309a4362009-07-24 07:40:24 +00001845llvm::Constant *CGObjCGNU::EnumerationMutationFunction() {
1846 CodeGen::CodeGenTypes &Types = CGM.getTypes();
1847 ASTContext &Ctx = CGM.getContext();
1848 // void objc_enumerationMutation (id)
John McCallead608a2010-02-26 00:48:12 +00001849 llvm::SmallVector<CanQualType,1> Params;
David Chisnall0f436562009-08-17 16:35:33 +00001850 Params.push_back(ASTIdTy);
Daniel Dunbar309a4362009-07-24 07:40:24 +00001851 const llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +00001852 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +00001853 FunctionType::ExtInfo()), false);
Daniel Dunbar309a4362009-07-24 07:40:24 +00001854 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
Anders Carlsson2abd89c2008-08-31 04:05:03 +00001855}
1856
John McCallf1549f62010-07-06 01:34:17 +00001857void CGObjCGNU::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1858 const ObjCAtSynchronizedStmt &S) {
1859 std::vector<const llvm::Type*> Args(1, IdTy);
1860 llvm::FunctionType *FTy =
1861 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattner5dc08672009-05-08 00:11:50 +00001862
John McCallf1549f62010-07-06 01:34:17 +00001863 // Evaluate the lock operand. This should dominate the cleanup.
1864 llvm::Value *SyncArg =
1865 CGF.EmitScalarExpr(S.getSynchExpr());
Chris Lattner5dc08672009-05-08 00:11:50 +00001866
John McCallf1549f62010-07-06 01:34:17 +00001867 // Acquire the lock.
1868 llvm::Value *SyncEnter = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
1869 SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy);
1870 CGF.Builder.CreateCall(SyncEnter, SyncArg);
Chris Lattner5dc08672009-05-08 00:11:50 +00001871
John McCallf1549f62010-07-06 01:34:17 +00001872 // Register an all-paths cleanup to release the lock.
1873 {
John McCallda65ea82010-07-13 20:32:21 +00001874 CodeGenFunction::CleanupBlock ReleaseScope(CGF, NormalAndEHCleanup);
Chris Lattnerd6a99072009-05-11 18:16:28 +00001875
Chris Lattnerd6a99072009-05-11 18:16:28 +00001876 llvm::Value *SyncExit = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
Chris Lattnerd6a99072009-05-11 18:16:28 +00001877 SyncArg = CGF.Builder.CreateBitCast(SyncArg, IdTy);
1878 CGF.Builder.CreateCall(SyncExit, SyncArg);
Chris Lattner5dc08672009-05-08 00:11:50 +00001879 }
1880
John McCallf1549f62010-07-06 01:34:17 +00001881 // Emit the body of the statement.
1882 CGF.EmitStmt(S.getSynchBody());
Chris Lattner5dc08672009-05-08 00:11:50 +00001883
John McCallf1549f62010-07-06 01:34:17 +00001884 // Pop the lock-release cleanup.
1885 CGF.PopCleanupBlock();
1886}
Chris Lattner5dc08672009-05-08 00:11:50 +00001887
John McCallf1549f62010-07-06 01:34:17 +00001888namespace {
1889 struct CatchHandler {
1890 const VarDecl *Variable;
1891 const Stmt *Body;
1892 llvm::BasicBlock *Block;
1893 llvm::Value *TypeInfo;
1894 };
1895}
David Chisnall0faa5162009-12-24 02:26:34 +00001896
John McCallf1549f62010-07-06 01:34:17 +00001897void CGObjCGNU::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1898 const ObjCAtTryStmt &S) {
1899 // Unlike the Apple non-fragile runtimes, which also uses
1900 // unwind-based zero cost exceptions, the GNU Objective C runtime's
1901 // EH support isn't a veneer over C++ EH. Instead, exception
1902 // objects are created by __objc_exception_throw and destroyed by
1903 // the personality function; this avoids the need for bracketing
1904 // catch handlers with calls to __blah_begin_catch/__blah_end_catch
1905 // (or even _Unwind_DeleteException), but probably doesn't
1906 // interoperate very well with foreign exceptions.
1907
1908 // Jump destination for falling out of catch bodies.
1909 CodeGenFunction::JumpDest Cont;
1910 if (S.getNumCatchStmts())
1911 Cont = CGF.getJumpDestInCurrentScope("eh.cont");
1912
1913 // We handle @finally statements by pushing them as a cleanup
1914 // before entering the catch.
1915 CodeGenFunction::FinallyInfo FinallyInfo;
1916 if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt()) {
1917 std::vector<const llvm::Type*> Args(1, IdTy);
1918 llvm::FunctionType *FTy =
1919 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
1920 llvm::Constant *Rethrow =
1921 CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
1922
1923 FinallyInfo = CGF.EnterFinallyBlock(Finally->getFinallyBody(), 0, 0,
1924 Rethrow);
David Chisnall0faa5162009-12-24 02:26:34 +00001925 }
Mike Stump1eb44332009-09-09 15:08:12 +00001926
John McCallf1549f62010-07-06 01:34:17 +00001927 llvm::SmallVector<CatchHandler, 8> Handlers;
1928
1929 // Enter the catch, if there is one.
1930 if (S.getNumCatchStmts()) {
1931 for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
1932 const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I);
1933 const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
1934
1935 Handlers.push_back(CatchHandler());
1936 CatchHandler &Handler = Handlers.back();
1937 Handler.Variable = CatchDecl;
1938 Handler.Body = CatchStmt->getCatchBody();
1939 Handler.Block = CGF.createBasicBlock("catch");
1940
1941 // @catch() and @catch(id) both catch any ObjC exception.
1942 // Treat them as catch-alls.
1943 // FIXME: this is what this code was doing before, but should 'id'
1944 // really be catching foreign exceptions?
1945 if (!CatchDecl
1946 || CatchDecl->getType()->isObjCIdType()
1947 || CatchDecl->getType()->isObjCQualifiedIdType()) {
1948
1949 Handler.TypeInfo = 0; // catch-all
1950
1951 // Don't consider any other catches.
1952 break;
1953 }
1954
1955 // All other types should be Objective-C interface pointer types.
1956 const ObjCObjectPointerType *OPT =
1957 CatchDecl->getType()->getAs<ObjCObjectPointerType>();
1958 assert(OPT && "Invalid @catch type.");
1959 const ObjCInterfaceDecl *IDecl =
1960 OPT->getObjectType()->getInterface();
1961 assert(IDecl && "Invalid @catch type.");
1962 Handler.TypeInfo = MakeConstantString(IDecl->getNameAsString());
1963 }
1964
1965 EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
1966 for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
1967 Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block);
1968 }
1969
1970 // Emit the try body.
1971 CGF.EmitStmt(S.getTryBody());
1972
1973 // Leave the try.
1974 if (S.getNumCatchStmts())
1975 CGF.EHStack.popCatch();
1976
1977 // Remember where we were.
1978 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
1979
1980 // Emit the handlers.
1981 for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
1982 CatchHandler &Handler = Handlers[I];
1983 CGF.EmitBlock(Handler.Block);
1984
1985 llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot());
1986
1987 // Bind the catch parameter if it exists.
1988 if (const VarDecl *CatchParam = Handler.Variable) {
1989 const llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType());
1990 Exn = CGF.Builder.CreateBitCast(Exn, CatchType);
1991
1992 CGF.EmitLocalBlockVarDecl(*CatchParam);
1993 CGF.Builder.CreateStore(Exn, CGF.GetAddrOfLocalVar(CatchParam));
1994 }
1995
1996 CGF.ObjCEHValueStack.push_back(Exn);
1997 CGF.EmitStmt(Handler.Body);
1998 CGF.ObjCEHValueStack.pop_back();
1999
2000 CGF.EmitBranchThroughCleanup(Cont);
2001 }
2002
2003 // Go back to the try-statement fallthrough.
2004 CGF.Builder.restoreIP(SavedIP);
2005
2006 // Pop out of the finally.
2007 if (S.getFinallyStmt())
2008 CGF.ExitFinallyBlock(FinallyInfo);
2009
2010 if (Cont.Block) {
2011 if (Cont.Block->use_empty())
2012 delete Cont.Block;
2013 else {
2014 CGF.EmitBranch(Cont.Block);
2015 CGF.EmitBlock(Cont.Block);
2016 }
2017 }
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00002018}
2019
2020void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar49f66022008-09-24 03:38:44 +00002021 const ObjCAtThrowStmt &S) {
Chris Lattner5dc08672009-05-08 00:11:50 +00002022 llvm::Value *ExceptionAsObject;
2023
2024 std::vector<const llvm::Type*> Args(1, IdTy);
2025 llvm::FunctionType *FTy =
Owen Anderson0032b272009-08-13 21:57:51 +00002026 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Mike Stump1eb44332009-09-09 15:08:12 +00002027 llvm::Value *ThrowFn =
Chris Lattner5dc08672009-05-08 00:11:50 +00002028 CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
Mike Stump1eb44332009-09-09 15:08:12 +00002029
Chris Lattner5dc08672009-05-08 00:11:50 +00002030 if (const Expr *ThrowExpr = S.getThrowExpr()) {
2031 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
Fariborz Jahanian1e64a952009-05-17 16:49:27 +00002032 ExceptionAsObject = Exception;
Chris Lattner5dc08672009-05-08 00:11:50 +00002033 } else {
Mike Stump1eb44332009-09-09 15:08:12 +00002034 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Chris Lattner5dc08672009-05-08 00:11:50 +00002035 "Unexpected rethrow outside @catch block.");
2036 ExceptionAsObject = CGF.ObjCEHValueStack.back();
2037 }
Fariborz Jahanian1e64a952009-05-17 16:49:27 +00002038 ExceptionAsObject =
2039 CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy, "tmp");
Mike Stump1eb44332009-09-09 15:08:12 +00002040
Chris Lattner5dc08672009-05-08 00:11:50 +00002041 // Note: This may have to be an invoke, if we want to support constructs like:
2042 // @try {
2043 // @throw(obj);
2044 // }
2045 // @catch(id) ...
2046 //
2047 // This is effectively turning @throw into an incredibly-expensive goto, but
2048 // it may happen as a result of inlining followed by missed optimizations, or
2049 // as a result of stupidity.
2050 llvm::BasicBlock *UnwindBB = CGF.getInvokeDest();
2051 if (!UnwindBB) {
2052 CGF.Builder.CreateCall(ThrowFn, ExceptionAsObject);
2053 CGF.Builder.CreateUnreachable();
2054 } else {
2055 CGF.Builder.CreateInvoke(ThrowFn, UnwindBB, UnwindBB, &ExceptionAsObject,
2056 &ExceptionAsObject+1);
2057 }
2058 // Clear the insertion point to indicate we are in unreachable code.
2059 CGF.Builder.ClearInsertionPoint();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00002060}
2061
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00002062llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00002063 llvm::Value *AddrWeakObj) {
David Chisnallef6e0f32010-02-03 15:59:02 +00002064 CGBuilderTy B = CGF.Builder;
2065 AddrWeakObj = EnforceType(B, AddrWeakObj, IdTy);
2066 return B.CreateCall(WeakReadFn, AddrWeakObj);
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00002067}
2068
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00002069void CGObjCGNU::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00002070 llvm::Value *src, llvm::Value *dst) {
David Chisnallef6e0f32010-02-03 15:59:02 +00002071 CGBuilderTy B = CGF.Builder;
2072 src = EnforceType(B, src, IdTy);
2073 dst = EnforceType(B, dst, PtrToIdTy);
2074 B.CreateCall2(WeakAssignFn, src, dst);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00002075}
2076
Fariborz Jahanian58626502008-11-19 00:59:10 +00002077void CGObjCGNU::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00002078 llvm::Value *src, llvm::Value *dst) {
David Chisnallef6e0f32010-02-03 15:59:02 +00002079 CGBuilderTy B = CGF.Builder;
2080 src = EnforceType(B, src, IdTy);
2081 dst = EnforceType(B, dst, PtrToIdTy);
2082 B.CreateCall2(GlobalAssignFn, src, dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +00002083}
2084
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00002085void CGObjCGNU::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00002086 llvm::Value *src, llvm::Value *dst,
2087 llvm::Value *ivarOffset) {
David Chisnallef6e0f32010-02-03 15:59:02 +00002088 CGBuilderTy B = CGF.Builder;
2089 src = EnforceType(B, src, IdTy);
2090 dst = EnforceType(B, dst, PtrToIdTy);
2091 B.CreateCall3(IvarAssignFn, src, dst, ivarOffset);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00002092}
2093
Fariborz Jahanian58626502008-11-19 00:59:10 +00002094void CGObjCGNU::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00002095 llvm::Value *src, llvm::Value *dst) {
David Chisnallef6e0f32010-02-03 15:59:02 +00002096 CGBuilderTy B = CGF.Builder;
2097 src = EnforceType(B, src, IdTy);
2098 dst = EnforceType(B, dst, PtrToIdTy);
2099 B.CreateCall2(StrongCastAssignFn, src, dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +00002100}
2101
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00002102void CGObjCGNU::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00002103 llvm::Value *DestPtr,
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00002104 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00002105 llvm::Value *Size) {
David Chisnallef6e0f32010-02-03 15:59:02 +00002106 CGBuilderTy B = CGF.Builder;
2107 DestPtr = EnforceType(B, DestPtr, IdTy);
2108 SrcPtr = EnforceType(B, SrcPtr, PtrToIdTy);
2109
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00002110 B.CreateCall3(MemMoveFn, DestPtr, SrcPtr, Size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00002111}
2112
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002113llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
2114 const ObjCInterfaceDecl *ID,
2115 const ObjCIvarDecl *Ivar) {
2116 const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
2117 + '.' + Ivar->getNameAsString();
2118 // Emit the variable and initialize it with what we think the correct value
2119 // is. This allows code compiled with non-fragile ivars to work correctly
2120 // when linked against code which isn't (most of the time).
David Chisnall8a5a9aa2009-08-31 16:41:57 +00002121 llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
2122 if (!IvarOffsetPointer) {
David Chisnalld901da52010-04-19 01:37:25 +00002123 uint64_t Offset;
2124 if (ObjCImplementationDecl *OID =
Dan Gohmancb421fa2010-04-19 16:39:44 +00002125 CGM.getContext().getObjCImplementation(
2126 const_cast<ObjCInterfaceDecl *>(ID)))
David Chisnalld901da52010-04-19 01:37:25 +00002127 Offset = ComputeIvarBaseOffset(CGM, OID, Ivar);
2128 else
2129 Offset = ComputeIvarBaseOffset(CGM, ID, Ivar);
2130
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002131 llvm::ConstantInt *OffsetGuess =
David Chisnallf9508372010-01-11 19:02:35 +00002132 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Offset, "ivar");
David Chisnall8a5a9aa2009-08-31 16:41:57 +00002133 // Don't emit the guess in non-PIC code because the linker will not be able
2134 // to replace it with the real version for a library. In non-PIC code you
2135 // must compile with the fragile ABI if you want to use ivars from a
Mike Stump1eb44332009-09-09 15:08:12 +00002136 // GCC-compiled class.
David Chisnall8a5a9aa2009-08-31 16:41:57 +00002137 if (CGM.getLangOptions().PICLevel) {
2138 llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule,
2139 llvm::Type::getInt32Ty(VMContext), false,
2140 llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess");
2141 IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
2142 IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage,
2143 IvarOffsetGV, Name);
2144 } else {
2145 IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00002146 llvm::Type::getInt32PtrTy(VMContext), false,
2147 llvm::GlobalValue::ExternalLinkage, 0, Name);
David Chisnall8a5a9aa2009-08-31 16:41:57 +00002148 }
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002149 }
David Chisnall8a5a9aa2009-08-31 16:41:57 +00002150 return IvarOffsetPointer;
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002151}
2152
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00002153LValue CGObjCGNU::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
2154 QualType ObjectTy,
2155 llvm::Value *BaseValue,
2156 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00002157 unsigned CVRQualifiers) {
John McCallc12c5bb2010-05-15 11:32:37 +00002158 const ObjCInterfaceDecl *ID =
2159 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00002160 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
2161 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00002162}
Mike Stumpbb1c8602009-07-31 21:31:32 +00002163
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002164static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
2165 const ObjCInterfaceDecl *OID,
2166 const ObjCIvarDecl *OIVD) {
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002167 llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00002168 Context.ShallowCollectObjCIvars(OID, Ivars);
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002169 for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
2170 if (OIVD == Ivars[k])
2171 return OID;
2172 }
Mike Stump1eb44332009-09-09 15:08:12 +00002173
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002174 // Otherwise check in the super class.
2175 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
2176 return FindIvarInterface(Context, Super, OIVD);
Mike Stump1eb44332009-09-09 15:08:12 +00002177
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002178 return 0;
2179}
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00002180
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00002181llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00002182 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00002183 const ObjCIvarDecl *Ivar) {
David Chisnall8a5a9aa2009-08-31 16:41:57 +00002184 if (CGM.getLangOptions().ObjCNonFragileABI) {
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002185 Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar);
David Chisnall8a5a9aa2009-08-31 16:41:57 +00002186 return CGF.Builder.CreateLoad(CGF.Builder.CreateLoad(
2187 ObjCIvarOffsetVariable(Interface, Ivar), false, "ivar"));
Fariborz Jahanian9cd96ff2009-05-20 18:41:51 +00002188 }
Daniel Dunbar97776872009-04-22 07:32:20 +00002189 uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002190 return llvm::ConstantInt::get(LongTy, Offset, "ivar");
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00002191}
2192
Mike Stumpbb1c8602009-07-31 21:31:32 +00002193CodeGen::CGObjCRuntime *
2194CodeGen::CreateGNUObjCRuntime(CodeGen::CodeGenModule &CGM) {
Chris Lattnerdce14062008-06-26 04:19:03 +00002195 return new CGObjCGNU(CGM);
Chris Lattner0f984262008-03-01 08:50:34 +00002196}