blob: d9d79e1587526e0b1185bdeee920c3c319fbb282 [file] [log] [blame]
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
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//
10// This provides Objective-C code generation targetting the Apple runtime.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000015
Daniel Dunbar034299e2010-03-31 01:09:11 +000016#include "CGRecordLayout.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000017#include "CodeGenModule.h"
Daniel Dunbara94ecd22008-08-16 03:19:19 +000018#include "CodeGenFunction.h"
John McCallbd309292010-07-06 01:34:17 +000019#include "CGException.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000020#include "clang/AST/ASTContext.h"
Daniel Dunbar221fa942008-08-11 04:54:23 +000021#include "clang/AST/Decl.h"
Daniel Dunbarb036db82008-08-13 03:21:16 +000022#include "clang/AST/DeclObjC.h"
Anders Carlsson15b73de2009-07-18 19:43:29 +000023#include "clang/AST/RecordLayout.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000024#include "clang/AST/StmtObjC.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000025#include "clang/Basic/LangOptions.h"
Chandler Carruth85098242010-06-15 23:19:56 +000026#include "clang/Frontend/CodeGenOptions.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000027
John McCall42227ed2010-07-31 23:20:56 +000028#include "llvm/InlineAsm.h"
29#include "llvm/IntrinsicInst.h"
Owen Andersonae86c192009-07-13 04:10:07 +000030#include "llvm/LLVMContext.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000031#include "llvm/Module.h"
Daniel Dunbarc475d422008-10-29 22:36:39 +000032#include "llvm/ADT/DenseSet.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000033#include "llvm/ADT/SetVector.h"
34#include "llvm/ADT/SmallString.h"
Fariborz Jahanian751c1e72009-12-12 21:26:21 +000035#include "llvm/ADT/SmallPtrSet.h"
John McCall5c08ab92010-07-13 22:12:14 +000036#include "llvm/Support/CallSite.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000037#include "llvm/Support/raw_ostream.h"
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +000038#include "llvm/Target/TargetData.h"
Torok Edwindb714922009-08-24 13:25:12 +000039#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000040
41using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000042using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000043
Daniel Dunbar9fd114d2009-04-22 07:32:20 +000044// Common CGObjCRuntime functions, these don't belong here, but they
45// don't belong in CGObjCRuntime either so we will live with it for
46// now.
47
Daniel Dunbar0cec95f2009-05-03 08:55:17 +000048static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
49 const ObjCInterfaceDecl *OID,
Daniel Dunbar961202372009-05-03 12:57:56 +000050 const ObjCImplementationDecl *ID,
Daniel Dunbar0cec95f2009-05-03 08:55:17 +000051 const ObjCIvarDecl *Ivar) {
Daniel Dunbar8c7f9812010-04-02 21:14:02 +000052 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar80b4eef2009-05-03 13:15:50 +000053
Daniel Dunbar7e5aba42010-04-02 22:29:40 +000054 // FIXME: We should eliminate the need to have ObjCImplementationDecl passed
55 // in here; it should never be necessary because that should be the lexical
56 // decl context for the ivar.
Daniel Dunbar031d4d42010-04-02 15:43:29 +000057
Daniel Dunbar80b4eef2009-05-03 13:15:50 +000058 // If we know have an implementation (and the ivar is in it) then
59 // look up in the implementation layout.
Daniel Dunbar59e476b2009-08-03 17:06:42 +000060 const ASTRecordLayout *RL;
Daniel Dunbar80b4eef2009-05-03 13:15:50 +000061 if (ID && ID->getClassInterface() == Container)
62 RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
63 else
64 RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
Daniel Dunbar8c7f9812010-04-02 21:14:02 +000065
66 // Compute field index.
67 //
68 // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is
69 // implemented. This should be fixed to get the information from the layout
70 // directly.
71 unsigned Index = 0;
72 llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
73 CGM.getContext().ShallowCollectObjCIvars(Container, Ivars);
74 for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
75 if (Ivar == Ivars[k])
76 break;
77 ++Index;
78 }
79 assert(Index != Ivars.size() && "Ivar is not inside container!");
80
Daniel Dunbar80b4eef2009-05-03 13:15:50 +000081 return RL->getFieldOffset(Index);
Daniel Dunbar0cec95f2009-05-03 08:55:17 +000082}
83
84uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
85 const ObjCInterfaceDecl *OID,
86 const ObjCIvarDecl *Ivar) {
Daniel Dunbar961202372009-05-03 12:57:56 +000087 return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8;
88}
89
90uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
91 const ObjCImplementationDecl *OID,
92 const ObjCIvarDecl *Ivar) {
93 return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8;
Daniel Dunbar9fd114d2009-04-22 07:32:20 +000094}
95
96LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
97 const ObjCInterfaceDecl *OID,
98 llvm::Value *BaseValue,
99 const ObjCIvarDecl *Ivar,
100 unsigned CVRQualifiers,
101 llvm::Value *Offset) {
Daniel Dunbar0cec95f2009-05-03 08:55:17 +0000102 // Compute (type*) ( (char *) BaseValue + Offset)
Benjamin Kramerabd5b902009-10-13 10:07:13 +0000103 const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
Daniel Dunbar0cec95f2009-05-03 08:55:17 +0000104 QualType IvarTy = Ivar->getType();
105 const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
Daniel Dunbar9fd114d2009-04-22 07:32:20 +0000106 llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr);
Daniel Dunbar9fd114d2009-04-22 07:32:20 +0000107 V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
Owen Anderson9793f0e2009-07-29 22:16:19 +0000108 V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000109
John McCall8ccfcb52009-09-24 19:53:00 +0000110 Qualifiers Quals = CGF.MakeQualifiers(IvarTy);
111 Quals.addCVRQualifiers(CVRQualifiers);
112
Daniel Dunbarb76c4cd2010-04-05 16:20:33 +0000113 if (!Ivar->isBitField())
114 return LValue::MakeAddr(V, Quals);
Daniel Dunbar961202372009-05-03 12:57:56 +0000115
Daniel Dunbarb76c4cd2010-04-05 16:20:33 +0000116 // We need to compute the bit offset for the bit-field, the offset is to the
117 // byte. Note, there is a subtle invariant here: we can only call this routine
118 // on non-synthesized ivars but we may be called for synthesized ivars.
119 // However, a synthesized ivar can never be a bit-field, so this is safe.
120 uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar) % 8;
121 uint64_t BitFieldSize =
122 Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +0000123
Daniel Dunbardc406b82010-04-05 21:36:35 +0000124 // Allocate a new CGBitFieldInfo object to describe this access.
125 //
126 // FIXME: This is incredibly wasteful, these should be uniqued or part of some
127 // layout object. However, this is blocked on other cleanups to the
128 // Objective-C code, so for now we just live with allocating a bunch of these
129 // objects.
Daniel Dunbardc406b82010-04-05 21:36:35 +0000130
Daniel Dunbarb935b932010-04-13 20:58:55 +0000131 // We always construct a single, possibly unaligned, access for this case.
Daniel Dunbar9c78d632010-04-15 05:09:32 +0000132 CGBitFieldInfo::AccessInfo AI;
Daniel Dunbarb935b932010-04-13 20:58:55 +0000133 AI.FieldIndex = 0;
134 AI.FieldByteOffset = 0;
135 AI.FieldBitStart = BitOffset;
136 AI.AccessWidth = CGF.CGM.getContext().getTypeSize(IvarTy);
137 AI.AccessAlignment = 0;
138 AI.TargetBitOffset = 0;
139 AI.TargetBitWidth = BitFieldSize;
140
Daniel Dunbar9c78d632010-04-15 05:09:32 +0000141 CGBitFieldInfo *Info =
142 new (CGF.CGM.getContext()) CGBitFieldInfo(BitFieldSize, 1, &AI,
143 IvarTy->isSignedIntegerType());
144
Daniel Dunbarb76c4cd2010-04-05 16:20:33 +0000145 // FIXME: We need to set a very conservative alignment on this, or make sure
146 // that the runtime is doing the right thing.
Daniel Dunbar196ea442010-04-06 01:07:44 +0000147 return LValue::MakeBitfield(V, *Info, Quals.getCVRQualifiers());
Daniel Dunbar9fd114d2009-04-22 07:32:20 +0000148}
149
150///
151
Daniel Dunbar303e2c22008-08-11 02:45:11 +0000152namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000153
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000154typedef std::vector<llvm::Constant*> ConstantVector;
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000155
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000156// FIXME: We should find a nicer way to make the labels for metadata, string
157// concatenation is lame.
Daniel Dunbarb036db82008-08-13 03:21:16 +0000158
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000159class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +0000160protected:
161 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000162
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000163private:
164 llvm::Constant *getMessageSendFn() const {
165 // id objc_msgSend (id, SEL, ...)
166 std::vector<const llvm::Type*> Params;
167 Params.push_back(ObjectPtrTy);
168 Params.push_back(SelectorPtrTy);
169 return
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000170 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
171 Params, true),
172 "objc_msgSend");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000173 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000174
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000175 llvm::Constant *getMessageSendStretFn() const {
176 // id objc_msgSend_stret (id, SEL, ...)
177 std::vector<const llvm::Type*> Params;
178 Params.push_back(ObjectPtrTy);
179 Params.push_back(SelectorPtrTy);
180 return
Owen Anderson41a75022009-08-13 21:57:51 +0000181 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000182 Params, true),
183 "objc_msgSend_stret");
184
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000185 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000186
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000187 llvm::Constant *getMessageSendFpretFn() const {
188 // FIXME: This should be long double on x86_64?
189 // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
190 std::vector<const llvm::Type*> Params;
191 Params.push_back(ObjectPtrTy);
192 Params.push_back(SelectorPtrTy);
193 return
Owen Anderson41a75022009-08-13 21:57:51 +0000194 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
195 llvm::Type::getDoubleTy(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000196 Params,
197 true),
198 "objc_msgSend_fpret");
199
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000200 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000201
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000202 llvm::Constant *getMessageSendSuperFn() const {
203 // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
204 const char *SuperName = "objc_msgSendSuper";
205 std::vector<const llvm::Type*> Params;
206 Params.push_back(SuperPtrTy);
207 Params.push_back(SelectorPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000208 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000209 Params, true),
210 SuperName);
211 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000212
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000213 llvm::Constant *getMessageSendSuperFn2() const {
214 // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
215 const char *SuperName = "objc_msgSendSuper2";
216 std::vector<const llvm::Type*> Params;
217 Params.push_back(SuperPtrTy);
218 Params.push_back(SelectorPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000219 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000220 Params, true),
221 SuperName);
222 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000223
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000224 llvm::Constant *getMessageSendSuperStretFn() const {
225 // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
226 // SEL op, ...)
227 std::vector<const llvm::Type*> Params;
228 Params.push_back(Int8PtrTy);
229 Params.push_back(SuperPtrTy);
230 Params.push_back(SelectorPtrTy);
Owen Anderson170229f2009-07-14 23:10:40 +0000231 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000232 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000233 Params, true),
234 "objc_msgSendSuper_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000235 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000236
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000237 llvm::Constant *getMessageSendSuperStretFn2() const {
238 // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
239 // SEL op, ...)
240 std::vector<const llvm::Type*> Params;
241 Params.push_back(Int8PtrTy);
242 Params.push_back(SuperPtrTy);
243 Params.push_back(SelectorPtrTy);
Owen Anderson170229f2009-07-14 23:10:40 +0000244 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000245 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000246 Params, true),
247 "objc_msgSendSuper2_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000248 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000249
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000250 llvm::Constant *getMessageSendSuperFpretFn() const {
251 // There is no objc_msgSendSuper_fpret? How can that work?
252 return getMessageSendSuperFn();
253 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000254
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000255 llvm::Constant *getMessageSendSuperFpretFn2() const {
256 // There is no objc_msgSendSuper_fpret? How can that work?
257 return getMessageSendSuperFn2();
258 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000259
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000260protected:
261 CodeGen::CodeGenModule &CGM;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000262
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000263public:
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +0000264 const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000265 const llvm::Type *Int8PtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000266
Daniel Dunbar5d715592008-08-12 05:28:47 +0000267 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
268 const llvm::Type *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000269
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000270 /// PtrObjectPtrTy - LLVM type for id *
271 const llvm::Type *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000272
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000273 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Daniel Dunbar5d715592008-08-12 05:28:47 +0000274 const llvm::Type *SelectorPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000275 /// ProtocolPtrTy - LLVM type for external protocol handles
276 /// (typeof(Protocol))
277 const llvm::Type *ExternalProtocolPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000278
Daniel Dunbarc722b852008-08-30 03:02:31 +0000279 // SuperCTy - clang type for struct objc_super.
280 QualType SuperCTy;
281 // SuperPtrCTy - clang type for struct objc_super *.
282 QualType SuperPtrCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000283
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000284 /// SuperTy - LLVM type for struct objc_super.
285 const llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000286 /// SuperPtrTy - LLVM type for struct objc_super *.
287 const llvm::Type *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000288
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000289 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
290 /// in GCC parlance).
291 const llvm::StructType *PropertyTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000292
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000293 /// PropertyListTy - LLVM type for struct objc_property_list
294 /// (_prop_list_t in GCC parlance).
295 const llvm::StructType *PropertyListTy;
296 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
297 const llvm::Type *PropertyListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000298
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000299 // MethodTy - LLVM type for struct objc_method.
300 const llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000301
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000302 /// CacheTy - LLVM type for struct objc_cache.
303 const llvm::Type *CacheTy;
304 /// CachePtrTy - LLVM type for struct objc_cache *.
305 const llvm::Type *CachePtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000306
Chris Lattnerce8754e2009-04-22 02:44:54 +0000307 llvm::Constant *getGetPropertyFn() {
308 CodeGen::CodeGenTypes &Types = CGM.getTypes();
309 ASTContext &Ctx = CGM.getContext();
310 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
John McCall2da83a32010-02-26 00:48:12 +0000311 llvm::SmallVector<CanQualType,4> Params;
312 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
313 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000314 Params.push_back(IdType);
315 Params.push_back(SelType);
316 Params.push_back(Ctx.LongTy);
317 Params.push_back(Ctx.BoolTy);
318 const llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000319 Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000320 FunctionType::ExtInfo()),
321 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000322 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
323 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000324
Chris Lattnerce8754e2009-04-22 02:44:54 +0000325 llvm::Constant *getSetPropertyFn() {
326 CodeGen::CodeGenTypes &Types = CGM.getTypes();
327 ASTContext &Ctx = CGM.getContext();
328 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
John McCall2da83a32010-02-26 00:48:12 +0000329 llvm::SmallVector<CanQualType,6> Params;
330 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
331 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000332 Params.push_back(IdType);
333 Params.push_back(SelType);
334 Params.push_back(Ctx.LongTy);
335 Params.push_back(IdType);
336 Params.push_back(Ctx.BoolTy);
337 Params.push_back(Ctx.BoolTy);
338 const llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000339 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000340 FunctionType::ExtInfo()),
341 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000342 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
343 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000344
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000345
346 llvm::Constant *getCopyStructFn() {
347 CodeGen::CodeGenTypes &Types = CGM.getTypes();
348 ASTContext &Ctx = CGM.getContext();
349 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
350 llvm::SmallVector<CanQualType,5> Params;
351 Params.push_back(Ctx.VoidPtrTy);
352 Params.push_back(Ctx.VoidPtrTy);
353 Params.push_back(Ctx.LongTy);
354 Params.push_back(Ctx.BoolTy);
355 Params.push_back(Ctx.BoolTy);
356 const llvm::FunctionType *FTy =
357 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
358 FunctionType::ExtInfo()),
359 false);
360 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
361 }
362
Chris Lattnerce8754e2009-04-22 02:44:54 +0000363 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000364 CodeGen::CodeGenTypes &Types = CGM.getTypes();
365 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000366 // void objc_enumerationMutation (id)
John McCall2da83a32010-02-26 00:48:12 +0000367 llvm::SmallVector<CanQualType,1> Params;
368 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000369 const llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000370 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000371 FunctionType::ExtInfo()),
372 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000373 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
374 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000375
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000376 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattnerce8754e2009-04-22 02:44:54 +0000377 llvm::Constant *getGcReadWeakFn() {
378 // id objc_read_weak (id *)
379 std::vector<const llvm::Type*> Args;
380 Args.push_back(ObjectPtrTy->getPointerTo());
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000381 llvm::FunctionType *FTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +0000382 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000383 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000384 }
385
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000386 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000387 llvm::Constant *getGcAssignWeakFn() {
388 // id objc_assign_weak (id, id *)
389 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
390 Args.push_back(ObjectPtrTy->getPointerTo());
391 llvm::FunctionType *FTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +0000392 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000393 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
394 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000395
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000396 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000397 llvm::Constant *getGcAssignGlobalFn() {
398 // id objc_assign_global(id, id *)
399 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
400 Args.push_back(ObjectPtrTy->getPointerTo());
Owen Anderson170229f2009-07-14 23:10:40 +0000401 llvm::FunctionType *FTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +0000402 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000403 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
404 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000405
Fariborz Jahanian217af242010-07-20 20:30:03 +0000406 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
407 llvm::Constant *getGcAssignThreadLocalFn() {
408 // id objc_assign_threadlocal(id src, id * dest)
409 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
410 Args.push_back(ObjectPtrTy->getPointerTo());
411 llvm::FunctionType *FTy =
412 llvm::FunctionType::get(ObjectPtrTy, Args, false);
413 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
414 }
415
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000416 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000417 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000418 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattner0a696a422009-04-22 02:38:11 +0000419 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
420 Args.push_back(ObjectPtrTy->getPointerTo());
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000421 Args.push_back(LongTy);
Owen Anderson170229f2009-07-14 23:10:40 +0000422 llvm::FunctionType *FTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +0000423 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000424 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
425 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000426
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000427 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
428 llvm::Constant *GcMemmoveCollectableFn() {
429 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
430 std::vector<const llvm::Type*> Args(1, Int8PtrTy);
431 Args.push_back(Int8PtrTy);
432 Args.push_back(LongTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000433 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000434 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
435 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000436
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000437 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000438 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000439 // id objc_assign_strongCast(id, id *)
Chris Lattner0a696a422009-04-22 02:38:11 +0000440 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
441 Args.push_back(ObjectPtrTy->getPointerTo());
Owen Anderson170229f2009-07-14 23:10:40 +0000442 llvm::FunctionType *FTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +0000443 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000444 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
445 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000446
447 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000448 llvm::Constant *getExceptionThrowFn() {
449 // void objc_exception_throw(id)
450 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
451 llvm::FunctionType *FTy =
Owen Anderson41a75022009-08-13 21:57:51 +0000452 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000453 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
454 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000455
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000456 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
457 llvm::Constant *getExceptionRethrowFn() {
458 // void objc_exception_rethrow(void)
459 std::vector<const llvm::Type*> Args;
460 llvm::FunctionType *FTy =
461 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, true);
462 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
463 }
464
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000465 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerdcceee72009-04-06 16:53:45 +0000466 llvm::Constant *getSyncEnterFn() {
467 // void objc_sync_enter (id)
468 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
469 llvm::FunctionType *FTy =
Owen Anderson41a75022009-08-13 21:57:51 +0000470 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000471 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
472 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000473
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000474 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000475 llvm::Constant *getSyncExitFn() {
476 // void objc_sync_exit (id)
477 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
478 llvm::FunctionType *FTy =
Owen Anderson41a75022009-08-13 21:57:51 +0000479 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000480 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
481 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000482
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000483 llvm::Constant *getSendFn(bool IsSuper) const {
484 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
485 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000486
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000487 llvm::Constant *getSendFn2(bool IsSuper) const {
488 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
489 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000490
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000491 llvm::Constant *getSendStretFn(bool IsSuper) const {
492 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
493 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000494
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000495 llvm::Constant *getSendStretFn2(bool IsSuper) const {
496 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
497 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000498
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000499 llvm::Constant *getSendFpretFn(bool IsSuper) const {
500 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
501 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000502
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000503 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
504 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
505 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000506
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000507 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
508 ~ObjCCommonTypesHelper(){}
509};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000510
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000511/// ObjCTypesHelper - Helper class that encapsulates lazy
512/// construction of varies types used during ObjC generation.
513class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000514public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000515 /// SymtabTy - LLVM type for struct objc_symtab.
516 const llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000517 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
518 const llvm::Type *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000519 /// ModuleTy - LLVM type for struct objc_module.
520 const llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000521
Daniel Dunbarb036db82008-08-13 03:21:16 +0000522 /// ProtocolTy - LLVM type for struct objc_protocol.
523 const llvm::StructType *ProtocolTy;
524 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
525 const llvm::Type *ProtocolPtrTy;
526 /// ProtocolExtensionTy - LLVM type for struct
527 /// objc_protocol_extension.
528 const llvm::StructType *ProtocolExtensionTy;
529 /// ProtocolExtensionTy - LLVM type for struct
530 /// objc_protocol_extension *.
531 const llvm::Type *ProtocolExtensionPtrTy;
532 /// MethodDescriptionTy - LLVM type for struct
533 /// objc_method_description.
534 const llvm::StructType *MethodDescriptionTy;
535 /// MethodDescriptionListTy - LLVM type for struct
536 /// objc_method_description_list.
537 const llvm::StructType *MethodDescriptionListTy;
538 /// MethodDescriptionListPtrTy - LLVM type for struct
539 /// objc_method_description_list *.
540 const llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000541 /// ProtocolListTy - LLVM type for struct objc_property_list.
542 const llvm::Type *ProtocolListTy;
543 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
544 const llvm::Type *ProtocolListPtrTy;
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000545 /// CategoryTy - LLVM type for struct objc_category.
546 const llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000547 /// ClassTy - LLVM type for struct objc_class.
548 const llvm::StructType *ClassTy;
549 /// ClassPtrTy - LLVM type for struct objc_class *.
550 const llvm::Type *ClassPtrTy;
551 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
552 const llvm::StructType *ClassExtensionTy;
553 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
554 const llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000555 // IvarTy - LLVM type for struct objc_ivar.
556 const llvm::StructType *IvarTy;
557 /// IvarListTy - LLVM type for struct objc_ivar_list.
558 const llvm::Type *IvarListTy;
559 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
560 const llvm::Type *IvarListPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000561 /// MethodListTy - LLVM type for struct objc_method_list.
562 const llvm::Type *MethodListTy;
563 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
564 const llvm::Type *MethodListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000565
Anders Carlsson9ff22482008-09-09 10:10:21 +0000566 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
567 const llvm::Type *ExceptionDataTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000568
Anders Carlsson9ff22482008-09-09 10:10:21 +0000569 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000570 llvm::Constant *getExceptionTryEnterFn() {
571 std::vector<const llvm::Type*> Params;
Owen Anderson9793f0e2009-07-29 22:16:19 +0000572 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
Owen Anderson170229f2009-07-14 23:10:40 +0000573 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000574 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000575 Params, false),
576 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000577 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000578
579 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000580 llvm::Constant *getExceptionTryExitFn() {
581 std::vector<const llvm::Type*> Params;
Owen Anderson9793f0e2009-07-29 22:16:19 +0000582 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
Owen Anderson170229f2009-07-14 23:10:40 +0000583 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000584 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000585 Params, false),
586 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000587 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000588
589 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000590 llvm::Constant *getExceptionExtractFn() {
591 std::vector<const llvm::Type*> Params;
Owen Anderson9793f0e2009-07-29 22:16:19 +0000592 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
593 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattnerc6406db2009-04-22 02:26:14 +0000594 Params, false),
595 "objc_exception_extract");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000596
Chris Lattnerc6406db2009-04-22 02:26:14 +0000597 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000598
Anders Carlsson9ff22482008-09-09 10:10:21 +0000599 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000600 llvm::Constant *getExceptionMatchFn() {
601 std::vector<const llvm::Type*> Params;
602 Params.push_back(ClassPtrTy);
603 Params.push_back(ObjectPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000604 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000605 llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000606 Params, false),
607 "objc_exception_match");
608
Chris Lattnerc6406db2009-04-22 02:26:14 +0000609 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000610
Anders Carlsson9ff22482008-09-09 10:10:21 +0000611 /// SetJmpFn - LLVM _setjmp function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000612 llvm::Constant *getSetJmpFn() {
613 std::vector<const llvm::Type*> Params;
Benjamin Kramerabd5b902009-10-13 10:07:13 +0000614 Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
Chris Lattnerc6406db2009-04-22 02:26:14 +0000615 return
Owen Anderson41a75022009-08-13 21:57:51 +0000616 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000617 Params, false),
618 "_setjmp");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000619
Chris Lattnerc6406db2009-04-22 02:26:14 +0000620 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000621
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000622public:
623 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000624 ~ObjCTypesHelper() {}
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000625};
626
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000627/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000628/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000629class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000630public:
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000631
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000632 // MethodListnfABITy - LLVM for struct _method_list_t
633 const llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000634
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000635 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
636 const llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000637
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000638 // ProtocolnfABITy = LLVM for struct _protocol_t
639 const llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000640
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000641 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
642 const llvm::Type *ProtocolnfABIPtrTy;
643
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000644 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
645 const llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000646
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000647 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
648 const llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000649
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000650 // ClassnfABITy - LLVM for struct _class_t
651 const llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000652
Fariborz Jahanian71394042009-01-23 23:53:38 +0000653 // ClassnfABIPtrTy - LLVM for struct _class_t*
654 const llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000655
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000656 // IvarnfABITy - LLVM for struct _ivar_t
657 const llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000658
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000659 // IvarListnfABITy - LLVM for struct _ivar_list_t
660 const llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000661
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000662 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
663 const llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000664
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000665 // ClassRonfABITy - LLVM for struct _class_ro_t
666 const llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000667
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000668 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
669 const llvm::Type *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000670
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000671 // CategorynfABITy - LLVM for struct _category_t
672 const llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000673
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000674 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000675
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000676 // MessageRefTy - LLVM for:
677 // struct _message_ref_t {
678 // IMP messenger;
679 // SEL name;
680 // };
681 const llvm::StructType *MessageRefTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000682 // MessageRefCTy - clang type for struct _message_ref_t
683 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000684
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000685 // MessageRefPtrTy - LLVM for struct _message_ref_t*
686 const llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000687 // MessageRefCPtrTy - clang type for struct _message_ref_t*
688 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000689
Fariborz Jahanian4e87c832009-02-05 01:13:09 +0000690 // MessengerTy - Type of the messenger (shown as IMP above)
691 const llvm::FunctionType *MessengerTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000692
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000693 // SuperMessageRefTy - LLVM for:
694 // struct _super_message_ref_t {
695 // SUPER_IMP messenger;
696 // SEL name;
697 // };
698 const llvm::StructType *SuperMessageRefTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000699
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000700 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
701 const llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000702
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000703 llvm::Constant *getMessageSendFixupFn() {
704 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
705 std::vector<const llvm::Type*> Params;
706 Params.push_back(ObjectPtrTy);
707 Params.push_back(MessageRefPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000708 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000709 Params, true),
710 "objc_msgSend_fixup");
711 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000712
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000713 llvm::Constant *getMessageSendFpretFixupFn() {
714 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
715 std::vector<const llvm::Type*> Params;
716 Params.push_back(ObjectPtrTy);
717 Params.push_back(MessageRefPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000718 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000719 Params, true),
720 "objc_msgSend_fpret_fixup");
721 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000722
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000723 llvm::Constant *getMessageSendStretFixupFn() {
724 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
725 std::vector<const llvm::Type*> Params;
726 Params.push_back(ObjectPtrTy);
727 Params.push_back(MessageRefPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000728 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000729 Params, true),
730 "objc_msgSend_stret_fixup");
731 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000732
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000733 llvm::Constant *getMessageSendIdFixupFn() {
734 // id objc_msgSendId_fixup(id, struct message_ref_t*, ...)
735 std::vector<const llvm::Type*> Params;
736 Params.push_back(ObjectPtrTy);
737 Params.push_back(MessageRefPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000738 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000739 Params, true),
740 "objc_msgSendId_fixup");
741 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000742
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000743 llvm::Constant *getMessageSendIdStretFixupFn() {
744 // id objc_msgSendId_stret_fixup(id, struct message_ref_t*, ...)
745 std::vector<const llvm::Type*> Params;
746 Params.push_back(ObjectPtrTy);
747 Params.push_back(MessageRefPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000748 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000749 Params, true),
750 "objc_msgSendId_stret_fixup");
751 }
752 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000753 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000754 // struct _super_message_ref_t*, ...)
755 std::vector<const llvm::Type*> Params;
756 Params.push_back(SuperPtrTy);
757 Params.push_back(SuperMessageRefPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000758 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000759 Params, true),
760 "objc_msgSendSuper2_fixup");
761 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000762
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000763 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000764 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000765 // struct _super_message_ref_t*, ...)
766 std::vector<const llvm::Type*> Params;
767 Params.push_back(SuperPtrTy);
768 Params.push_back(SuperMessageRefPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000769 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000770 Params, true),
771 "objc_msgSendSuper2_stret_fixup");
772 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000773
774
775
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000776 /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C
777 /// exception personality function.
Chris Lattnerdcceee72009-04-06 16:53:45 +0000778 llvm::Value *getEHPersonalityPtr() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000779 llvm::Constant *Personality =
Owen Anderson41a75022009-08-13 21:57:51 +0000780 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Chris Lattnerdcceee72009-04-06 16:53:45 +0000781 true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000782 "__objc_personality_v0");
Owen Andersonade90fd2009-07-29 18:54:39 +0000783 return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000784 }
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000785
Chris Lattnera7c00b42009-04-22 02:15:23 +0000786 llvm::Constant *getUnwindResumeOrRethrowFn() {
787 std::vector<const llvm::Type*> Params;
788 Params.push_back(Int8PtrTy);
Owen Anderson170229f2009-07-14 23:10:40 +0000789 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000790 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000791 Params, false),
Daniel Dunbar3241d402010-02-10 18:49:11 +0000792 (CGM.getLangOptions().SjLjExceptions ? "_Unwind_SjLj_Resume" :
793 "_Unwind_Resume_or_Rethrow"));
Chris Lattnera7c00b42009-04-22 02:15:23 +0000794 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000795
Chris Lattnera7c00b42009-04-22 02:15:23 +0000796 llvm::Constant *getObjCEndCatchFn() {
Owen Anderson41a75022009-08-13 21:57:51 +0000797 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Chris Lattner3dd1b4b2009-07-01 04:13:52 +0000798 false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000799 "objc_end_catch");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000800
Chris Lattnera7c00b42009-04-22 02:15:23 +0000801 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000802
Chris Lattnera7c00b42009-04-22 02:15:23 +0000803 llvm::Constant *getObjCBeginCatchFn() {
804 std::vector<const llvm::Type*> Params;
805 Params.push_back(Int8PtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000806 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
Chris Lattnera7c00b42009-04-22 02:15:23 +0000807 Params, false),
808 "objc_begin_catch");
809 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000810
811 const llvm::StructType *EHTypeTy;
812 const llvm::Type *EHTypePtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000813
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000814 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
815 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000816};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000817
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000818class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000819public:
820 // FIXME - accessibility
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000821 class GC_IVAR {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +0000822 public:
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000823 unsigned ivar_bytepos;
824 unsigned ivar_size;
825 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000826 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar22b0ada2009-04-23 01:29:05 +0000827
828 // Allow sorting based on byte pos.
829 bool operator<(const GC_IVAR &b) const {
830 return ivar_bytepos < b.ivar_bytepos;
831 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000832 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000833
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000834 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000835 public:
836 unsigned skip;
837 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000838 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000839 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000840 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000841
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000842protected:
843 CodeGen::CodeGenModule &CGM;
Owen Andersonae86c192009-07-13 04:10:07 +0000844 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000845 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000846 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000847
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000848 // gc ivar layout bitmap calculation helper caches.
849 llvm::SmallVector<GC_IVAR, 16> SkipIvars;
850 llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000851
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000852 /// LazySymbols - Symbols to generate a lazy reference for. See
853 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000854 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000855
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000856 /// DefinedSymbols - External symbols which are defined by this
857 /// module. The symbols in this list and LazySymbols are used to add
858 /// special linker symbols which ensure that Objective-C modules are
859 /// linked properly.
Daniel Dunbard027a922009-09-07 00:20:42 +0000860 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000861
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000862 /// ClassNames - uniqued class names.
Daniel Dunbarb036db82008-08-13 03:21:16 +0000863 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000864
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000865 /// MethodVarNames - uniqued method variable names.
866 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000867
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000868 /// DefinedCategoryNames - list of category names in form Class_Category.
869 llvm::SetVector<std::string> DefinedCategoryNames;
870
Daniel Dunbarb036db82008-08-13 03:21:16 +0000871 /// MethodVarTypes - uniqued method type signatures. We have to use
872 /// a StringMap here because have no other unique reference.
873 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000874
Daniel Dunbar3c76cb52008-08-26 21:51:14 +0000875 /// MethodDefinitions - map of methods which have been defined in
876 /// this translation unit.
877 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000878
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000879 /// PropertyNames - uniqued method variable names.
880 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000881
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000882 /// ClassReferences - uniqued class references.
883 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000884
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000885 /// SelectorReferences - uniqued selector references.
886 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000887
Daniel Dunbarb036db82008-08-13 03:21:16 +0000888 /// Protocols - Protocols for which an objc_protocol structure has
889 /// been emitted. Forward declarations are handled by creating an
890 /// empty structure whose initializer is filled in when/if defined.
891 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000892
Daniel Dunbarc475d422008-10-29 22:36:39 +0000893 /// DefinedProtocols - Protocols which have actually been
894 /// defined. We should not need this, see FIXME in GenerateProtocol.
895 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000896
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000897 /// DefinedClasses - List of defined classes.
898 std::vector<llvm::GlobalValue*> DefinedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000899
900 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
901 std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000902
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000903 /// DefinedCategories - List of defined categories.
904 std::vector<llvm::GlobalValue*> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000905
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000906 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
907 std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000908
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000909 /// GetNameForMethod - Return a name for the given method.
910 /// \param[out] NameOut - The return value.
911 void GetNameForMethod(const ObjCMethodDecl *OMD,
912 const ObjCContainerDecl *CD,
Daniel Dunbard2386812009-10-19 01:21:19 +0000913 llvm::SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000914
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000915 /// GetMethodVarName - Return a unique constant for the given
916 /// selector's name. The return value has type char *.
917 llvm::Constant *GetMethodVarName(Selector Sel);
918 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
919 llvm::Constant *GetMethodVarName(const std::string &Name);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000920
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000921 /// GetMethodVarType - Return a unique constant for the given
922 /// selector's name. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000923
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000924 // FIXME: This is a horrible name.
925 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000926 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000927
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000928 /// GetPropertyName - Return a unique constant for the given
929 /// name. The return value has type char *.
930 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000931
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000932 // FIXME: This can be dropped once string functions are unified.
933 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
934 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000935
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000936 /// GetClassName - Return a unique constant for the given selector's
937 /// name. The return value has type char *.
938 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000939
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000940 /// BuildIvarLayout - Builds ivar layout bitmap for the class
941 /// implementation for the __strong or __weak case.
942 ///
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000943 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
944 bool ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +0000945
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +0000946 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000947
Daniel Dunbar15bd8882009-05-03 14:10:34 +0000948 void BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000949 unsigned int BytePos, bool ForStrongLayout,
950 bool &HasUnion);
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +0000951 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000952 const llvm::StructLayout *Layout,
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000953 const RecordDecl *RD,
Chris Lattner5b36ddb2009-03-31 08:48:01 +0000954 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000955 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahaniana123b642009-04-24 16:17:09 +0000956 bool &HasUnion);
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000957
Fariborz Jahanian01dff422009-03-05 19:17:31 +0000958 /// GetIvarLayoutName - Returns a unique constant for the given
959 /// ivar layout bitmap.
960 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
961 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000962
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000963 /// EmitPropertyList - Emit the given property list. The return
964 /// value has type PropertyListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000965 llvm::Constant *EmitPropertyList(llvm::Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000966 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000967 const ObjCContainerDecl *OCD,
968 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000969
Fariborz Jahanian751c1e72009-12-12 21:26:21 +0000970 /// PushProtocolProperties - Push protocol's property on the input stack.
971 void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
972 std::vector<llvm::Constant*> &Properties,
973 const Decl *Container,
974 const ObjCProtocolDecl *PROTO,
975 const ObjCCommonTypesHelper &ObjCTypes);
976
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000977 /// GetProtocolRef - Return a reference to the internal protocol
978 /// description, creating an empty one if it has not been
979 /// defined. The return value has type ProtocolPtrTy.
980 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +0000981
Daniel Dunbar30c65362009-03-09 20:09:19 +0000982 /// CreateMetadataVar - Create a global variable with internal
983 /// linkage for use by the Objective-C runtime.
984 ///
985 /// This is a convenience wrapper which not only creates the
986 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +0000987 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +0000988 ///
989 /// \param Name - The variable name.
990 /// \param Init - The variable initializer; this is also used to
991 /// define the type of the variable.
992 /// \param Section - The section the variable should go into, or 0.
993 /// \param Align - The alignment for the variable, or 0.
994 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbar4527d302009-04-14 17:42:51 +0000995 /// "llvm.used".
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000996 llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +0000997 llvm::Constant *Init,
998 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +0000999 unsigned Align,
1000 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +00001001
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001002 CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001003 ReturnValueSlot Return,
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001004 QualType ResultType,
1005 llvm::Value *Sel,
1006 llvm::Value *Arg0,
1007 QualType Arg0Ty,
1008 bool IsSuper,
1009 const CallArgList &CallArgs,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001010 const ObjCMethodDecl *OMD,
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001011 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +00001012
Daniel Dunbar5e639272010-04-25 20:39:01 +00001013 /// EmitImageInfo - Emit the image info marker used to encode some module
1014 /// level information.
1015 void EmitImageInfo();
1016
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001017public:
Owen Andersonae86c192009-07-13 04:10:07 +00001018 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
Mike Stump11289f42009-09-09 15:08:12 +00001019 CGM(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001020
David Chisnall481e3a82010-01-23 02:40:42 +00001021 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001022
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001023 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
1024 const ObjCContainerDecl *CD=0);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001025
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001026 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001027
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001028 /// GetOrEmitProtocol - Get the protocol object for the given
1029 /// declaration, emitting it if necessary. The return value has type
1030 /// ProtocolPtrTy.
1031 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001032
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001033 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1034 /// object for the given declaration, emitting it if needed. These
1035 /// forward references will be filled in with empty bodies if no
1036 /// definition is seen. The return value has type ProtocolPtrTy.
1037 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001038 virtual llvm::Constant *GCBlockLayout(CodeGen::CodeGenFunction &CGF,
1039 const llvm::SmallVectorImpl<const BlockDeclRefExpr *> &);
1040
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001041};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001042
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001043class CGObjCMac : public CGObjCCommonMac {
1044private:
1045 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001046
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001047 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001048 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001049 void EmitModuleInfo();
1050
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001051 /// EmitModuleSymols - Emit module symbols, the list of defined
1052 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001053 llvm::Constant *EmitModuleSymbols();
1054
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001055 /// FinishModule - Write out global data structures at the end of
1056 /// processing a translation unit.
1057 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +00001058
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001059 /// EmitClassExtension - Generate the class extension structure used
1060 /// to store the weak ivar layout and properties. The return value
1061 /// has type ClassExtensionPtrTy.
1062 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
1063
1064 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1065 /// for the given class.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001066 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001067 const ObjCInterfaceDecl *ID);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001068
1069 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1070 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001071
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001072 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001073 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001074 QualType ResultType,
1075 Selector Sel,
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001076 llvm::Value *Arg0,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001077 QualType Arg0Ty,
1078 bool IsSuper,
1079 const CallArgList &CallArgs);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001080
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001081 /// EmitIvarList - Emit the ivar list for the given
1082 /// implementation. If ForClass is true the list of class ivars
1083 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1084 /// interface ivars will be emitted. The return value has type
1085 /// IvarListPtrTy.
1086 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00001087 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001088
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001089 /// EmitMetaClass - Emit a forward reference to the class structure
1090 /// for the metaclass of the given interface. The return value has
1091 /// type ClassPtrTy.
1092 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1093
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001094 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001095 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001096 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1097 llvm::Constant *Protocols,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001098 const ConstantVector &Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001099
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001100 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001101
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001102 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001103
1104 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +00001105 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001106 llvm::Constant *EmitMethodList(llvm::Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00001107 const char *Section,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001108 const ConstantVector &Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001109
1110 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001111 /// method declarations.
Daniel Dunbarb036db82008-08-13 03:21:16 +00001112 /// - TypeName: The name for the type containing the methods.
1113 /// - IsProtocol: True iff these methods are for a protocol.
1114 /// - ClassMethds: True iff these are class methods.
1115 /// - Required: When true, only "required" methods are
1116 /// listed. Similarly, when false only "optional" methods are
1117 /// listed. For classes this should always be true.
1118 /// - begin, end: The method list to output.
1119 ///
1120 /// The return value has type MethodDescriptionListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001121 llvm::Constant *EmitMethodDescList(llvm::Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001122 const char *Section,
1123 const ConstantVector &Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001124
Daniel Dunbarc475d422008-10-29 22:36:39 +00001125 /// GetOrEmitProtocol - Get the protocol object for the given
1126 /// declaration, emitting it if necessary. The return value has type
1127 /// ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001128 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001129
1130 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1131 /// object for the given declaration, emitting it if needed. These
1132 /// forward references will be filled in with empty bodies if no
1133 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001134 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001135
Daniel Dunbarb036db82008-08-13 03:21:16 +00001136 /// EmitProtocolExtension - Generate the protocol extension
1137 /// structure used to store optional instance and class methods, and
1138 /// protocol properties. The return value has type
1139 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001140 llvm::Constant *
1141 EmitProtocolExtension(const ObjCProtocolDecl *PD,
1142 const ConstantVector &OptInstanceMethods,
1143 const ConstantVector &OptClassMethods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001144
1145 /// EmitProtocolList - Generate the list of referenced
1146 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001147 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001148 ObjCProtocolDecl::protocol_iterator begin,
1149 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001150
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001151 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1152 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001153 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1154 bool lval=false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001155
1156public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001157 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001158
Fariborz Jahanian71394042009-01-23 23:53:38 +00001159 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001160
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001161 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001162 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001163 QualType ResultType,
1164 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001165 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001166 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001167 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001168 const ObjCMethodDecl *Method);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001169
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001170 virtual CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001171 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001172 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001173 QualType ResultType,
1174 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001175 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001176 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001177 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001178 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001179 const CallArgList &CallArgs,
1180 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001181
Daniel Dunbarcb463852008-11-01 01:53:16 +00001182 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001183 const ObjCInterfaceDecl *ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001184
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001185 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1186 bool lval = false);
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001187
1188 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1189 /// untyped one.
1190 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1191 const ObjCMethodDecl *Method);
1192
John McCall2ca705e2010-07-24 00:37:23 +00001193 virtual llvm::Constant *GetEHType(QualType T);
1194
Daniel Dunbar92992502008-08-15 22:20:32 +00001195 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001196
Daniel Dunbar92992502008-08-15 22:20:32 +00001197 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001198
Daniel Dunbarcb463852008-11-01 01:53:16 +00001199 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001200 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001201
Chris Lattnerd4808922009-03-22 21:03:39 +00001202 virtual llvm::Constant *GetPropertyGetFunction();
1203 virtual llvm::Constant *GetPropertySetFunction();
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001204 virtual llvm::Constant *GetCopyStructFunction();
Chris Lattnerd4808922009-03-22 21:03:39 +00001205 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001206
John McCallbd309292010-07-06 01:34:17 +00001207 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1208 const ObjCAtTryStmt &S);
1209 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1210 const ObjCAtSynchronizedStmt &S);
1211 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00001212 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1213 const ObjCAtThrowStmt &S);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001214 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001215 llvm::Value *AddrWeakObj);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001216 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001217 llvm::Value *src, llvm::Value *dst);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001218 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001219 llvm::Value *src, llvm::Value *dest,
1220 bool threadlocal = false);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00001221 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001222 llvm::Value *src, llvm::Value *dest,
1223 llvm::Value *ivarOffset);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001224 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1225 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001226 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1227 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001228 llvm::Value *size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001229
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001230 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1231 QualType ObjectTy,
1232 llvm::Value *BaseValue,
1233 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001234 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001235 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001236 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001237 const ObjCIvarDecl *Ivar);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001238};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001239
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001240class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001241private:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001242 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001243 llvm::GlobalVariable* ObjCEmptyCacheVar;
1244 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001245
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001246 /// SuperClassReferences - uniqued super class references.
1247 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001248
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001249 /// MetaClassReferences - uniqued meta class references.
1250 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001251
1252 /// EHTypeReferences - uniqued class ehtype references.
1253 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001254
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001255 /// NonLegacyDispatchMethods - List of methods for which we do *not* generate
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001256 /// legacy messaging dispatch.
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001257 llvm::DenseSet<Selector> NonLegacyDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001258
Fariborz Jahanian67260552009-11-17 21:37:35 +00001259 /// DefinedMetaClasses - List of defined meta-classes.
1260 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1261
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001262 /// LegacyDispatchedSelector - Returns true if SEL is not in the list of
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001263 /// NonLegacyDispatchMethods; false otherwise.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001264 bool LegacyDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001265
Fariborz Jahanian71394042009-01-23 23:53:38 +00001266 /// FinishNonFragileABIModule - Write out global data structures at the end of
1267 /// processing a translation unit.
1268 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001269
Daniel Dunbar19573e72009-05-15 21:48:48 +00001270 /// AddModuleClassList - Add the given list of class pointers to the
1271 /// module with the provided symbol and section names.
1272 void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
1273 const char *SymbolName,
1274 const char *SectionName);
1275
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001276 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1277 unsigned InstanceStart,
1278 unsigned InstanceSize,
1279 const ObjCImplementationDecl *ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001280 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001281 llvm::Constant *IsAGV,
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001282 llvm::Constant *SuperClassGV,
Fariborz Jahanian82208252009-01-31 00:59:10 +00001283 llvm::Constant *ClassRoGV,
1284 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001285
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001286 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001287
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00001288 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001289
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001290 /// EmitMethodList - Emit the method list for the given
1291 /// implementation. The return value has type MethodListnfABITy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001292 llvm::Constant *EmitMethodList(llvm::Twine Name,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001293 const char *Section,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001294 const ConstantVector &Methods);
1295 /// EmitIvarList - Emit the ivar list for the given
1296 /// implementation. If ForClass is true the list of class ivars
1297 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1298 /// interface ivars will be emitted. The return value has type
1299 /// IvarListnfABIPtrTy.
1300 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001301
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001302 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001303 const ObjCIvarDecl *Ivar,
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00001304 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001305
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001306 /// GetOrEmitProtocol - Get the protocol object for the given
1307 /// declaration, emitting it if necessary. The return value has type
1308 /// ProtocolPtrTy.
1309 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001310
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001311 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1312 /// object for the given declaration, emitting it if needed. These
1313 /// forward references will be filled in with empty bodies if no
1314 /// definition is seen. The return value has type ProtocolPtrTy.
1315 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001316
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001317 /// EmitProtocolList - Generate the list of referenced
1318 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001319 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001320 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001321 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001322
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001323 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001324 ReturnValueSlot Return,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001325 QualType ResultType,
1326 Selector Sel,
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00001327 llvm::Value *Receiver,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001328 QualType Arg0Ty,
1329 bool IsSuper,
1330 const CallArgList &CallArgs);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001331
1332 /// GetClassGlobal - Return the global variable for the Objective-C
1333 /// class of the given name.
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00001334 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001335
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001336 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001337 /// for the given class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001338 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001339 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001340
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001341 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1342 /// for the given super class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001343 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1344 const ObjCInterfaceDecl *ID);
1345
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001346 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1347 /// meta-data
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001348 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001349 const ObjCInterfaceDecl *ID);
1350
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001351 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1352 /// the given ivar.
1353 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001354 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001355 const ObjCInterfaceDecl *ID,
1356 const ObjCIvarDecl *Ivar);
1357
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001358 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1359 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001360 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1361 bool lval=false);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001362
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001363 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001364 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001365 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001366 bool ForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001367
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001368 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar15894b72009-04-07 05:48:37 +00001369 return "OBJC_METACLASS_$_";
1370 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001371
Daniel Dunbar15894b72009-04-07 05:48:37 +00001372 const char *getClassSymbolPrefix() const {
1373 return "OBJC_CLASS_$_";
1374 }
1375
Daniel Dunbar961202372009-05-03 12:57:56 +00001376 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001377 uint32_t &InstanceStart,
1378 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001379
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001380 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001381 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001382 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1383 return CGM.getContext().Selectors.getSelector(0, &II);
1384 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001385
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001386 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001387 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1388 return CGM.getContext().Selectors.getSelector(1, &II);
1389 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001390
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001391 /// ImplementationIsNonLazy - Check whether the given category or
1392 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001393 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001394
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001395public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001396 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001397 // FIXME. All stubs for now!
1398 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001399
Fariborz Jahanian71394042009-01-23 23:53:38 +00001400 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001401 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001402 QualType ResultType,
1403 Selector Sel,
1404 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001405 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001406 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001407 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001408
1409 virtual CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001410 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001411 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001412 QualType ResultType,
1413 Selector Sel,
1414 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001415 bool isCategoryImpl,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001416 llvm::Value *Receiver,
1417 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001418 const CallArgList &CallArgs,
1419 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001420
Fariborz Jahanian71394042009-01-23 23:53:38 +00001421 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001422 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001423
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001424 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1425 bool lvalue = false)
1426 { return EmitSelector(Builder, Sel, lvalue); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001427
1428 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1429 /// untyped one.
1430 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1431 const ObjCMethodDecl *Method)
1432 { return EmitSelector(Builder, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001433
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00001434 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001435
Fariborz Jahanian71394042009-01-23 23:53:38 +00001436 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001437 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian097feda2009-01-30 18:58:59 +00001438 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001439
John McCall2ca705e2010-07-24 00:37:23 +00001440 virtual llvm::Constant *GetEHType(QualType T);
1441
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001442 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001443 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001444 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001445 virtual llvm::Constant *GetPropertySetFunction() {
1446 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001447 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001448
1449 virtual llvm::Constant *GetCopyStructFunction() {
1450 return ObjCTypes.getCopyStructFn();
1451 }
1452
Chris Lattnerd4808922009-03-22 21:03:39 +00001453 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001454 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001455 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001456
John McCallbd309292010-07-06 01:34:17 +00001457 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1458 const ObjCAtTryStmt &S);
1459 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1460 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001461 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlsson9ab53d12009-02-16 22:59:18 +00001462 const ObjCAtThrowStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001463 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001464 llvm::Value *AddrWeakObj);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001465 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001466 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001467 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001468 llvm::Value *src, llvm::Value *dest,
1469 bool threadlocal = false);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001470 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001471 llvm::Value *src, llvm::Value *dest,
1472 llvm::Value *ivarOffset);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001473 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001474 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001475 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1476 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001477 llvm::Value *size);
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001478 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1479 QualType ObjectTy,
1480 llvm::Value *BaseValue,
1481 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001482 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001483 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001484 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001485 const ObjCIvarDecl *Ivar);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001486};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001487
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001488} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001489
1490/* *** Helper Functions *** */
1491
1492/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001493static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001494 llvm::Constant *C,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001495 unsigned idx0,
1496 unsigned idx1) {
1497 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001498 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1499 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001500 };
Owen Andersonade90fd2009-07-29 18:54:39 +00001501 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001502}
1503
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001504/// hasObjCExceptionAttribute - Return true if this class or any super
1505/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001506static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001507 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001508 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001509 return true;
1510 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001511 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001512 return false;
1513}
1514
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001515/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001516
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001517CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001518 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001519 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001520 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001521}
1522
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001523/// GetClass - Return a reference to the class for the given interface
1524/// decl.
Daniel Dunbarcb463852008-11-01 01:53:16 +00001525llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001526 const ObjCInterfaceDecl *ID) {
1527 return EmitClassRef(Builder, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001528}
1529
1530/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001531llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1532 bool lval) {
1533 return EmitSelector(Builder, Sel, lval);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001534}
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001535llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001536 *Method) {
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001537 return EmitSelector(Builder, Method->getSelector());
1538}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001539
John McCall2ca705e2010-07-24 00:37:23 +00001540llvm::Constant *CGObjCMac::GetEHType(QualType T) {
1541 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
1542 return 0;
1543}
1544
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001545/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001546/*
1547 struct __builtin_CFString {
1548 const int *isa; // point to __CFConstantStringClassReference
1549 int flags;
1550 const char *str;
1551 long length;
1552 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001553*/
1554
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001555/// or Generate a constant NSString object.
1556/*
1557 struct __builtin_NSString {
1558 const int *isa; // point to __NSConstantStringClassReference
1559 const char *str;
1560 unsigned int length;
1561 };
1562*/
1563
Fariborz Jahanian71394042009-01-23 23:53:38 +00001564llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall481e3a82010-01-23 02:40:42 +00001565 const StringLiteral *SL) {
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001566 return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
1567 CGM.GetAddrOfConstantCFString(SL) :
1568 CGM.GetAddrOfConstantNSString(SL));
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001569}
1570
1571/// Generates a message send where the super is the receiver. This is
1572/// a message send to self with special delivery semantics indicating
1573/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001574CodeGen::RValue
1575CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001576 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001577 QualType ResultType,
1578 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001579 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001580 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001581 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001582 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001583 const CodeGen::CallArgList &CallArgs,
1584 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001585 // Create and init a super structure; this is a (receiver, class)
1586 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001587 llvm::Value *ObjCSuper =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001588 CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001589 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001590 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001591 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001592 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001593
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001594 // If this is a class message the metaclass is passed as the target.
1595 llvm::Value *Target;
1596 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001597 if (isCategoryImpl) {
1598 // Message sent to 'super' in a class method defined in a category
1599 // implementation requires an odd treatment.
1600 // If we are in a class method, we must retrieve the
1601 // _metaclass_ for the current class, pointed at by
1602 // the class's "isa" pointer. The following assumes that
1603 // isa" is the first ivar in a class (which it must be).
1604 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1605 Target = CGF.Builder.CreateStructGEP(Target, 0);
1606 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00001607 } else {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001608 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1609 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1610 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1611 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001612 }
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00001613 }
1614 else if (isCategoryImpl)
1615 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1616 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001617 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1618 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1619 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001620 }
Mike Stump18bb9282009-05-16 07:57:57 +00001621 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1622 // ObjCTypes types.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001623 const llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00001624 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00001625 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001626 CGF.Builder.CreateStore(Target,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001627 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall78a15112010-05-22 01:48:05 +00001628 return EmitLegacyMessageSend(CGF, Return, ResultType,
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001629 EmitSelector(CGF.Builder, Sel),
1630 ObjCSuper, ObjCTypes.SuperPtrCTy,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001631 true, CallArgs, Method, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001632}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001633
1634/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001635CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001636 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001637 QualType ResultType,
1638 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001639 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001640 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001641 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001642 const ObjCMethodDecl *Method) {
John McCall78a15112010-05-22 01:48:05 +00001643 return EmitLegacyMessageSend(CGF, Return, ResultType,
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001644 EmitSelector(CGF.Builder, Sel),
1645 Receiver, CGF.getContext().getObjCIdType(),
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001646 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001647}
1648
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001649CodeGen::RValue
1650CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001651 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001652 QualType ResultType,
1653 llvm::Value *Sel,
1654 llvm::Value *Arg0,
1655 QualType Arg0Ty,
1656 bool IsSuper,
1657 const CallArgList &CallArgs,
1658 const ObjCMethodDecl *Method,
1659 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00001660 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00001661 if (!IsSuper)
1662 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Daniel Dunbar41cf9de2008-09-09 01:06:48 +00001663 ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001664 ActualArgs.push_back(std::make_pair(RValue::get(Sel),
Daniel Dunbarc722b852008-08-30 03:02:31 +00001665 CGF.getContext().getObjCSelType()));
1666 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001667
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00001668 CodeGenTypes &Types = CGM.getTypes();
John McCallab26cfa2010-02-05 21:31:56 +00001669 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindolac50c27c2010-03-30 20:24:48 +00001670 FunctionType::ExtInfo());
Daniel Dunbardf0e62d2009-09-17 04:01:40 +00001671 const llvm::FunctionType *FTy =
1672 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001673
Anders Carlsson280e61f12010-06-21 20:59:55 +00001674 if (Method)
1675 assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1676 CGM.getContext().getCanonicalType(ResultType) &&
1677 "Result type mismatch!");
1678
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001679 llvm::Constant *Fn = NULL;
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001680 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001681 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001682 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001683 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1684 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1685 : ObjCTypes.getSendFpretFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001686 } else {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001687 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001688 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001689 }
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001690 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
John McCall78a15112010-05-22 01:48:05 +00001691 return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001692}
1693
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001694static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1695 if (FQT.isObjCGCStrong())
1696 return Qualifiers::Strong;
1697
1698 if (FQT.isObjCGCWeak())
1699 return Qualifiers::Weak;
1700
1701 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1702 return Qualifiers::Strong;
1703
1704 if (const PointerType *PT = FQT->getAs<PointerType>())
1705 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1706
1707 return Qualifiers::GCNone;
1708}
1709
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001710llvm::Constant *CGObjCCommonMac::GCBlockLayout(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanianafa3c0a2010-08-04 18:44:59 +00001711 const llvm::SmallVectorImpl<const BlockDeclRefExpr *> &DeclRefs) {
1712 llvm::Constant *NullPtr =
1713 llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
Fariborz Jahanian89f37212010-08-05 15:52:12 +00001714 if ((CGM.getLangOptions().getGCMode() == LangOptions::NonGC) ||
1715 DeclRefs.empty())
Fariborz Jahanianafa3c0a2010-08-04 18:44:59 +00001716 return NullPtr;
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001717 bool hasUnion = false;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001718 SkipIvars.clear();
1719 IvarsInfo.clear();
1720 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
1721 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
1722
1723 for (size_t i = 0; i < DeclRefs.size(); ++i) {
1724 const BlockDeclRefExpr *BDRE = DeclRefs[i];
1725 const ValueDecl *VD = BDRE->getDecl();
1726 CharUnits Offset = CGF.BlockDecls[VD];
1727 uint64_t FieldOffset = Offset.getQuantity();
1728 QualType Ty = VD->getType();
1729 assert(!Ty->isArrayType() &&
1730 "Array block variable should have been caught");
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001731 if ((Ty->isRecordType() || Ty->isUnionType()) && !BDRE->isByRef()) {
Fariborz Jahanian903aba32010-08-05 21:00:25 +00001732 BuildAggrIvarRecordLayout(Ty->getAs<RecordType>(),
1733 FieldOffset,
1734 true,
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001735 hasUnion);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00001736 continue;
1737 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001738
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001739 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), Ty);
1740 unsigned FieldSize = CGM.getContext().getTypeSize(Ty);
1741 // __block variables are passed by their descriptior address. So, size
1742 // must reflect this.
1743 if (BDRE->isByRef())
1744 FieldSize = WordSizeInBits;
1745 if (GCAttr == Qualifiers::Strong || BDRE->isByRef())
1746 IvarsInfo.push_back(GC_IVAR(FieldOffset,
1747 FieldSize / WordSizeInBits));
1748 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
1749 SkipIvars.push_back(GC_IVAR(FieldOffset,
1750 FieldSize / ByteSizeInBits));
1751 }
1752
1753 if (IvarsInfo.empty())
1754 return NullPtr;
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001755 // Sort on byte position in case we encounterred a union nested in
1756 // block variable type's aggregate type.
1757 if (hasUnion && !IvarsInfo.empty())
1758 std::sort(IvarsInfo.begin(), IvarsInfo.end());
1759 if (hasUnion && !SkipIvars.empty())
1760 std::sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001761
1762 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00001763 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001764 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
1765 printf("\n block variable layout for block: ");
1766 const unsigned char *s = (unsigned char*)BitMap.c_str();
1767 for (unsigned i = 0; i < BitMap.size(); i++)
1768 if (!(s[i] & 0xf0))
1769 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1770 else
1771 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
1772 printf("\n");
1773 }
1774
1775 return C;
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001776}
1777
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001778llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001779 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00001780 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00001781 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00001782 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1783
Owen Andersonade90fd2009-07-29 18:54:39 +00001784 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Daniel Dunbarb036db82008-08-13 03:21:16 +00001785 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001786}
1787
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001788void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00001789 // FIXME: We shouldn't need this, the protocol decl should contain enough
1790 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00001791 DefinedProtocols.insert(PD->getIdentifier());
1792
1793 // If we have generated a forward reference to this protocol, emit
1794 // it now. Otherwise do nothing, the protocol objects are lazily
1795 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001796 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00001797 GetOrEmitProtocol(PD);
1798}
1799
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001800llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001801 if (DefinedProtocols.count(PD->getIdentifier()))
1802 return GetOrEmitProtocol(PD);
1803 return GetOrEmitProtocolRef(PD);
1804}
1805
Daniel Dunbarb036db82008-08-13 03:21:16 +00001806/*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001807// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1808struct _objc_protocol {
1809struct _objc_protocol_extension *isa;
1810char *protocol_name;
1811struct _objc_protocol_list *protocol_list;
1812struct _objc__method_prototype_list *instance_methods;
1813struct _objc__method_prototype_list *class_methods
1814};
Daniel Dunbarb036db82008-08-13 03:21:16 +00001815
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001816See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00001817*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00001818llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1819 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1820
1821 // Early exit if a defining object has already been generated.
1822 if (Entry && Entry->hasInitializer())
1823 return Entry;
1824
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00001825 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00001826 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00001827 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1828
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001829 // Construct method lists.
1830 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1831 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001832 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00001833 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001834 ObjCMethodDecl *MD = *i;
1835 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1836 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1837 OptInstanceMethods.push_back(C);
1838 } else {
1839 InstanceMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001840 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001841 }
1842
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001843 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00001844 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001845 ObjCMethodDecl *MD = *i;
1846 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1847 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1848 OptClassMethods.push_back(C);
1849 } else {
1850 ClassMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001851 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001852 }
1853
Daniel Dunbarb036db82008-08-13 03:21:16 +00001854 std::vector<llvm::Constant*> Values(5);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001855 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001856 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001857 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001858 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00001859 PD->protocol_begin(),
1860 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001861 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001862 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001863 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1864 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001865 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001866 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001867 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1868 ClassMethods);
Owen Anderson0e0189d2009-07-27 22:29:56 +00001869 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001870 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001871
Daniel Dunbarb036db82008-08-13 03:21:16 +00001872 if (Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001873 // Already created, fix the linkage and update the initializer.
1874 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001875 Entry->setInitializer(Init);
1876 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001877 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00001878 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001879 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001880 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001881 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00001882 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00001883 // FIXME: Is this necessary? Why only for protocol?
1884 Entry->setAlignment(4);
1885 }
Chris Lattnerf56501c2009-07-17 23:57:13 +00001886 CGM.AddUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001887
1888 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00001889}
1890
Daniel Dunbarc475d422008-10-29 22:36:39 +00001891llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001892 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1893
1894 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001895 // We use the initializer as a marker of whether this is a forward
1896 // reference or not. At module finalization we add the empty
1897 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001898 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00001899 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarc475d422008-10-29 22:36:39 +00001900 llvm::GlobalValue::ExternalLinkage,
1901 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001902 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00001903 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00001904 // FIXME: Is this necessary? Why only for protocol?
1905 Entry->setAlignment(4);
1906 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001907
Daniel Dunbarb036db82008-08-13 03:21:16 +00001908 return Entry;
1909}
1910
1911/*
1912 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001913 uint32_t size;
1914 struct objc_method_description_list *optional_instance_methods;
1915 struct objc_method_description_list *optional_class_methods;
1916 struct objc_property_list *instance_properties;
Daniel Dunbarb036db82008-08-13 03:21:16 +00001917 };
1918*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001919llvm::Constant *
1920CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1921 const ConstantVector &OptInstanceMethods,
1922 const ConstantVector &OptClassMethods) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001923 uint64_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00001924 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001925 std::vector<llvm::Constant*> Values(4);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001926 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001927 Values[1] =
1928 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001929 + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001930 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1931 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001932 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001933 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001934 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1935 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001936 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00001937 0, PD, ObjCTypes);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001938
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001939 // Return null if no extension bits are used.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001940 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Daniel Dunbarb036db82008-08-13 03:21:16 +00001941 Values[3]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00001942 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001943
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001944 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00001945 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001946
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001947 // No special section, but goes in llvm.used
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001948 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001949 Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001950 0, 0, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001951}
1952
1953/*
1954 struct objc_protocol_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001955 struct objc_protocol_list *next;
1956 long count;
1957 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00001958 };
1959*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00001960llvm::Constant *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001961CGObjCMac::EmitProtocolList(llvm::Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001962 ObjCProtocolDecl::protocol_iterator begin,
1963 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001964 std::vector<llvm::Constant*> ProtocolRefs;
1965
Daniel Dunbardec75f82008-08-21 21:57:41 +00001966 for (; begin != end; ++begin)
1967 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarb036db82008-08-13 03:21:16 +00001968
1969 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001970 if (ProtocolRefs.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00001971 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001972
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001973 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00001974 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbarb036db82008-08-13 03:21:16 +00001975
1976 std::vector<llvm::Constant*> Values(3);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001977 // This field is only used by the runtime.
Owen Anderson0b75f232009-07-31 20:28:54 +00001978 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001979 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001980 ProtocolRefs.size() - 1);
1981 Values[2] =
1982 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1983 ProtocolRefs.size()),
Daniel Dunbarb036db82008-08-13 03:21:16 +00001984 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001985
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00001986 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001987 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001988 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00001989 4, false);
Owen Andersonade90fd2009-07-29 18:54:39 +00001990 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001991}
1992
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00001993void CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
1994 std::vector<llvm::Constant*> &Properties,
1995 const Decl *Container,
1996 const ObjCProtocolDecl *PROTO,
1997 const ObjCCommonTypesHelper &ObjCTypes) {
1998 std::vector<llvm::Constant*> Prop(2);
1999 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
2000 E = PROTO->protocol_end(); P != E; ++P)
2001 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
2002 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
2003 E = PROTO->prop_end(); I != E; ++I) {
2004 const ObjCPropertyDecl *PD = *I;
2005 if (!PropertySet.insert(PD->getIdentifier()))
2006 continue;
2007 Prop[0] = GetPropertyName(PD->getIdentifier());
2008 Prop[1] = GetPropertyTypeString(PD, Container);
2009 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
2010 }
2011}
2012
Daniel Dunbarb036db82008-08-13 03:21:16 +00002013/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002014 struct _objc_property {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002015 const char * const name;
2016 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002017 };
2018
2019 struct _objc_property_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002020 uint32_t entsize; // sizeof (struct _objc_property)
2021 uint32_t prop_count;
2022 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002023 };
2024*/
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002025llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002026 const Decl *Container,
2027 const ObjCContainerDecl *OCD,
2028 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002029 std::vector<llvm::Constant*> Properties, Prop(2);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002030 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002031 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2032 E = OCD->prop_end(); I != E; ++I) {
Steve Naroffba3dc382009-01-11 12:47:58 +00002033 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002034 PropertySet.insert(PD->getIdentifier());
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002035 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbar4932b362008-08-28 04:38:10 +00002036 Prop[1] = GetPropertyTypeString(PD, Container);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002037 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002038 Prop));
2039 }
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002040 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002041 for (ObjCInterfaceDecl::protocol_iterator P = OID->protocol_begin(),
2042 E = OID->protocol_end(); P != E; ++P)
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002043 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2044 ObjCTypes);
2045 }
2046 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2047 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
2048 E = CD->protocol_end(); P != E; ++P)
2049 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2050 ObjCTypes);
2051 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002052
2053 // Return null for empty list.
2054 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002055 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002056
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002057 unsigned PropertySize =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002058 CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002059 std::vector<llvm::Constant*> Values(3);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002060 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2061 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002062 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002063 Properties.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002064 Values[2] = llvm::ConstantArray::get(AT, Properties);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002065 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002066
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002067 llvm::GlobalVariable *GV =
2068 CreateMetadataVar(Name, Init,
2069 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002070 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002071 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002072 true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002073 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002074}
2075
2076/*
Daniel Dunbarb036db82008-08-13 03:21:16 +00002077 struct objc_method_description_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002078 int count;
2079 struct objc_method_description list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002080 };
2081*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002082llvm::Constant *
2083CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
2084 std::vector<llvm::Constant*> Desc(2);
Owen Anderson170229f2009-07-14 23:10:40 +00002085 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002086 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
2087 ObjCTypes.SelectorPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002088 Desc[1] = GetMethodVarType(MD);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002089 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002090 Desc);
2091}
Daniel Dunbarb036db82008-08-13 03:21:16 +00002092
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002093llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002094 const char *Section,
2095 const ConstantVector &Methods) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002096 // Return null for empty list.
2097 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002098 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002099
2100 std::vector<llvm::Constant*> Values(2);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002101 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002102 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002103 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002104 Values[1] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002105 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002106
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002107 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002108 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002109 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002110}
2111
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002112/*
2113 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002114 char *category_name;
2115 char *class_name;
2116 struct _objc_method_list *instance_methods;
2117 struct _objc_method_list *class_methods;
2118 struct _objc_protocol_list *protocols;
2119 uint32_t size; // <rdar://4585769>
2120 struct _objc_property_list *instance_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002121 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002122*/
Daniel Dunbar92992502008-08-15 22:20:32 +00002123void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002124 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002125
Mike Stump18bb9282009-05-16 07:57:57 +00002126 // FIXME: This is poor design, the OCD should have a pointer to the category
2127 // decl. Additionally, note that Category can be null for the @implementation
2128 // w/o an @interface case. Sema should just create one for us as it does for
2129 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002130 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002131 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002132 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002133
2134 llvm::SmallString<256> ExtName;
2135 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2136 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002137
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002138 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002139 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002140 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002141 // Instance methods should always be defined.
2142 InstanceMethods.push_back(GetMethodConstant(*i));
2143 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002144 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002145 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002146 // Class methods should always be defined.
2147 ClassMethods.push_back(GetMethodConstant(*i));
2148 }
2149
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002150 std::vector<llvm::Constant*> Values(7);
2151 Values[0] = GetClassName(OCD->getIdentifier());
2152 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00002153 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002154 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002155 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002156 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002157 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002158 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002159 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002160 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002161 ClassMethods);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002162 if (Category) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002163 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002164 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002165 Category->protocol_begin(),
2166 Category->protocol_end());
2167 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002168 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002169 }
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002170 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002171
2172 // If there is no category @interface then there can be no properties.
2173 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002174 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002175 OCD, Category, ObjCTypes);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002176 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002177 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002178 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002179
Owen Anderson0e0189d2009-07-27 22:29:56 +00002180 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002181 Values);
2182
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002183 llvm::GlobalVariable *GV =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002184 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002185 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002186 4, true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002187 DefinedCategories.push_back(GV);
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00002188 DefinedCategoryNames.insert(ExtName.str());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002189}
2190
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002191// FIXME: Get from somewhere?
2192enum ClassFlags {
2193 eClassFlags_Factory = 0x00001,
2194 eClassFlags_Meta = 0x00002,
2195 // <rdr://5142207>
2196 eClassFlags_HasCXXStructors = 0x02000,
2197 eClassFlags_Hidden = 0x20000,
2198 eClassFlags_ABI2_Hidden = 0x00010,
2199 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
2200};
2201
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002202/*
2203 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002204 Class isa;
2205 Class super_class;
2206 const char *name;
2207 long version;
2208 long info;
2209 long instance_size;
2210 struct _objc_ivar_list *ivars;
2211 struct _objc_method_list *methods;
2212 struct _objc_cache *cache;
2213 struct _objc_protocol_list *protocols;
2214 // Objective-C 1.0 extensions (<rdr://4585769>)
2215 const char *ivar_layout;
2216 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002217 };
2218
2219 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002220*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002221void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002222 DefinedSymbols.insert(ID->getIdentifier());
2223
Chris Lattner86d7d912008-11-24 03:54:41 +00002224 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002225 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002226 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002227 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002228 llvm::Constant *Protocols =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002229 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00002230 Interface->protocol_begin(),
2231 Interface->protocol_end());
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002232 unsigned Flags = eClassFlags_Factory;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00002233 if (ID->getNumIvarInitializers())
2234 Flags |= eClassFlags_HasCXXStructors;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002235 unsigned Size =
Daniel Dunbar12119b92009-05-03 10:46:44 +00002236 CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002237
2238 // FIXME: Set CXX-structors flag.
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00002239 if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002240 Flags |= eClassFlags_Hidden;
2241
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002242 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002243 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002244 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002245 // Instance methods should always be defined.
2246 InstanceMethods.push_back(GetMethodConstant(*i));
2247 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002248 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002249 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002250 // Class methods should always be defined.
2251 ClassMethods.push_back(GetMethodConstant(*i));
2252 }
2253
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002254 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002255 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002256 ObjCPropertyImplDecl *PID = *i;
2257
2258 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2259 ObjCPropertyDecl *PD = PID->getPropertyDecl();
2260
2261 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2262 if (llvm::Constant *C = GetMethodConstant(MD))
2263 InstanceMethods.push_back(C);
2264 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2265 if (llvm::Constant *C = GetMethodConstant(MD))
2266 InstanceMethods.push_back(C);
2267 }
2268 }
2269
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002270 std::vector<llvm::Constant*> Values(12);
Daniel Dunbarccf61832009-05-03 08:56:52 +00002271 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002272 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002273 // Record a reference to the super class.
2274 LazySymbols.insert(Super->getIdentifier());
2275
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002276 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002277 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002278 ObjCTypes.ClassPtrTy);
2279 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002280 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002281 }
2282 Values[ 2] = GetClassName(ID->getIdentifier());
2283 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002284 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2285 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2286 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002287 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002288 Values[ 7] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002289 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002290 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002291 InstanceMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002292 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002293 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002294 Values[ 9] = Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002295 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002296 Values[11] = EmitClassExtension(ID);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002297 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002298 Values);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002299 std::string Name("\01L_OBJC_CLASS_");
2300 Name += ClassName;
2301 const char *Section = "__OBJC,__class,regular,no_dead_strip";
2302 // Check for a forward reference.
2303 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2304 if (GV) {
2305 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2306 "Forward metaclass reference has incorrect type.");
2307 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2308 GV->setInitializer(Init);
2309 GV->setSection(Section);
2310 GV->setAlignment(4);
2311 CGM.AddUsedGlobal(GV);
2312 }
2313 else
2314 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002315 DefinedClasses.push_back(GV);
2316}
2317
2318llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2319 llvm::Constant *Protocols,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002320 const ConstantVector &Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002321 unsigned Flags = eClassFlags_Meta;
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002322 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002323
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00002324 if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002325 Flags |= eClassFlags_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002326
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002327 std::vector<llvm::Constant*> Values(12);
2328 // The isa for the metaclass is the root of the hierarchy.
2329 const ObjCInterfaceDecl *Root = ID->getClassInterface();
2330 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2331 Root = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002332 Values[ 0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002333 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002334 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002335 // The super class for the metaclass is emitted as the name of the
2336 // super class. The runtime fixes this up to point to the
2337 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002338 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002339 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002340 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002341 ObjCTypes.ClassPtrTy);
2342 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002343 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002344 }
2345 Values[ 2] = GetClassName(ID->getIdentifier());
2346 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002347 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2348 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2349 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002350 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002351 Values[ 7] =
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002352 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002353 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002354 Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002355 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002356 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002357 Values[ 9] = Protocols;
2358 // ivar_layout for metaclass is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002359 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002360 // The class extension is always unused for metaclasses.
Owen Anderson0b75f232009-07-31 20:28:54 +00002361 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002362 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002363 Values);
2364
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002365 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner86d7d912008-11-24 03:54:41 +00002366 Name += ID->getNameAsCString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002367
2368 // Check for a forward reference.
2369 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2370 if (GV) {
2371 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2372 "Forward metaclass reference has incorrect type.");
2373 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2374 GV->setInitializer(Init);
2375 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00002376 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002377 llvm::GlobalValue::InternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002378 Init, Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002379 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002380 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbarae333842009-03-09 22:18:41 +00002381 GV->setAlignment(4);
Chris Lattnerf56501c2009-07-17 23:57:13 +00002382 CGM.AddUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002383
2384 return GV;
2385}
2386
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002387llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002388 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002389
Mike Stump18bb9282009-05-16 07:57:57 +00002390 // FIXME: Should we look these up somewhere other than the module. Its a bit
2391 // silly since we only generate these while processing an implementation, so
2392 // exactly one pointer would work if know when we entered/exitted an
2393 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002394
2395 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00002396 // Previously, metaclass with internal linkage may have been defined.
2397 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002398 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2399 true)) {
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002400 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2401 "Forward metaclass reference has incorrect type.");
2402 return GV;
2403 } else {
2404 // Generate as an external reference to keep a consistent
2405 // module. This will be patched up when we emit the metaclass.
Owen Andersonc10c8d32009-07-08 19:05:04 +00002406 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002407 llvm::GlobalValue::ExternalLinkage,
2408 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002409 Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002410 }
2411}
2412
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00002413llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2414 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2415
2416 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2417 true)) {
2418 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2419 "Forward class metadata reference has incorrect type.");
2420 return GV;
2421 } else {
2422 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2423 llvm::GlobalValue::ExternalLinkage,
2424 0,
2425 Name);
2426 }
2427}
2428
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002429/*
2430 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002431 uint32_t size;
2432 const char *weak_ivar_layout;
2433 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002434 };
2435*/
2436llvm::Constant *
2437CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002438 uint64_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002439 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002440
2441 std::vector<llvm::Constant*> Values(3);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002442 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian6df69862009-04-22 23:00:43 +00002443 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002444 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002445 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002446
2447 // Return null if no extension bits are used.
2448 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002449 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002450
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002451 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002452 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002453 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002454 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002455 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002456}
2457
2458/*
2459 struct objc_ivar {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002460 char *ivar_name;
2461 char *ivar_type;
2462 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002463 };
2464
2465 struct objc_ivar_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002466 int ivar_count;
2467 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002468 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002469*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002470llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002471 bool ForClass) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002472 std::vector<llvm::Constant*> Ivars, Ivar(3);
2473
2474 // When emitting the root class GCC emits ivar entries for the
2475 // actual class structure. It is not clear if we need to follow this
2476 // behavior; for now lets try and get away with not doing it. If so,
2477 // the cleanest solution would be to make up an ObjCInterfaceDecl
2478 // for the class.
2479 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00002480 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002481
2482 ObjCInterfaceDecl *OID =
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002483 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002484
Daniel Dunbarf5c18462009-04-20 06:54:31 +00002485 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian7c809592009-06-04 01:19:09 +00002486 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002487
Daniel Dunbarf5c18462009-04-20 06:54:31 +00002488 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2489 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian7c809592009-06-04 01:19:09 +00002490 // Ignore unnamed bit-fields.
2491 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002492 continue;
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00002493 Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2494 Ivar[1] = GetMethodVarType(IVD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002495 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00002496 ComputeIvarBaseOffset(CGM, OID, IVD));
Owen Anderson0e0189d2009-07-27 22:29:56 +00002497 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002498 }
2499
2500 // Return null for empty list.
2501 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002502 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002503
2504 std::vector<llvm::Constant*> Values(2);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002505 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002506 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002507 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002508 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002509 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002510
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002511 llvm::GlobalVariable *GV;
2512 if (ForClass)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002513 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002514 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002515 4, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002516 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002517 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002518 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002519 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002520 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002521}
2522
2523/*
2524 struct objc_method {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002525 SEL method_name;
2526 char *method_types;
2527 void *method;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002528 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002529
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002530 struct objc_method_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002531 struct objc_method_list *obsolete;
2532 int count;
2533 struct objc_method methods_list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002534 };
2535*/
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002536
2537/// GetMethodConstant - Return a struct objc_method constant for the
2538/// given method if it has been defined. The result is null if the
2539/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002540llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002541 // FIXME: Use DenseMap::lookup
2542 llvm::Function *Fn = MethodDefinitions[MD];
2543 if (!Fn)
2544 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002545
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002546 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002547 Method[0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002548 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002549 ObjCTypes.SelectorPtrTy);
2550 Method[1] = GetMethodVarType(MD);
Owen Andersonade90fd2009-07-29 18:54:39 +00002551 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002552 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002553}
2554
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002555llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002556 const char *Section,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002557 const ConstantVector &Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002558 // Return null for empty list.
2559 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002560 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002561
2562 std::vector<llvm::Constant*> Values(3);
Owen Anderson0b75f232009-07-31 20:28:54 +00002563 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002564 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002565 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002566 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002567 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002568 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002569
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002570 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002571 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002572 ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002573}
2574
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00002575llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002576 const ObjCContainerDecl *CD) {
Daniel Dunbard2386812009-10-19 01:21:19 +00002577 llvm::SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00002578 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002579
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002580 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00002581 const llvm::FunctionType *MethodTy =
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002582 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002583 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00002584 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002585 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00002586 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002587 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002588 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002589
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002590 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002591}
2592
Daniel Dunbar30c65362009-03-09 20:09:19 +00002593llvm::GlobalVariable *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002594CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00002595 llvm::Constant *Init,
2596 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002597 unsigned Align,
2598 bool AddToUsed) {
Daniel Dunbar30c65362009-03-09 20:09:19 +00002599 const llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002600 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002601 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerf56501c2009-07-17 23:57:13 +00002602 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbar30c65362009-03-09 20:09:19 +00002603 if (Section)
2604 GV->setSection(Section);
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002605 if (Align)
2606 GV->setAlignment(Align);
2607 if (AddToUsed)
Chris Lattnerf56501c2009-07-17 23:57:13 +00002608 CGM.AddUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00002609 return GV;
2610}
2611
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002612llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00002613 // Abuse this interface function as a place to finalize.
2614 FinishModule();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002615 return NULL;
2616}
2617
Chris Lattnerd4808922009-03-22 21:03:39 +00002618llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002619 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00002620}
2621
Chris Lattnerd4808922009-03-22 21:03:39 +00002622llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002623 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00002624}
2625
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00002626llvm::Constant *CGObjCMac::GetCopyStructFunction() {
2627 return ObjCTypes.getCopyStructFn();
2628}
2629
Chris Lattnerd4808922009-03-22 21:03:39 +00002630llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002631 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00002632}
2633
John McCallbd309292010-07-06 01:34:17 +00002634void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
2635 return EmitTryOrSynchronizedStmt(CGF, S);
2636}
2637
2638void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
2639 const ObjCAtSynchronizedStmt &S) {
2640 return EmitTryOrSynchronizedStmt(CGF, S);
2641}
2642
John McCall65bea082010-07-21 06:59:36 +00002643namespace {
John McCallcda666c2010-07-21 07:22:38 +00002644 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00002645 const Stmt &S;
John McCall2dd7d442010-08-04 05:59:32 +00002646 llvm::Value *SyncArgSlot;
John McCall65bea082010-07-21 06:59:36 +00002647 llvm::Value *CallTryExitVar;
2648 llvm::Value *ExceptionData;
2649 ObjCTypesHelper &ObjCTypes;
2650 PerformFragileFinally(const Stmt *S,
John McCall2dd7d442010-08-04 05:59:32 +00002651 llvm::Value *SyncArgSlot,
John McCall65bea082010-07-21 06:59:36 +00002652 llvm::Value *CallTryExitVar,
2653 llvm::Value *ExceptionData,
2654 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00002655 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00002656 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
2657
2658 void Emit(CodeGenFunction &CGF, bool IsForEH) {
2659 // Check whether we need to call objc_exception_try_exit.
2660 // In optimized code, this branch will always be folded.
2661 llvm::BasicBlock *FinallyCallExit =
2662 CGF.createBasicBlock("finally.call_exit");
2663 llvm::BasicBlock *FinallyNoCallExit =
2664 CGF.createBasicBlock("finally.no_call_exit");
2665 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
2666 FinallyCallExit, FinallyNoCallExit);
2667
2668 CGF.EmitBlock(FinallyCallExit);
2669 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
2670 ->setDoesNotThrow();
2671
2672 CGF.EmitBlock(FinallyNoCallExit);
2673
2674 if (isa<ObjCAtTryStmt>(S)) {
2675 if (const ObjCAtFinallyStmt* FinallyStmt =
2676 cast<ObjCAtTryStmt>(S).getFinallyStmt())
2677 CGF.EmitStmt(FinallyStmt->getFinallyBody());
2678
2679 // Currently, the end of the cleanup must always exist.
2680 CGF.EnsureInsertPoint();
2681 } else {
2682 // Emit objc_sync_exit(expr); as finally's sole statement for
2683 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00002684 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall65bea082010-07-21 06:59:36 +00002685 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2686 ->setDoesNotThrow();
2687 }
2688 }
2689 };
John McCall42227ed2010-07-31 23:20:56 +00002690
2691 class FragileHazards {
2692 CodeGenFunction &CGF;
2693 llvm::SmallVector<llvm::Value*, 20> Locals;
2694 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
2695
2696 llvm::InlineAsm *ReadHazard;
2697 llvm::InlineAsm *WriteHazard;
2698
2699 llvm::FunctionType *GetAsmFnType();
2700
2701 void collectLocals();
2702 void emitReadHazard(CGBuilderTy &Builder);
2703
2704 public:
2705 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00002706
John McCall42227ed2010-07-31 23:20:56 +00002707 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00002708 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00002709 };
2710}
2711
2712/// Create the fragile-ABI read and write hazards based on the current
2713/// state of the function, which is presumed to be immediately prior
2714/// to a @try block. These hazards are used to maintain correct
2715/// semantics in the face of optimization and the fragile ABI's
2716/// cavalier use of setjmp/longjmp.
2717FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
2718 collectLocals();
2719
2720 if (Locals.empty()) return;
2721
2722 // Collect all the blocks in the function.
2723 for (llvm::Function::iterator
2724 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
2725 BlocksBeforeTry.insert(&*I);
2726
2727 llvm::FunctionType *AsmFnTy = GetAsmFnType();
2728
2729 // Create a read hazard for the allocas. This inhibits dead-store
2730 // optimizations and forces the values to memory. This hazard is
2731 // inserted before any 'throwing' calls in the protected scope to
2732 // reflect the possibility that the variables might be read from the
2733 // catch block if the call throws.
2734 {
2735 std::string Constraint;
2736 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2737 if (I) Constraint += ',';
2738 Constraint += "*m";
2739 }
2740
2741 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2742 }
2743
2744 // Create a write hazard for the allocas. This inhibits folding
2745 // loads across the hazard. This hazard is inserted at the
2746 // beginning of the catch path to reflect the possibility that the
2747 // variables might have been written within the protected scope.
2748 {
2749 std::string Constraint;
2750 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2751 if (I) Constraint += ',';
2752 Constraint += "=*m";
2753 }
2754
2755 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2756 }
2757}
2758
2759/// Emit a write hazard at the current location.
2760void FragileHazards::emitWriteHazard() {
2761 if (Locals.empty()) return;
2762
2763 CGF.Builder.CreateCall(WriteHazard, Locals.begin(), Locals.end())
2764 ->setDoesNotThrow();
2765}
2766
John McCall42227ed2010-07-31 23:20:56 +00002767void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
2768 assert(!Locals.empty());
2769 Builder.CreateCall(ReadHazard, Locals.begin(), Locals.end())
2770 ->setDoesNotThrow();
2771}
2772
2773/// Emit read hazards in all the protected blocks, i.e. all the blocks
2774/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00002775void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00002776 if (Locals.empty()) return;
2777
2778 CGBuilderTy Builder(CGF.getLLVMContext());
2779
2780 // Iterate through all blocks, skipping those prior to the try.
2781 for (llvm::Function::iterator
2782 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
2783 llvm::BasicBlock &BB = *FI;
2784 if (BlocksBeforeTry.count(&BB)) continue;
2785
2786 // Walk through all the calls in the block.
2787 for (llvm::BasicBlock::iterator
2788 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
2789 llvm::Instruction &I = *BI;
2790
2791 // Ignore instructions that aren't non-intrinsic calls.
2792 // These are the only calls that can possibly call longjmp.
2793 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
2794 if (isa<llvm::IntrinsicInst>(I))
2795 continue;
2796
2797 // Ignore call sites marked nounwind. This may be questionable,
2798 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
2799 llvm::CallSite CS(&I);
2800 if (CS.doesNotThrow()) continue;
2801
John McCall2dd7d442010-08-04 05:59:32 +00002802 // Insert a read hazard before the call. This will ensure that
2803 // any writes to the locals are performed before making the
2804 // call. If the call throws, then this is sufficient to
2805 // guarantee correctness as long as it doesn't also write to any
2806 // locals.
John McCall42227ed2010-07-31 23:20:56 +00002807 Builder.SetInsertPoint(&BB, BI);
2808 emitReadHazard(Builder);
2809 }
2810 }
2811}
2812
2813static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
2814 if (V) S.insert(V);
2815}
2816
2817void FragileHazards::collectLocals() {
2818 // Compute a set of allocas to ignore.
2819 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
2820 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
2821 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
2822 addIfPresent(AllocasToIgnore, CGF.EHCleanupDest);
2823
2824 // Collect all the allocas currently in the function. This is
2825 // probably way too aggressive.
2826 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
2827 for (llvm::BasicBlock::iterator
2828 I = Entry.begin(), E = Entry.end(); I != E; ++I)
2829 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
2830 Locals.push_back(&*I);
2831}
2832
2833llvm::FunctionType *FragileHazards::GetAsmFnType() {
2834 std::vector<const llvm::Type *> Tys(Locals.size());
2835 for (unsigned I = 0, E = Locals.size(); I != E; ++I)
2836 Tys[I] = Locals[I]->getType();
2837 return llvm::FunctionType::get(CGF.Builder.getVoidTy(), Tys, false);
John McCall65bea082010-07-21 06:59:36 +00002838}
2839
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002840/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002841
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002842 Objective-C setjmp-longjmp (sjlj) Exception Handling
2843 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002844
John McCallbd309292010-07-06 01:34:17 +00002845 A catch buffer is a setjmp buffer plus:
2846 - a pointer to the exception that was caught
2847 - a pointer to the previous exception data buffer
2848 - two pointers of reserved storage
2849 Therefore catch buffers form a stack, with a pointer to the top
2850 of the stack kept in thread-local storage.
2851
2852 objc_exception_try_enter pushes a catch buffer onto the EH stack.
2853 objc_exception_try_exit pops the given catch buffer, which is
2854 required to be the top of the EH stack.
2855 objc_exception_throw pops the top of the EH stack, writes the
2856 thrown exception into the appropriate field, and longjmps
2857 to the setjmp buffer. It crashes the process (with a printf
2858 and an abort()) if there are no catch buffers on the stack.
2859 objc_exception_extract just reads the exception pointer out of the
2860 catch buffer.
2861
2862 There's no reason an implementation couldn't use a light-weight
2863 setjmp here --- something like __builtin_setjmp, but API-compatible
2864 with the heavyweight setjmp. This will be more important if we ever
2865 want to implement correct ObjC/C++ exception interactions for the
2866 fragile ABI.
2867
2868 Note that for this use of setjmp/longjmp to be correct, we may need
2869 to mark some local variables volatile: if a non-volatile local
2870 variable is modified between the setjmp and the longjmp, it has
2871 indeterminate value. For the purposes of LLVM IR, it may be
2872 sufficient to make loads and stores within the @try (to variables
2873 declared outside the @try) volatile. This is necessary for
2874 optimized correctness, but is not currently being done; this is
2875 being tracked as rdar://problem/8160285
2876
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002877 The basic framework for a @try-catch-finally is as follows:
2878 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002879 objc_exception_data d;
2880 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00002881 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002882
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002883 objc_exception_try_enter(&d);
2884 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002885 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002886 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002887 // exception path
2888 id _caught = objc_exception_extract(&d);
2889
2890 // enter new try scope for handlers
2891 if (!setjmp(d.jmp_buf)) {
2892 ... match exception and execute catch blocks ...
2893
2894 // fell off end, rethrow.
2895 _rethrow = _caught;
2896 ... jump-through-finally to finally_rethrow ...
2897 } else {
2898 // exception in catch block
2899 _rethrow = objc_exception_extract(&d);
2900 _call_try_exit = false;
2901 ... jump-through-finally to finally_rethrow ...
2902 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002903 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002904 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002905
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002906 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00002907 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002908 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00002909
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002910 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002911 ... dispatch to finally destination ...
2912
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002913 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002914 objc_exception_throw(_rethrow);
2915
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002916 finally_end:
2917 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002918
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002919 This framework differs slightly from the one gcc uses, in that gcc
2920 uses _rethrow to determine if objc_exception_try_exit should be called
2921 and if the object should be rethrown. This breaks in the face of
2922 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002923
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002924 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002925
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002926 - If there are no catch blocks, then we avoid emitting the second
2927 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002928
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002929 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2930 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002931
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002932 - FIXME: If there is no @finally block we can do a few more
2933 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002934
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002935 Rethrows and Jumps-Through-Finally
2936 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002937
John McCallbd309292010-07-06 01:34:17 +00002938 '@throw;' is supported by pushing the currently-caught exception
2939 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002940
John McCallbd309292010-07-06 01:34:17 +00002941 Branches through the @finally block are handled with an ordinary
2942 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
2943 exceptions are not compatible with C++ exceptions, and this is
2944 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002945
John McCallbd309292010-07-06 01:34:17 +00002946 @synchronized(expr) { stmt; } is emitted as if it were:
2947 id synch_value = expr;
2948 objc_sync_enter(synch_value);
2949 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002950*/
2951
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00002952void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2953 const Stmt &S) {
2954 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00002955
2956 // A destination for the fall-through edges of the catch handlers to
2957 // jump to.
2958 CodeGenFunction::JumpDest FinallyEnd =
2959 CGF.getJumpDestInCurrentScope("finally.end");
2960
2961 // A destination for the rethrow edge of the catch handlers to jump
2962 // to.
2963 CodeGenFunction::JumpDest FinallyRethrow =
2964 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002965
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002966 // For @synchronized, call objc_sync_enter(sync.expr). The
2967 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00002968 // @synchronized. We can't avoid a temp here because we need the
2969 // value to be preserved. If the backend ever does liveness
2970 // correctly after setjmp, this will be unnecessary.
2971 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002972 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00002973 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002974 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2975 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallbd309292010-07-06 01:34:17 +00002976 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
2977 ->setDoesNotThrow();
John McCall2dd7d442010-08-04 05:59:32 +00002978
2979 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
2980 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002981 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002982
John McCall2dd7d442010-08-04 05:59:32 +00002983 // Allocate memory for the setjmp buffer. This needs to be kept
2984 // live throughout the try and catch blocks.
2985 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2986 "exceptiondata.ptr");
2987
John McCall42227ed2010-07-31 23:20:56 +00002988 // Create the fragile hazards. Note that this will not capture any
2989 // of the allocas required for exception processing, but will
2990 // capture the current basic block (which extends all the way to the
2991 // setjmp call) as "before the @try".
2992 FragileHazards Hazards(CGF);
2993
John McCallbd309292010-07-06 01:34:17 +00002994 // Create a flag indicating whether the cleanup needs to call
2995 // objc_exception_try_exit. This is true except when
2996 // - no catches match and we're branching through the cleanup
2997 // just to rethrow the exception, or
2998 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00002999 // The setjmp-safety rule here is that we should always store to this
3000 // variable in a place that dominates the branch through the cleanup
3001 // without passing through any setjmps.
John McCallbd309292010-07-06 01:34:17 +00003002 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlssonda0e4562009-02-07 21:26:04 +00003003 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003004
John McCallbd309292010-07-06 01:34:17 +00003005 // Push a normal cleanup to leave the try scope.
John McCallcda666c2010-07-21 07:22:38 +00003006 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00003007 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00003008 CallTryExitVar,
3009 ExceptionData,
3010 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00003011
3012 // Enter a try block:
3013 // - Call objc_exception_try_enter to push ExceptionData on top of
3014 // the EH stack.
3015 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3016 ->setDoesNotThrow();
3017
3018 // - Call setjmp on the exception data buffer.
3019 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3020 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3021 llvm::Value *SetJmpBuffer =
3022 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, GEPIndexes+3, "setjmp_buffer");
3023 llvm::CallInst *SetJmpResult =
3024 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3025 SetJmpResult->setDoesNotThrow();
3026
3027 // If setjmp returned 0, enter the protected block; otherwise,
3028 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00003029 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3030 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00003031 llvm::Value *DidCatch =
3032 CGF.Builder.CreateIsNull(SetJmpResult, "did_catch_exception");
3033 CGF.Builder.CreateCondBr(DidCatch, TryBlock, TryHandler);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003034
John McCallbd309292010-07-06 01:34:17 +00003035 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003036 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00003037 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003038 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00003039 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00003040
3041 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003042
John McCallbd309292010-07-06 01:34:17 +00003043 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00003044 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003045
John McCall42227ed2010-07-31 23:20:56 +00003046 // Don't optimize loads of the in-scope locals across this point.
3047 Hazards.emitWriteHazard();
3048
John McCallbd309292010-07-06 01:34:17 +00003049 // For a @synchronized (or a @try with no catches), just branch
3050 // through the cleanup to the rethrow block.
3051 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3052 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00003053 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003054 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00003055
3056 // Otherwise, we have to match against the caught exceptions.
3057 } else {
John McCall2dd7d442010-08-04 05:59:32 +00003058 // Retrieve the exception object. We may emit multiple blocks but
3059 // nothing can cross this so the value is already in SSA form.
3060 llvm::CallInst *Caught =
3061 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3062 ExceptionData, "caught");
3063 Caught->setDoesNotThrow();
3064
John McCallbd309292010-07-06 01:34:17 +00003065 // Push the exception to rethrow onto the EH value stack for the
3066 // benefit of any @throws in the handlers.
3067 CGF.ObjCEHValueStack.push_back(Caught);
3068
Douglas Gregor96c79492010-04-23 22:50:49 +00003069 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003070
John McCall2dd7d442010-08-04 05:59:32 +00003071 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallbd309292010-07-06 01:34:17 +00003072
John McCall2dd7d442010-08-04 05:59:32 +00003073 llvm::BasicBlock *CatchBlock = 0;
3074 llvm::BasicBlock *CatchHandler = 0;
3075 if (HasFinally) {
3076 // Enter a new exception try block (in case a @catch block
3077 // throws an exception).
3078 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3079 ->setDoesNotThrow();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003080
John McCall2dd7d442010-08-04 05:59:32 +00003081 llvm::CallInst *SetJmpResult =
3082 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3083 "setjmp.result");
3084 SetJmpResult->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003085
John McCall2dd7d442010-08-04 05:59:32 +00003086 llvm::Value *Threw =
3087 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3088
3089 CatchBlock = CGF.createBasicBlock("catch");
3090 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3091 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3092
3093 CGF.EmitBlock(CatchBlock);
3094 }
3095
3096 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003097
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003098 // Handle catch list. As a special case we check if everything is
3099 // matched and avoid generating code for falling off the end if
3100 // so.
3101 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00003102 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3103 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003104
Douglas Gregor46a572b2010-04-26 16:46:50 +00003105 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff7cae42b2009-07-10 23:34:53 +00003106 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar523208f2008-09-27 07:36:24 +00003107
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003108 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003109 if (!CatchParam) {
3110 AllMatched = true;
3111 } else {
John McCall9dd450b2009-09-21 23:43:11 +00003112 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003113
John McCallbd309292010-07-06 01:34:17 +00003114 // catch(id e) always matches under this ABI, since only
3115 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00003116 // FIXME: For the time being we also match id<X>; this should
3117 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00003118 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003119 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003120 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003121
John McCallbd309292010-07-06 01:34:17 +00003122 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003123 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00003124 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3125
Anders Carlsson9396a892008-09-11 09:15:33 +00003126 if (CatchParam) {
Steve Naroff371b8fb2009-03-03 19:52:17 +00003127 CGF.EmitLocalBlockVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003128 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00003129
3130 // These types work out because ConvertType(id) == i8*.
Steve Naroff371b8fb2009-03-03 19:52:17 +00003131 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson9396a892008-09-11 09:15:33 +00003132 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003133
Anders Carlsson9396a892008-09-11 09:15:33 +00003134 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003135
3136 // The scope of the catch variable ends right here.
3137 CatchVarCleanups.ForceCleanup();
3138
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003139 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003140 break;
3141 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003142
Steve Naroff7cae42b2009-07-10 23:34:53 +00003143 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00003144 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00003145
3146 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00003147 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3148 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003149
3150 // Check if the @catch block matches the exception object.
John McCall96fa4842010-05-17 21:00:27 +00003151 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003152
John McCallbd309292010-07-06 01:34:17 +00003153 llvm::CallInst *Match =
Chris Lattnerc6406db2009-04-22 02:26:14 +00003154 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3155 Class, Caught, "match");
John McCallbd309292010-07-06 01:34:17 +00003156 Match->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003157
John McCallbd309292010-07-06 01:34:17 +00003158 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3159 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003160
3161 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00003162 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003163
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003164 // Emit the @catch block.
3165 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00003166
3167 // Collect any cleanups for the catch variable. The scope lasts until
3168 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00003169 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00003170
Steve Naroff371b8fb2009-03-03 19:52:17 +00003171 CGF.EmitLocalBlockVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003172 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003173
John McCallbd309292010-07-06 01:34:17 +00003174 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003175 llvm::Value *Tmp =
3176 CGF.Builder.CreateBitCast(Caught,
3177 CGF.ConvertType(CatchParam->getType()),
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003178 "tmp");
Steve Naroff371b8fb2009-03-03 19:52:17 +00003179 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003180
Anders Carlsson9396a892008-09-11 09:15:33 +00003181 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003182
3183 // We're done with the catch variable.
3184 CatchVarCleanups.ForceCleanup();
3185
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003186 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003187
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003188 CGF.EmitBlock(NextCatchBlock);
3189 }
3190
John McCallbd309292010-07-06 01:34:17 +00003191 CGF.ObjCEHValueStack.pop_back();
3192
John McCall2dd7d442010-08-04 05:59:32 +00003193 // If nothing wanted anything to do with the caught exception,
3194 // kill the extract call.
3195 if (Caught->use_empty())
3196 Caught->eraseFromParent();
3197
3198 if (!AllMatched)
3199 CGF.EmitBranchThroughCleanup(FinallyRethrow);
3200
3201 if (HasFinally) {
3202 // Emit the exception handler for the @catch blocks.
3203 CGF.EmitBlock(CatchHandler);
3204
3205 // In theory we might now need a write hazard, but actually it's
3206 // unnecessary because there's no local-accessing code between
3207 // the try's write hazard and here.
3208 //Hazards.emitWriteHazard();
3209
3210 // Don't pop the catch handler; the throw already did.
3211 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003212 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003213 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003214 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003215
John McCall42227ed2010-07-31 23:20:56 +00003216 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00003217 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003218
John McCallbd309292010-07-06 01:34:17 +00003219 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00003220 CGF.Builder.restoreIP(TryFallthroughIP);
3221 if (CGF.HaveInsertPoint())
3222 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00003223 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00003224 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003225
John McCallbd309292010-07-06 01:34:17 +00003226 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00003227 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00003228 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00003229 if (CGF.HaveInsertPoint()) {
John McCall2dd7d442010-08-04 05:59:32 +00003230 // Just look in the buffer for the exception to throw.
3231 llvm::CallInst *Caught =
3232 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3233 ExceptionData);
3234 Caught->setDoesNotThrow();
3235
3236 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), Caught)
John McCallbd309292010-07-06 01:34:17 +00003237 ->setDoesNotThrow();
3238 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00003239 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003240
John McCall42227ed2010-07-31 23:20:56 +00003241 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003242}
3243
3244void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003245 const ObjCAtThrowStmt &S) {
Anders Carlssone005aa12008-09-09 16:16:55 +00003246 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003247
Anders Carlssone005aa12008-09-09 16:16:55 +00003248 if (const Expr *ThrowExpr = S.getThrowExpr()) {
3249 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003250 ExceptionAsObject =
Anders Carlssone005aa12008-09-09 16:16:55 +00003251 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
3252 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003253 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003254 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00003255 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00003256 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003257
John McCallbd309292010-07-06 01:34:17 +00003258 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3259 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003260 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003261
3262 // Clear the insertion point to indicate we are in unreachable code.
3263 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003264}
3265
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003266/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003267/// object: objc_read_weak (id *src)
3268///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003269llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003270 llvm::Value *AddrWeakObj) {
Eli Friedmana374b682009-03-07 03:57:15 +00003271 const llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003272 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3273 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3274 ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00003275 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003276 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00003277 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003278 return read_weak;
3279}
3280
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003281/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
3282/// objc_assign_weak (id src, id *dst)
3283///
3284void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003285 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003286 const llvm::Type * SrcTy = src->getType();
3287 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003288 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003289 assert(Size <= 8 && "does not support size > 8");
3290 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003291 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003292 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3293 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003294 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3295 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00003296 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003297 src, dst, "weakassign");
3298 return;
3299}
3300
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003301/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
3302/// objc_assign_global (id src, id *dst)
3303///
3304void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00003305 llvm::Value *src, llvm::Value *dst,
3306 bool threadlocal) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003307 const llvm::Type * SrcTy = src->getType();
3308 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003309 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003310 assert(Size <= 8 && "does not support size > 8");
3311 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003312 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003313 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3314 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003315 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3316 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00003317 if (!threadlocal)
3318 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
3319 src, dst, "globalassign");
3320 else
3321 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
3322 src, dst, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003323 return;
3324}
3325
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003326/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003327/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003328///
3329void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003330 llvm::Value *src, llvm::Value *dst,
3331 llvm::Value *ivarOffset) {
3332 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003333 const llvm::Type * SrcTy = src->getType();
3334 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003335 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003336 assert(Size <= 8 && "does not support size > 8");
3337 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003338 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003339 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3340 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003341 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3342 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003343 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3344 src, dst, ivarOffset);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003345 return;
3346}
3347
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003348/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
3349/// objc_assign_strongCast (id src, id *dst)
3350///
3351void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003352 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003353 const llvm::Type * SrcTy = src->getType();
3354 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003355 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003356 assert(Size <= 8 && "does not support size > 8");
3357 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003358 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003359 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3360 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003361 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3362 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00003363 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003364 src, dst, "weakassign");
3365 return;
3366}
3367
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003368void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003369 llvm::Value *DestPtr,
3370 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003371 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003372 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3373 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003374 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003375 DestPtr, SrcPtr, size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003376 return;
3377}
3378
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003379/// EmitObjCValueForIvar - Code Gen for ivar reference.
3380///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003381LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3382 QualType ObjectTy,
3383 llvm::Value *BaseValue,
3384 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003385 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00003386 const ObjCInterfaceDecl *ID =
3387 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003388 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3389 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003390}
3391
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003392llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00003393 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003394 const ObjCIvarDecl *Ivar) {
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003395 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003396 return llvm::ConstantInt::get(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003397 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3398 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003399}
3400
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003401/* *** Private Interface *** */
3402
3403/// EmitImageInfo - Emit the image info marker used to encode some module
3404/// level information.
3405///
3406/// See: <rdr://4810609&4810587&4810587>
3407/// struct IMAGE_INFO {
3408/// unsigned version;
3409/// unsigned flags;
3410/// };
3411enum ImageInfoFlags {
Daniel Dunbar5e639272010-04-25 20:39:01 +00003412 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003413 eImageInfo_GarbageCollected = (1 << 1),
3414 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003415 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3416
Daniel Dunbar5e639272010-04-25 20:39:01 +00003417 // A flag indicating that the module has no instances of a @synthesize of a
3418 // superclass variable. <rdar://problem/6803242>
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003419 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003420};
3421
Daniel Dunbar5e639272010-04-25 20:39:01 +00003422void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003423 unsigned version = 0; // Version is unused?
3424 unsigned flags = 0;
3425
3426 // FIXME: Fix and continue?
3427 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
3428 flags |= eImageInfo_GarbageCollected;
3429 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
3430 flags |= eImageInfo_GCOnly;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003431
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003432 // We never allow @synthesize of a superclass property.
3433 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003434
Chris Lattner5e016ae2010-06-27 07:15:29 +00003435 const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
3436
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003437 // Emitted as int[2];
3438 llvm::Constant *values[2] = {
Chris Lattner5e016ae2010-06-27 07:15:29 +00003439 llvm::ConstantInt::get(Int32Ty, version),
3440 llvm::ConstantInt::get(Int32Ty, flags)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003441 };
Chris Lattner5e016ae2010-06-27 07:15:29 +00003442 llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003443
3444 const char *Section;
3445 if (ObjCABI == 1)
3446 Section = "__OBJC, __image_info,regular";
3447 else
3448 Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003449 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003450 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
Owen Anderson47034e12009-07-28 18:33:04 +00003451 llvm::ConstantArray::get(AT, values, 2),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003452 Section,
3453 0,
3454 true);
3455 GV->setConstant(true);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003456}
3457
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003458
3459// struct objc_module {
3460// unsigned long version;
3461// unsigned long size;
3462// const char *name;
3463// Symtab symtab;
3464// };
3465
3466// FIXME: Get from somewhere
3467static const int ModuleVersion = 7;
3468
3469void CGObjCMac::EmitModuleInfo() {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003470 uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003471
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003472 std::vector<llvm::Constant*> Values(4);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003473 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
3474 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbar92992502008-08-15 22:20:32 +00003475 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbarb036db82008-08-13 03:21:16 +00003476 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003477 Values[3] = EmitModuleSymbols();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003478 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson0e0189d2009-07-27 22:29:56 +00003479 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003480 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003481 4, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003482}
3483
3484llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003485 unsigned NumClasses = DefinedClasses.size();
3486 unsigned NumCategories = DefinedCategories.size();
3487
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003488 // Return null if no symbols were defined.
3489 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00003490 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003491
3492 std::vector<llvm::Constant*> Values(5);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003493 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Anderson0b75f232009-07-31 20:28:54 +00003494 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003495 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3496 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003497
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003498 // The runtime expects exactly the list of defined classes followed
3499 // by the list of defined categories, in a single array.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003500 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003501 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00003502 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003503 ObjCTypes.Int8PtrTy);
3504 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003505 Symbols[NumClasses + i] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003506 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003507 ObjCTypes.Int8PtrTy);
3508
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003509 Values[4] =
Owen Anderson9793f0e2009-07-29 22:16:19 +00003510 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003511 NumClasses + NumCategories),
3512 Symbols);
3513
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00003514 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003515
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003516 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003517 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3518 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003519 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003520 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003521}
3522
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003523llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003524 const ObjCInterfaceDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003525 LazySymbols.insert(ID->getIdentifier());
3526
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003527 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003528
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003529 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003530 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00003531 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003532 ObjCTypes.ClassPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003533 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003534 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3535 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003536 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003537 }
3538
Daniel Dunbarc76493a2009-11-29 21:23:36 +00003539 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003540}
3541
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00003542llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3543 bool lvalue) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003544 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003545
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003546 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003547 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00003548 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003549 ObjCTypes.SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003550 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003551 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3552 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003553 4, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003554 }
3555
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00003556 if (lvalue)
3557 return Entry;
Daniel Dunbarc76493a2009-11-29 21:23:36 +00003558 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003559}
3560
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00003561llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003562 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003563
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003564 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003565 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003566 llvm::ConstantArray::get(VMContext,
3567 Ident->getNameStart()),
Daniel Dunbarcda43072010-07-29 22:57:21 +00003568 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003569 1, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003570
Owen Anderson170229f2009-07-14 23:10:40 +00003571 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003572}
3573
Fariborz Jahanian01dff422009-03-05 19:17:31 +00003574/// GetIvarLayoutName - Returns a unique constant for the given
3575/// ivar layout bitmap.
3576llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003577 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003578 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00003579}
3580
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003581void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003582 unsigned int BytePos,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003583 bool ForStrongLayout,
3584 bool &HasUnion) {
3585 const RecordDecl *RD = RT->getDecl();
3586 // FIXME - Use iterator.
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003587 llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003588 const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003589 const llvm::StructLayout *RecLayout =
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003590 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003591
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003592 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3593 ForStrongLayout, HasUnion);
3594}
3595
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +00003596void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003597 const llvm::StructLayout *Layout,
3598 const RecordDecl *RD,
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003599 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003600 unsigned int BytePos, bool ForStrongLayout,
3601 bool &HasUnion) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003602 bool IsUnion = (RD && RD->isUnion());
3603 uint64_t MaxUnionIvarSize = 0;
3604 uint64_t MaxSkippedUnionIvarSize = 0;
3605 FieldDecl *MaxField = 0;
3606 FieldDecl *MaxSkippedField = 0;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003607 FieldDecl *LastFieldBitfield = 0;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003608 uint64_t MaxFieldOffset = 0;
3609 uint64_t MaxSkippedFieldOffset = 0;
3610 uint64_t LastBitfieldOffset = 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003611
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003612 if (RecFields.empty())
3613 return;
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003614 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3615 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3616
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003617 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003618 FieldDecl *Field = RecFields[i];
Daniel Dunbar62b10702009-05-03 23:35:23 +00003619 uint64_t FieldOffset;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00003620 if (RD) {
Daniel Dunbard51c1a62010-04-14 17:02:21 +00003621 // Note that 'i' here is actually the field index inside RD of Field,
3622 // although this dependency is hidden.
3623 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
3624 FieldOffset = RL.getFieldOffset(i) / 8;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00003625 } else
Daniel Dunbar62b10702009-05-03 23:35:23 +00003626 FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003627
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003628 // Skip over unnamed or bitfields
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003629 if (!Field->getIdentifier() || Field->isBitField()) {
3630 LastFieldBitfield = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003631 LastBitfieldOffset = FieldOffset;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003632 continue;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003633 }
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003634
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003635 LastFieldBitfield = 0;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003636 QualType FQT = Field->getType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003637 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003638 if (FQT->isUnionType())
3639 HasUnion = true;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003640
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003641 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003642 BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003643 ForStrongLayout, HasUnion);
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003644 continue;
3645 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003646
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003647 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003648 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003649 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003650 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003651 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003652 FQT = CArray->getElementType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003653 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3654 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003655 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003656 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003657 FQT = CArray->getElementType();
3658 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003659
3660 assert(!FQT->isUnionType() &&
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003661 "layout for array of unions not supported");
3662 if (FQT->isRecordType()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003663 int OldIndex = IvarsInfo.size() - 1;
3664 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003665
Ted Kremenekc23c7e62009-07-29 21:53:49 +00003666 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003667 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003668 ForStrongLayout, HasUnion);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003669
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003670 // Replicate layout information for each array element. Note that
3671 // one element is already done.
3672 uint64_t ElIx = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003673 for (int FirstIndex = IvarsInfo.size() - 1,
3674 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003675 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003676 for (int i = OldIndex+1; i <= FirstIndex; ++i)
3677 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3678 IvarsInfo[i].ivar_size));
3679 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3680 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3681 SkipIvars[i].ivar_size));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003682 }
3683 continue;
3684 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003685 }
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003686 // At this point, we are done with Record/Union and array there of.
3687 // For other arrays we are down to its element type.
John McCall8ccfcb52009-09-24 19:53:00 +00003688 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003689
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003690 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall8ccfcb52009-09-24 19:53:00 +00003691 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3692 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00003693 if (IsUnion) {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003694 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00003695 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003696 MaxUnionIvarSize = UnionIvarSize;
3697 MaxField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003698 MaxFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003699 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00003700 } else {
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003701 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003702 FieldSize / WordSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003703 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003704 } else if ((ForStrongLayout &&
John McCall8ccfcb52009-09-24 19:53:00 +00003705 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3706 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00003707 if (IsUnion) {
Mike Stump18bb9282009-05-16 07:57:57 +00003708 // FIXME: Why the asymmetry? We divide by word size in bits on other
3709 // side.
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003710 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar22007d32009-05-03 13:32:01 +00003711 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003712 MaxSkippedUnionIvarSize = UnionIvarSize;
3713 MaxSkippedField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003714 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003715 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00003716 } else {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003717 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003718 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003719 FieldSize / ByteSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003720 }
3721 }
3722 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003723
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003724 if (LastFieldBitfield) {
3725 // Last field was a bitfield. Must update skip info.
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003726 Expr *BitWidth = LastFieldBitfield->getBitWidth();
3727 uint64_t BitFieldSize =
Eli Friedman1c4a1752009-04-26 19:19:15 +00003728 BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
Daniel Dunbar22007d32009-05-03 13:32:01 +00003729 GC_IVAR skivar;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003730 skivar.ivar_bytepos = BytePos + LastBitfieldOffset;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003731 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3732 + ((BitFieldSize % ByteSizeInBits) != 0);
3733 SkipIvars.push_back(skivar);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003734 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003735
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003736 if (MaxField)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003737 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003738 MaxUnionIvarSize));
3739 if (MaxSkippedField)
Daniel Dunbar5b743912009-05-03 23:31:46 +00003740 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003741 MaxSkippedUnionIvarSize));
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00003742}
3743
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003744/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
3745/// the computations and returning the layout bitmap (for ivar or blocks) in
3746/// the given argument BitMap string container. Routine reads
3747/// two containers, IvarsInfo and SkipIvars which are assumed to be
3748/// filled already by the caller.
3749llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003750 unsigned int WordsToScan, WordsToSkip;
Benjamin Kramerabd5b902009-10-13 10:07:13 +00003751 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003752
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003753 // Build the string of skip/scan nibbles
Fariborz Jahaniance5676572009-04-24 17:15:27 +00003754 llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003755 unsigned int WordSize =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003756 CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003757 if (IvarsInfo[0].ivar_bytepos == 0) {
3758 WordsToSkip = 0;
3759 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003760 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003761 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3762 WordsToScan = IvarsInfo[0].ivar_size;
3763 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003764 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003765 unsigned int TailPrevGCObjC =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003766 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003767 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003768 // consecutive 'scanned' object pointers.
3769 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003770 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003771 // Skip over 'gc'able object pointer which lay over each other.
3772 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3773 continue;
3774 // Must skip over 1 or more words. We save current skip/scan values
3775 // and start a new pair.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003776 SKIP_SCAN SkScan;
3777 SkScan.skip = WordsToSkip;
3778 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003779 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003780
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003781 // Skip the hole.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003782 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3783 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003784 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003785 WordsToSkip = 0;
3786 WordsToScan = IvarsInfo[i].ivar_size;
3787 }
3788 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003789 if (WordsToScan > 0) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003790 SKIP_SCAN SkScan;
3791 SkScan.skip = WordsToSkip;
3792 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003793 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003794 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003795
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003796 if (!SkipIvars.empty()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003797 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003798 int LastByteSkipped =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003799 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003800 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003801 int LastByteScanned =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003802 IvarsInfo[LastIndex].ivar_bytepos +
3803 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003804 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramerd20ef752009-12-25 15:43:36 +00003805 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003806 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003807 SKIP_SCAN SkScan;
3808 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3809 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003810 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003811 }
3812 }
3813 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3814 // as 0xMN.
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003815 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003816 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003817 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3818 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3819 // 0xM0 followed by 0x0N detected.
3820 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3821 for (int j = i+1; j < SkipScan; j++)
3822 SkipScanIvars[j] = SkipScanIvars[j+1];
3823 --SkipScan;
3824 }
3825 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003826
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003827 // Generate the string.
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003828 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003829 unsigned char byte;
3830 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3831 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3832 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
3833 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003834
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003835 // first skip big.
3836 for (unsigned int ix = 0; ix < skip_big; ix++)
3837 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003838
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003839 // next (skip small, scan)
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003840 if (skip_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003841 byte = skip_small << 4;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003842 if (scan_big > 0) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003843 byte |= 0xf;
3844 --scan_big;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003845 } else if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003846 byte |= scan_small;
3847 scan_small = 0;
3848 }
3849 BitMap += byte;
3850 }
3851 // next scan big
3852 for (unsigned int ix = 0; ix < scan_big; ix++)
3853 BitMap += (unsigned char)(0x0f);
3854 // last scan small
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003855 if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003856 byte = scan_small;
3857 BitMap += byte;
3858 }
3859 }
3860 // null terminate string.
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003861 unsigned char zero = 0;
3862 BitMap += zero;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003863
3864 llvm::GlobalVariable * Entry =
3865 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3866 llvm::ConstantArray::get(VMContext, BitMap.c_str()),
3867 "__TEXT,__cstring,cstring_literals",
3868 1, true);
3869 return getConstantGEP(VMContext, Entry, 0, 0);
3870}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003871
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003872/// BuildIvarLayout - Builds ivar layout bitmap for the class
3873/// implementation for the __strong or __weak case.
3874/// The layout map displays which words in ivar list must be skipped
3875/// and which must be scanned by GC (see below). String is built of bytes.
3876/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
3877/// of words to skip and right nibble is count of words to scan. So, each
3878/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
3879/// represented by a 0x00 byte which also ends the string.
3880/// 1. when ForStrongLayout is true, following ivars are scanned:
3881/// - id, Class
3882/// - object *
3883/// - __strong anything
3884///
3885/// 2. When ForStrongLayout is false, following ivars are scanned:
3886/// - __weak anything
3887///
3888llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
3889 const ObjCImplementationDecl *OMD,
3890 bool ForStrongLayout) {
3891 bool hasUnion = false;
3892
3893 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3894 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
3895 return llvm::Constant::getNullValue(PtrTy);
3896
3897 llvm::SmallVector<FieldDecl*, 32> RecFields;
3898 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
3899 CGM.getContext().CollectObjCIvars(OI, RecFields);
3900
3901 // Add this implementations synthesized ivars.
3902 llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
3903 CGM.getContext().CollectNonClassIvars(OI, Ivars);
3904 for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
3905 RecFields.push_back(cast<FieldDecl>(Ivars[k]));
3906
3907 if (RecFields.empty())
3908 return llvm::Constant::getNullValue(PtrTy);
3909
3910 SkipIvars.clear();
3911 IvarsInfo.clear();
3912
3913 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
3914 if (IvarsInfo.empty())
3915 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003916 // Sort on byte position in case we encounterred a union nested in
3917 // the ivar list.
3918 if (hasUnion && !IvarsInfo.empty())
3919 std::sort(IvarsInfo.begin(), IvarsInfo.end());
3920 if (hasUnion && !SkipIvars.empty())
3921 std::sort(SkipIvars.begin(), SkipIvars.end());
3922
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003923 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003924 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003925
3926 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003927 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00003928 ForStrongLayout ? "strong" : "weak",
3929 OMD->getClassInterface()->getNameAsCString());
3930 const unsigned char *s = (unsigned char*)BitMap.c_str();
3931 for (unsigned i = 0; i < BitMap.size(); i++)
3932 if (!(s[i] & 0xf0))
3933 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3934 else
3935 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
3936 printf("\n");
3937 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003938 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00003939}
3940
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003941llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003942 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3943
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003944 // FIXME: Avoid std::string copying.
3945 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003946 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Owen Anderson41a75022009-08-13 21:57:51 +00003947 llvm::ConstantArray::get(VMContext, Sel.getAsString()),
Daniel Dunbarcda43072010-07-29 22:57:21 +00003948 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003949 1, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003950
Owen Anderson170229f2009-07-14 23:10:40 +00003951 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003952}
3953
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003954// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003955llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003956 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3957}
3958
3959// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003960llvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003961 return GetMethodVarName(&CGM.getContext().Idents.get(Name));
3962}
3963
Daniel Dunbarf5c18462009-04-20 06:54:31 +00003964llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003965 std::string TypeStr;
3966 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
3967
3968 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarb036db82008-08-13 03:21:16 +00003969
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003970 if (!Entry)
3971 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson41a75022009-08-13 21:57:51 +00003972 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbarcda43072010-07-29 22:57:21 +00003973 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003974 1, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003975
Owen Anderson170229f2009-07-14 23:10:40 +00003976 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003977}
3978
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003979llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003980 std::string TypeStr;
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003981 CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
3982 TypeStr);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003983
3984 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3985
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003986 if (!Entry)
3987 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson41a75022009-08-13 21:57:51 +00003988 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbarcda43072010-07-29 22:57:21 +00003989 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003990 1, true);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003991
Owen Anderson170229f2009-07-14 23:10:40 +00003992 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003993}
3994
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003995// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003996llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003997 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003998
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003999 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004000 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004001 llvm::ConstantArray::get(VMContext,
4002 Ident->getNameStart()),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004003 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004004 1, true);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004005
Owen Anderson170229f2009-07-14 23:10:40 +00004006 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004007}
4008
4009// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00004010// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004011llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004012CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4013 const Decl *Container) {
Daniel Dunbar4932b362008-08-28 04:38:10 +00004014 std::string TypeStr;
4015 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004016 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4017}
4018
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004019void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004020 const ObjCContainerDecl *CD,
Daniel Dunbard2386812009-10-19 01:21:19 +00004021 llvm::SmallVectorImpl<char> &Name) {
4022 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00004023 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00004024 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4025 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004026 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00004027 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramerb11416d2010-04-17 09:33:03 +00004028 OS << '(' << CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00004029 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004030}
4031
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004032void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004033 EmitModuleInfo();
4034
Daniel Dunbarc475d422008-10-29 22:36:39 +00004035 // Emit the dummy bodies for any protocols which were referenced but
4036 // never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004037 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerf56501c2009-07-17 23:57:13 +00004038 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4039 if (I->second->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00004040 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004041
Daniel Dunbarc475d422008-10-29 22:36:39 +00004042 std::vector<llvm::Constant*> Values(5);
Owen Anderson0b75f232009-07-31 20:28:54 +00004043 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004044 Values[1] = GetClassName(I->first);
Owen Anderson0b75f232009-07-31 20:28:54 +00004045 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004046 Values[3] = Values[4] =
Owen Anderson0b75f232009-07-31 20:28:54 +00004047 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004048 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004049 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarc475d422008-10-29 22:36:39 +00004050 Values));
Chris Lattnerf56501c2009-07-17 23:57:13 +00004051 CGM.AddUsedGlobal(I->second);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004052 }
4053
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004054 // Add assembler directives to add lazy undefined symbol references
4055 // for classes which are referenced but not defined. This is
4056 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00004057 //
4058 // FIXME: It would be nice if we had an LLVM construct for this.
4059 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
4060 llvm::SmallString<256> Asm;
4061 Asm += CGM.getModule().getModuleInlineAsm();
4062 if (!Asm.empty() && Asm.back() != '\n')
4063 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004064
Daniel Dunbard027a922009-09-07 00:20:42 +00004065 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbard027a922009-09-07 00:20:42 +00004066 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4067 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar07d07852009-10-18 21:17:35 +00004068 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4069 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnera299f2c2010-04-17 18:26:20 +00004070 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004071 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnera299f2c2010-04-17 18:26:20 +00004072 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004073 }
4074
4075 for (size_t i = 0; i < DefinedCategoryNames.size(); ++i) {
4076 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4077 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4078 }
Chris Lattnera299f2c2010-04-17 18:26:20 +00004079
Daniel Dunbard027a922009-09-07 00:20:42 +00004080 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004081 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004082}
4083
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004084CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004085 : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00004086 ObjCTypes(cgm) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004087 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004088 ObjCABI = 2;
4089}
4090
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004091/* *** */
4092
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004093ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004094 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004095 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4096 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004097
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004098 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004099 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004100 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004101 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Benjamin Kramerabd5b902009-10-13 10:07:13 +00004102 Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004103
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004104 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004105 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004106 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004107
Mike Stump18bb9282009-05-16 07:57:57 +00004108 // FIXME: It would be nice to unify this with the opaque type, so that the IR
4109 // comes out a bit cleaner.
Daniel Dunbarb036db82008-08-13 03:21:16 +00004110 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004111 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004112
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004113 // I'm not sure I like this. The implicit coordination is a bit
4114 // gross. We should solve this in a reasonable fashion because this
4115 // is a pretty common task (match some runtime data structure with
4116 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004117
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004118 // FIXME: This is leaked.
4119 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004120
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004121 // struct _objc_super {
4122 // id self;
4123 // Class cls;
4124 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00004125 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004126 Ctx.getTranslationUnitDecl(),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004127 SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004128 &Ctx.Idents.get("_objc_super"));
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004129 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004130 Ctx.getObjCIdType(), 0, 0, false));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004131 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004132 Ctx.getObjCClassType(), 0, 0, false));
Douglas Gregord5058122010-02-11 01:19:42 +00004133 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004134
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004135 SuperCTy = Ctx.getTagDeclType(RD);
4136 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004137
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004138 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004139 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4140
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004141 // struct _prop_t {
4142 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004143 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004144 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004145 PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004146 CGM.getModule().addTypeName("struct._prop_t",
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004147 PropertyTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004148
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004149 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004150 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004151 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004152 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004153 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004154 PropertyListTy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004155 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004156 llvm::ArrayType::get(PropertyTy, 0),
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004157 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004158 CGM.getModule().addTypeName("struct._prop_list_t",
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004159 PropertyListTy);
4160 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004161 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004162
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004163 // struct _objc_method {
4164 // SEL _cmd;
4165 // char *method_type;
4166 // char *_imp;
4167 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004168 MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004169 Int8PtrTy,
4170 Int8PtrTy,
4171 NULL);
4172 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004173
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004174 // struct _objc_cache *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004175 CacheTy = llvm::OpaqueType::get(VMContext);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004176 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004177 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004178}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004179
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004180ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004181 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004182 // struct _objc_method_description {
4183 // SEL name;
4184 // char *types;
4185 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004186 MethodDescriptionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004187 llvm::StructType::get(VMContext, SelectorPtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004188 Int8PtrTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00004189 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004190 CGM.getModule().addTypeName("struct._objc_method_description",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004191 MethodDescriptionTy);
4192
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004193 // struct _objc_method_description_list {
4194 // int count;
4195 // struct _objc_method_description[1];
4196 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004197 MethodDescriptionListTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004198 llvm::StructType::get(VMContext, IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004199 llvm::ArrayType::get(MethodDescriptionTy, 0),
Daniel Dunbarb036db82008-08-13 03:21:16 +00004200 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004201 CGM.getModule().addTypeName("struct._objc_method_description_list",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004202 MethodDescriptionListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004203
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004204 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004205 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004206 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004207
Daniel Dunbarb036db82008-08-13 03:21:16 +00004208 // Protocol description structures
4209
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004210 // struct _objc_protocol_extension {
4211 // uint32_t size; // sizeof(struct _objc_protocol_extension)
4212 // struct _objc_method_description_list *optional_instance_methods;
4213 // struct _objc_method_description_list *optional_class_methods;
4214 // struct _objc_property_list *instance_properties;
4215 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004216 ProtocolExtensionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004217 llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004218 MethodDescriptionListPtrTy,
4219 MethodDescriptionListPtrTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00004220 PropertyListPtrTy,
4221 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004222 CGM.getModule().addTypeName("struct._objc_protocol_extension",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004223 ProtocolExtensionTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004224
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004225 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004226 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004227
Daniel Dunbarc475d422008-10-29 22:36:39 +00004228 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00004229
Owen Andersonc36edfe2009-08-13 23:27:53 +00004230 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
4231 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004232
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004233 const llvm::Type *T =
Mike Stump11289f42009-09-09 15:08:12 +00004234 llvm::StructType::get(VMContext,
Owen Anderson758428f2009-08-05 23:18:46 +00004235 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004236 LongTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004237 llvm::ArrayType::get(ProtocolTyHolder, 0),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004238 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004239 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
4240
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004241 // struct _objc_protocol {
4242 // struct _objc_protocol_extension *isa;
4243 // char *protocol_name;
4244 // struct _objc_protocol **_objc_protocol_list;
4245 // struct _objc_method_description_list *instance_methods;
4246 // struct _objc_method_description_list *class_methods;
4247 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004248 T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004249 Int8PtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004250 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Daniel Dunbarb036db82008-08-13 03:21:16 +00004251 MethodDescriptionListPtrTy,
4252 MethodDescriptionListPtrTy,
4253 NULL);
4254 cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
4255
4256 ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004257 CGM.getModule().addTypeName("struct._objc_protocol_list",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004258 ProtocolListTy);
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004259 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004260 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004261
4262 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004263 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004264 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004265
4266 // Class description structures
4267
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004268 // struct _objc_ivar {
4269 // char *ivar_name;
4270 // char *ivar_type;
4271 // int ivar_offset;
4272 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004273 IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004274 Int8PtrTy,
4275 IntTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004276 NULL);
4277 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
4278
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004279 // struct _objc_ivar_list *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004280 IvarListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004281 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004282 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004283
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004284 // struct _objc_method_list *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004285 MethodListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004286 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004287 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004288
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004289 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004290 ClassExtensionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004291 llvm::StructType::get(VMContext, IntTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004292 Int8PtrTy,
4293 PropertyListPtrTy,
4294 NULL);
4295 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004296 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004297
Owen Andersonc36edfe2009-08-13 23:27:53 +00004298 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004299
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004300 // struct _objc_class {
4301 // Class isa;
4302 // Class super_class;
4303 // char *name;
4304 // long version;
4305 // long info;
4306 // long instance_size;
4307 // struct _objc_ivar_list *ivars;
4308 // struct _objc_method_list *methods;
4309 // struct _objc_cache *cache;
4310 // struct _objc_protocol_list *protocols;
4311 // char *ivar_layout;
4312 // struct _objc_class_ext *ext;
4313 // };
Owen Anderson758428f2009-08-05 23:18:46 +00004314 T = llvm::StructType::get(VMContext,
4315 llvm::PointerType::getUnqual(ClassTyHolder),
Owen Anderson9793f0e2009-07-29 22:16:19 +00004316 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004317 Int8PtrTy,
4318 LongTy,
4319 LongTy,
4320 LongTy,
4321 IvarListPtrTy,
4322 MethodListPtrTy,
4323 CachePtrTy,
4324 ProtocolListPtrTy,
4325 Int8PtrTy,
4326 ClassExtensionPtrTy,
4327 NULL);
4328 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004329
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004330 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
4331 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004332 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004333
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004334 // struct _objc_category {
4335 // char *category_name;
4336 // char *class_name;
4337 // struct _objc_method_list *instance_method;
4338 // struct _objc_method_list *class_method;
4339 // uint32_t size; // sizeof(struct _objc_category)
4340 // struct _objc_property_list *instance_properties;// category's @property
4341 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004342 CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004343 Int8PtrTy,
4344 MethodListPtrTy,
4345 MethodListPtrTy,
4346 ProtocolListPtrTy,
4347 IntTy,
4348 PropertyListPtrTy,
4349 NULL);
4350 CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
4351
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004352 // Global metadata structures
4353
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004354 // struct _objc_symtab {
4355 // long sel_ref_cnt;
4356 // SEL *refs;
4357 // short cls_def_cnt;
4358 // short cat_def_cnt;
4359 // char *defs[cls_def_cnt + cat_def_cnt];
4360 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004361 SymtabTy = llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004362 SelectorPtrTy,
4363 ShortTy,
4364 ShortTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004365 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004366 NULL);
4367 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004368 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004369
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00004370 // struct _objc_module {
4371 // long version;
4372 // long size; // sizeof(struct _objc_module)
4373 // char *name;
4374 // struct _objc_symtab* symtab;
4375 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004376 ModuleTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004377 llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004378 LongTy,
4379 Int8PtrTy,
4380 SymtabPtrTy,
4381 NULL);
4382 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00004383
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004384
Mike Stump18bb9282009-05-16 07:57:57 +00004385 // FIXME: This is the size of the setjmp buffer and should be target
4386 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00004387 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004388
Anders Carlsson9ff22482008-09-09 10:10:21 +00004389 // Exceptions
Owen Anderson9793f0e2009-07-29 22:16:19 +00004390 const llvm::Type *StackPtrTy = llvm::ArrayType::get(
Benjamin Kramerabd5b902009-10-13 10:07:13 +00004391 llvm::Type::getInt8PtrTy(VMContext), 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004392
4393 ExceptionDataTy =
Chris Lattner5e016ae2010-06-27 07:15:29 +00004394 llvm::StructType::get(VMContext,
4395 llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
4396 SetJmpBufferSize),
Anders Carlsson9ff22482008-09-09 10:10:21 +00004397 StackPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004398 CGM.getModule().addTypeName("struct._objc_exception_data",
Anders Carlsson9ff22482008-09-09 10:10:21 +00004399 ExceptionDataTy);
4400
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004401}
4402
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004403ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004404 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004405 // struct _method_list_t {
4406 // uint32_t entsize; // sizeof(struct _objc_method)
4407 // uint32_t method_count;
4408 // struct _objc_method method_list[method_count];
4409 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004410 MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004411 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004412 llvm::ArrayType::get(MethodTy, 0),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004413 NULL);
4414 CGM.getModule().addTypeName("struct.__method_list_t",
4415 MethodListnfABITy);
4416 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004417 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004418
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004419 // struct _protocol_t {
4420 // id isa; // NULL
4421 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004422 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004423 // const struct method_list_t * const instance_methods;
4424 // const struct method_list_t * const class_methods;
4425 // const struct method_list_t *optionalInstanceMethods;
4426 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004427 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004428 // const uint32_t size; // sizeof(struct _protocol_t)
4429 // const uint32_t flags; // = 0
4430 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004431
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004432 // Holder for struct _protocol_list_t *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004433 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004434
Owen Anderson758428f2009-08-05 23:18:46 +00004435 ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004436 Int8PtrTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004437 llvm::PointerType::getUnqual(
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004438 ProtocolListTyHolder),
4439 MethodListnfABIPtrTy,
4440 MethodListnfABIPtrTy,
4441 MethodListnfABIPtrTy,
4442 MethodListnfABIPtrTy,
4443 PropertyListPtrTy,
4444 IntTy,
4445 IntTy,
4446 NULL);
4447 CGM.getModule().addTypeName("struct._protocol_t",
4448 ProtocolnfABITy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004449
4450 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004451 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004452
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004453 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004454 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004455 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004456 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004457 ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004458 llvm::ArrayType::get(
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004459 ProtocolnfABIPtrTy, 0),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004460 NULL);
4461 CGM.getModule().addTypeName("struct._objc_protocol_list",
4462 ProtocolListnfABITy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004463 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004464 ProtocolListnfABITy);
4465
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004466 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004467 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004468
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004469 // struct _ivar_t {
4470 // unsigned long int *offset; // pointer to ivar offset location
4471 // char *name;
4472 // char *type;
4473 // uint32_t alignment;
4474 // uint32_t size;
4475 // }
Mike Stump11289f42009-09-09 15:08:12 +00004476 IvarnfABITy = llvm::StructType::get(VMContext,
Owen Anderson758428f2009-08-05 23:18:46 +00004477 llvm::PointerType::getUnqual(LongTy),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004478 Int8PtrTy,
4479 Int8PtrTy,
4480 IntTy,
4481 IntTy,
4482 NULL);
4483 CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004484
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004485 // struct _ivar_list_t {
4486 // uint32 entsize; // sizeof(struct _ivar_t)
4487 // uint32 count;
4488 // struct _iver_t list[count];
4489 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004490 IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004491 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004492 llvm::ArrayType::get(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004493 IvarnfABITy, 0),
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004494 NULL);
4495 CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004496
Owen Anderson9793f0e2009-07-29 22:16:19 +00004497 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004498
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004499 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004500 // uint32_t const flags;
4501 // uint32_t const instanceStart;
4502 // uint32_t const instanceSize;
4503 // uint32_t const reserved; // only when building for 64bit targets
4504 // const uint8_t * const ivarLayout;
4505 // const char *const name;
4506 // const struct _method_list_t * const baseMethods;
4507 // const struct _objc_protocol_list *const baseProtocols;
4508 // const struct _ivar_list_t *const ivars;
4509 // const uint8_t * const weakIvarLayout;
4510 // const struct _prop_list_t * const properties;
4511 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004512
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004513 // FIXME. Add 'reserved' field in 64bit abi mode!
Owen Anderson758428f2009-08-05 23:18:46 +00004514 ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004515 IntTy,
4516 IntTy,
4517 Int8PtrTy,
4518 Int8PtrTy,
4519 MethodListnfABIPtrTy,
4520 ProtocolListnfABIPtrTy,
4521 IvarListnfABIPtrTy,
4522 Int8PtrTy,
4523 PropertyListPtrTy,
4524 NULL);
4525 CGM.getModule().addTypeName("struct._class_ro_t",
4526 ClassRonfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004527
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004528 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
4529 std::vector<const llvm::Type*> Params;
4530 Params.push_back(ObjectPtrTy);
4531 Params.push_back(SelectorPtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004532 ImpnfABITy = llvm::PointerType::getUnqual(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004533 llvm::FunctionType::get(ObjectPtrTy, Params, false));
4534
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004535 // struct _class_t {
4536 // struct _class_t *isa;
4537 // struct _class_t * const superclass;
4538 // void *cache;
4539 // IMP *vtable;
4540 // struct class_ro_t *ro;
4541 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004542
Owen Andersonc36edfe2009-08-13 23:27:53 +00004543 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Owen Anderson170229f2009-07-14 23:10:40 +00004544 ClassnfABITy =
Owen Anderson758428f2009-08-05 23:18:46 +00004545 llvm::StructType::get(VMContext,
4546 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004547 llvm::PointerType::getUnqual(ClassTyHolder),
4548 CachePtrTy,
4549 llvm::PointerType::getUnqual(ImpnfABITy),
4550 llvm::PointerType::getUnqual(ClassRonfABITy),
4551 NULL);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004552 CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4553
4554 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004555 ClassnfABITy);
4556
Fariborz Jahanian71394042009-01-23 23:53:38 +00004557 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004558 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004559
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004560 // struct _category_t {
4561 // const char * const name;
4562 // struct _class_t *const cls;
4563 // const struct _method_list_t * const instance_methods;
4564 // const struct _method_list_t * const class_methods;
4565 // const struct _protocol_list_t * const protocols;
4566 // const struct _prop_list_t * const properties;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00004567 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004568 CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
Fariborz Jahanian71394042009-01-23 23:53:38 +00004569 ClassnfABIPtrTy,
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00004570 MethodListnfABIPtrTy,
4571 MethodListnfABIPtrTy,
4572 ProtocolListnfABIPtrTy,
4573 PropertyListPtrTy,
4574 NULL);
4575 CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004576
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004577 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004578 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4579 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004580
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004581 // MessageRefTy - LLVM for:
4582 // struct _message_ref_t {
4583 // IMP messenger;
4584 // SEL name;
4585 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004586
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004587 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00004588 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004589 Ctx.getTranslationUnitDecl(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004590 SourceLocation(),
4591 &Ctx.Idents.get("_message_ref_t"));
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004592 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004593 Ctx.VoidPtrTy, 0, 0, false));
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004594 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004595 Ctx.getObjCSelType(), 0, 0, false));
Douglas Gregord5058122010-02-11 01:19:42 +00004596 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004597
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004598 MessageRefCTy = Ctx.getTagDeclType(RD);
4599 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4600 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004601
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004602 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004603 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004604
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004605 // SuperMessageRefTy - LLVM for:
4606 // struct _super_message_ref_t {
4607 // SUPER_IMP messenger;
4608 // SEL name;
4609 // };
Owen Anderson758428f2009-08-05 23:18:46 +00004610 SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004611 SelectorPtrTy,
4612 NULL);
4613 CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004614
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004615 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004616 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4617
Daniel Dunbarb1559a42009-03-01 04:46:24 +00004618
4619 // struct objc_typeinfo {
4620 // const void** vtable; // objc_ehtype_vtable + 2
4621 // const char* name; // c++ typeinfo string
4622 // Class cls;
4623 // };
Owen Anderson758428f2009-08-05 23:18:46 +00004624 EHTypeTy = llvm::StructType::get(VMContext,
4625 llvm::PointerType::getUnqual(Int8PtrTy),
Daniel Dunbarb1559a42009-03-01 04:46:24 +00004626 Int8PtrTy,
4627 ClassnfABIPtrTy,
4628 NULL);
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00004629 CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004630 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004631}
4632
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004633llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004634 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004635
Fariborz Jahanian71394042009-01-23 23:53:38 +00004636 return NULL;
4637}
4638
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004639void CGObjCNonFragileABIMac::AddModuleClassList(const
4640 std::vector<llvm::GlobalValue*>
4641 &Container,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004642 const char *SymbolName,
4643 const char *SectionName) {
4644 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004645
Daniel Dunbar19573e72009-05-15 21:48:48 +00004646 if (!NumClasses)
4647 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004648
Daniel Dunbar19573e72009-05-15 21:48:48 +00004649 std::vector<llvm::Constant*> Symbols(NumClasses);
4650 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00004651 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00004652 ObjCTypes.Int8PtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004653 llvm::Constant* Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004654 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004655 NumClasses),
4656 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004657
Daniel Dunbar19573e72009-05-15 21:48:48 +00004658 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00004659 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004660 llvm::GlobalValue::InternalLinkage,
4661 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00004662 SymbolName);
Daniel Dunbar710cb202010-04-25 20:39:32 +00004663 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00004664 GV->setSection(SectionName);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004665 CGM.AddUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00004666}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004667
Fariborz Jahanian71394042009-01-23 23:53:38 +00004668void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4669 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004670
Daniel Dunbar19573e72009-05-15 21:48:48 +00004671 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004672 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004673 AddModuleClassList(DefinedClasses,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004674 "\01L_OBJC_LABEL_CLASS_$",
4675 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahanian67260552009-11-17 21:37:35 +00004676
Fariborz Jahanian67260552009-11-17 21:37:35 +00004677 for (unsigned i = 0; i < DefinedClasses.size(); i++) {
4678 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
4679 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4680 continue;
4681 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahanian67260552009-11-17 21:37:35 +00004682 }
4683
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004684 for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
4685 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
4686 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4687 continue;
4688 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4689 }
Fariborz Jahanian67260552009-11-17 21:37:35 +00004690
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004691 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004692 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4693 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004694
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004695 // Build list of all implemented category addresses in array
4696 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004697 AddModuleClassList(DefinedCategories,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004698 "\01L_OBJC_LABEL_CATEGORY_$",
4699 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004700 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004701 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4702 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004703
Daniel Dunbar5e639272010-04-25 20:39:01 +00004704 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00004705}
4706
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004707/// LegacyDispatchedSelector - Returns true if SEL is not in the list of
Fariborz Jahaniane4128642009-05-12 20:06:41 +00004708/// NonLegacyDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004709/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004710/// message dispatch call for all the rest.
4711///
4712bool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004713 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
4714 default:
4715 assert(0 && "Invalid dispatch method!");
4716 case CodeGenOptions::Legacy:
Daniel Dunbarca5e3eb2010-02-01 21:07:33 +00004717 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004718 case CodeGenOptions::NonLegacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00004719 return false;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004720 case CodeGenOptions::Mixed:
4721 break;
4722 }
4723
4724 // If so, see whether this selector is in the white-list of things which must
4725 // use the new dispatch convention. We lazily build a dense set for this.
Fariborz Jahaniane4128642009-05-12 20:06:41 +00004726 if (NonLegacyDispatchMethods.empty()) {
4727 NonLegacyDispatchMethods.insert(GetNullarySelector("alloc"));
4728 NonLegacyDispatchMethods.insert(GetNullarySelector("class"));
4729 NonLegacyDispatchMethods.insert(GetNullarySelector("self"));
4730 NonLegacyDispatchMethods.insert(GetNullarySelector("isFlipped"));
4731 NonLegacyDispatchMethods.insert(GetNullarySelector("length"));
4732 NonLegacyDispatchMethods.insert(GetNullarySelector("count"));
4733 NonLegacyDispatchMethods.insert(GetNullarySelector("retain"));
4734 NonLegacyDispatchMethods.insert(GetNullarySelector("release"));
4735 NonLegacyDispatchMethods.insert(GetNullarySelector("autorelease"));
4736 NonLegacyDispatchMethods.insert(GetNullarySelector("hash"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004737
Fariborz Jahaniane4128642009-05-12 20:06:41 +00004738 NonLegacyDispatchMethods.insert(GetUnarySelector("allocWithZone"));
4739 NonLegacyDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
4740 NonLegacyDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
4741 NonLegacyDispatchMethods.insert(GetUnarySelector("objectForKey"));
4742 NonLegacyDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
4743 NonLegacyDispatchMethods.insert(GetUnarySelector("isEqualToString"));
4744 NonLegacyDispatchMethods.insert(GetUnarySelector("isEqual"));
4745 NonLegacyDispatchMethods.insert(GetUnarySelector("addObject"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004746 // "countByEnumeratingWithState:objects:count"
Fariborz Jahanian18801362009-05-13 16:19:02 +00004747 IdentifierInfo *KeyIdents[] = {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004748 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4749 &CGM.getContext().Idents.get("objects"),
4750 &CGM.getContext().Idents.get("count")
Fariborz Jahanian18801362009-05-13 16:19:02 +00004751 };
4752 NonLegacyDispatchMethods.insert(
4753 CGM.getContext().Selectors.getSelector(3, KeyIdents));
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004754 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004755
Fariborz Jahaniane4128642009-05-12 20:06:41 +00004756 return (NonLegacyDispatchMethods.count(Sel) == 0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004757}
4758
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004759// Metadata flags
4760enum MetaDataDlags {
4761 CLS = 0x0,
4762 CLS_META = 0x1,
4763 CLS_ROOT = 0x2,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004764 OBJC2_CLS_HIDDEN = 0x10,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004765 CLS_EXCEPTION = 0x20
4766};
4767/// BuildClassRoTInitializer - generate meta-data for:
4768/// struct _class_ro_t {
4769/// uint32_t const flags;
4770/// uint32_t const instanceStart;
4771/// uint32_t const instanceSize;
4772/// uint32_t const reserved; // only when building for 64bit targets
4773/// const uint8_t * const ivarLayout;
4774/// const char *const name;
4775/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004776/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004777/// const struct _ivar_list_t *const ivars;
4778/// const uint8_t * const weakIvarLayout;
4779/// const struct _prop_list_t * const properties;
4780/// }
4781///
4782llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004783 unsigned flags,
4784 unsigned InstanceStart,
4785 unsigned InstanceSize,
4786 const ObjCImplementationDecl *ID) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004787 std::string ClassName = ID->getNameAsString();
4788 std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004789 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4790 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4791 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004792 // FIXME. For 64bit targets add 0 here.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004793 Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4794 : BuildIvarLayout(ID, true);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004795 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004796 // const struct _method_list_t * const baseMethods;
4797 std::vector<llvm::Constant*> Methods;
4798 std::string MethodListName("\01l_OBJC_$_");
4799 if (flags & CLS_META) {
4800 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004801 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004802 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004803 // Class methods should always be defined.
4804 Methods.push_back(GetMethodConstant(*i));
4805 }
4806 } else {
4807 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004808 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004809 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004810 // Instance methods should always be defined.
4811 Methods.push_back(GetMethodConstant(*i));
4812 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004813 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004814 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004815 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004816
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004817 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4818 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004819
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004820 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4821 if (llvm::Constant *C = GetMethodConstant(MD))
4822 Methods.push_back(C);
4823 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4824 if (llvm::Constant *C = GetMethodConstant(MD))
4825 Methods.push_back(C);
4826 }
4827 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004828 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004829 Values[ 5] = EmitMethodList(MethodListName,
4830 "__DATA, __objc_const", Methods);
4831
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004832 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4833 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004834 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004835 + OID->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004836 OID->protocol_begin(),
4837 OID->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004838
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00004839 if (flags & CLS_META)
Owen Anderson0b75f232009-07-31 20:28:54 +00004840 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00004841 else
4842 Values[ 7] = EmitIvarList(ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004843 Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4844 : BuildIvarLayout(ID, false);
Fariborz Jahanian066347e2009-01-28 22:18:42 +00004845 if (flags & CLS_META)
Owen Anderson0b75f232009-07-31 20:28:54 +00004846 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian066347e2009-01-28 22:18:42 +00004847 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004848 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4849 ID, ID->getClassInterface(), ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004850 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004851 Values);
4852 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004853 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
4854 llvm::GlobalValue::InternalLinkage,
4855 Init,
4856 (flags & CLS_META) ?
4857 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4858 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00004859 CLASS_RO_GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00004860 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00004861 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004862 return CLASS_RO_GV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00004863
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004864}
4865
4866/// BuildClassMetaData - This routine defines that to-level meta-data
4867/// for the given ClassName for:
4868/// struct _class_t {
4869/// struct _class_t *isa;
4870/// struct _class_t * const superclass;
4871/// void *cache;
4872/// IMP *vtable;
4873/// struct class_ro_t *ro;
4874/// }
4875///
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004876llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004877 std::string &ClassName,
4878 llvm::Constant *IsAGV,
4879 llvm::Constant *SuperClassGV,
4880 llvm::Constant *ClassRoGV,
4881 bool HiddenVisibility) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004882 std::vector<llvm::Constant*> Values(5);
4883 Values[0] = IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004884 Values[1] = SuperClassGV;
4885 if (!Values[1])
4886 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004887 Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
4888 Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4889 Values[4] = ClassRoGV; // &CLASS_RO_GV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004890 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004891 Values);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00004892 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4893 GV->setInitializer(Init);
Fariborz Jahanian04087232009-01-31 01:07:39 +00004894 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00004895 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00004896 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian82208252009-01-31 00:59:10 +00004897 if (HiddenVisibility)
4898 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004899 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004900}
4901
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004902bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00004903CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004904 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004905}
4906
Daniel Dunbar961202372009-05-03 12:57:56 +00004907void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00004908 uint32_t &InstanceStart,
4909 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004910 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00004911 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004912
Daniel Dunbar9b042e02009-05-04 23:23:09 +00004913 // InstanceSize is really instance end.
Anders Carlsson27b50132009-07-18 21:26:44 +00004914 InstanceSize = llvm::RoundUpToAlignment(RL.getDataSize(), 8) / 8;
Daniel Dunbar9b042e02009-05-04 23:23:09 +00004915
4916 // If there are no fields, the start is the same as the end.
4917 if (!RL.getFieldCount())
4918 InstanceStart = InstanceSize;
4919 else
4920 InstanceStart = RL.getFieldOffset(0) / 8;
Daniel Dunbar554fd792009-04-19 23:41:48 +00004921}
4922
Fariborz Jahanian71394042009-01-23 23:53:38 +00004923void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
4924 std::string ClassName = ID->getNameAsString();
4925 if (!ObjCEmptyCacheVar) {
4926 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004927 CGM.getModule(),
4928 ObjCTypes.CacheTy,
4929 false,
4930 llvm::GlobalValue::ExternalLinkage,
4931 0,
4932 "_objc_empty_cache");
4933
Fariborz Jahanian71394042009-01-23 23:53:38 +00004934 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004935 CGM.getModule(),
4936 ObjCTypes.ImpnfABITy,
4937 false,
4938 llvm::GlobalValue::ExternalLinkage,
4939 0,
4940 "_objc_empty_vtable");
Fariborz Jahanian71394042009-01-23 23:53:38 +00004941 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004942 assert(ID->getClassInterface() &&
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004943 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00004944 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004945 uint32_t InstanceStart =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00004946 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004947 uint32_t InstanceSize = InstanceStart;
4948 uint32_t flags = CLS_META;
Daniel Dunbar15894b72009-04-07 05:48:37 +00004949 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4950 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004951
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004952 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004953
4954 bool classIsHidden =
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00004955 CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden;
Fariborz Jahanian82208252009-01-31 00:59:10 +00004956 if (classIsHidden)
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004957 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00004958 if (ID->getNumIvarInitializers())
4959 flags |= eClassFlags_ABI2_HasCXXStructors;
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004960 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004961 // class is root
4962 flags |= CLS_ROOT;
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00004963 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004964 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004965 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004966 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00004967 const ObjCInterfaceDecl *Root = ID->getClassInterface();
4968 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4969 Root = Super;
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004970 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004971 if (Root->hasAttr<WeakImportAttr>())
4972 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00004973 // work on super class metadata symbol.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004974 std::string SuperClassName =
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004975 ObjCMetaClassName +
4976 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004977 SuperClassGV = GetClassGlobal(SuperClassName);
Fariborz Jahanian67260552009-11-17 21:37:35 +00004978 if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
4979 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004980 }
4981 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4982 InstanceStart,
4983 InstanceSize,ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004984 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004985 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian82208252009-01-31 00:59:10 +00004986 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4987 classIsHidden);
Fariborz Jahanian67260552009-11-17 21:37:35 +00004988 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00004989
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004990 // Metadata for the class
4991 flags = CLS;
Fariborz Jahanian82208252009-01-31 00:59:10 +00004992 if (classIsHidden)
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004993 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00004994 if (ID->getNumIvarInitializers())
4995 flags |= eClassFlags_ABI2_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00004996
Douglas Gregor78bd61f2009-06-18 16:11:24 +00004997 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
Daniel Dunbar8f28d012009-04-08 04:21:03 +00004998 flags |= CLS_EXCEPTION;
4999
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005000 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005001 flags |= CLS_ROOT;
5002 SuperClassGV = 0;
Chris Lattnerb433b272009-04-19 06:02:28 +00005003 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005004 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005005 std::string RootClassName =
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005006 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005007 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Fariborz Jahanian67260552009-11-17 21:37:35 +00005008 if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
5009 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005010 }
Daniel Dunbar961202372009-05-03 12:57:56 +00005011 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005012 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005013 InstanceStart,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005014 InstanceSize,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005015 ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005016
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005017 TClassName = ObjCClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005018 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005019 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5020 classIsHidden);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005021 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005022
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005023 // Determine if this class is also "non-lazy".
5024 if (ImplementationIsNonLazy(ID))
5025 DefinedNonLazyClasses.push_back(ClassMD);
5026
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005027 // Force the definition of the EHType if necessary.
5028 if (flags & CLS_EXCEPTION)
5029 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanian71394042009-01-23 23:53:38 +00005030}
5031
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005032/// GenerateProtocolRef - This routine is called to generate code for
5033/// a protocol reference expression; as in:
5034/// @code
5035/// @protocol(Proto1);
5036/// @endcode
5037/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5038/// which will hold address of the protocol meta-data.
5039///
5040llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005041 const ObjCProtocolDecl *PD) {
5042
Fariborz Jahanian464423d2009-04-10 18:47:34 +00005043 // This routine is called for @protocol only. So, we must build definition
5044 // of protocol's meta-data (not a reference to it!)
5045 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005046 llvm::Constant *Init =
5047 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5048 ObjCTypes.ExternalProtocolPtrTy);
5049
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005050 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
5051 ProtocolName += PD->getNameAsCString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005052
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005053 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5054 if (PTGV)
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005055 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005056 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005057 CGM.getModule(),
5058 Init->getType(), false,
5059 llvm::GlobalValue::WeakAnyLinkage,
5060 Init,
5061 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005062 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5063 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005064 CGM.AddUsedGlobal(PTGV);
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005065 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005066}
5067
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005068/// GenerateCategory - Build metadata for a category implementation.
5069/// struct _category_t {
5070/// const char * const name;
5071/// struct _class_t *const cls;
5072/// const struct _method_list_t * const instance_methods;
5073/// const struct _method_list_t * const class_methods;
5074/// const struct _protocol_list_t * const protocols;
5075/// const struct _prop_list_t * const properties;
5076/// }
5077///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005078void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005079 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005080 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005081 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5082 "_$_" + OCD->getNameAsString());
5083 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar15894b72009-04-07 05:48:37 +00005084 Interface->getNameAsString());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005085
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005086 std::vector<llvm::Constant*> Values(6);
5087 Values[0] = GetClassName(OCD->getIdentifier());
5088 // meta-class entry symbol
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005089 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Fariborz Jahanian3ad8dcf2009-11-17 22:02:21 +00005090 if (Interface->hasAttr<WeakImportAttr>())
5091 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5092
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005093 Values[1] = ClassGV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005094 std::vector<llvm::Constant*> Methods;
5095 std::string MethodListName(Prefix);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005096 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005097 "_$_" + OCD->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005098
5099 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005100 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005101 // Instance methods should always be defined.
5102 Methods.push_back(GetMethodConstant(*i));
5103 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005104
5105 Values[2] = EmitMethodList(MethodListName,
5106 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005107 Methods);
5108
5109 MethodListName = Prefix;
5110 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5111 OCD->getNameAsString();
5112 Methods.clear();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005113 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005114 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005115 // Class methods should always be defined.
5116 Methods.push_back(GetMethodConstant(*i));
5117 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005118
5119 Values[3] = EmitMethodList(MethodListName,
5120 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005121 Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005122 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00005123 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005124 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005125 llvm::SmallString<256> ExtName;
5126 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5127 << OCD->getName();
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005128 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005129 + Interface->getName() + "_$_"
5130 + Category->getName(),
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005131 Category->protocol_begin(),
5132 Category->protocol_end());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005133 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5134 OCD, Category, ObjCTypes);
Mike Stump658fe022009-07-30 22:28:39 +00005135 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00005136 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5137 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005138 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005139
5140 llvm::Constant *Init =
5141 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005142 Values);
5143 llvm::GlobalVariable *GCATV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005144 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005145 false,
5146 llvm::GlobalValue::InternalLinkage,
5147 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005148 ExtCatName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005149 GCATV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005150 CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005151 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005152 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005153 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005154
5155 // Determine if this category is also "non-lazy".
5156 if (ImplementationIsNonLazy(OCD))
5157 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005158}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005159
5160/// GetMethodConstant - Return a struct objc_method constant for the
5161/// given method if it has been defined. The result is null if the
5162/// method has not been defined. The return value has type MethodPtrTy.
5163llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005164 const ObjCMethodDecl *MD) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005165 // FIXME: Use DenseMap::lookup
5166 llvm::Function *Fn = MethodDefinitions[MD];
5167 if (!Fn)
5168 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005169
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005170 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005171 Method[0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00005172 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005173 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005174 Method[1] = GetMethodVarType(MD);
Owen Andersonade90fd2009-07-29 18:54:39 +00005175 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005176 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005177}
5178
5179/// EmitMethodList - Build meta-data for method declarations
5180/// struct _method_list_t {
5181/// uint32_t entsize; // sizeof(struct _objc_method)
5182/// uint32_t method_count;
5183/// struct _objc_method method_list[method_count];
5184/// }
5185///
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005186llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
5187 const char *Section,
5188 const ConstantVector &Methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005189 // Return null for empty list.
5190 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005191 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005192
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005193 std::vector<llvm::Constant*> Values(3);
5194 // sizeof(struct _objc_method)
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005195 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005196 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005197 // method_count
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005198 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005199 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005200 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005201 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005202 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005203
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005204 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005205 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005206 llvm::GlobalValue::InternalLinkage,
5207 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005208 Name);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005209 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005210 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005211 GV->setSection(Section);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005212 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00005213 return llvm::ConstantExpr::getBitCast(GV,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005214 ObjCTypes.MethodListnfABIPtrTy);
5215}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005216
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005217/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5218/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005219llvm::GlobalVariable *
5220CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5221 const ObjCIvarDecl *Ivar) {
5222 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar3f86b9c2009-05-05 00:36:57 +00005223 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregorbcced4e2009-04-09 21:40:53 +00005224 '.' + Ivar->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005225 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005226 CGM.getModule().getGlobalVariable(Name);
5227 if (!IvarOffsetGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005228 IvarOffsetGV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005229 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005230 false,
5231 llvm::GlobalValue::ExternalLinkage,
5232 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005233 Name);
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005234 return IvarOffsetGV;
5235}
5236
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005237llvm::Constant *
5238CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5239 const ObjCIvarDecl *Ivar,
5240 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005241 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005242 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005243 Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005244 IvarOffsetGV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005245 CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005246
Mike Stump18bb9282009-05-16 07:57:57 +00005247 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
5248 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005249 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5250 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
5251 CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden)
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00005252 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00005253 else
Fariborz Jahanianbc3c77b2009-04-06 18:30:00 +00005254 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005255 IvarOffsetGV->setSection("__DATA, __objc_const");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005256 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005257}
5258
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005259/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005260/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005261/// IvarListnfABIPtrTy.
5262/// struct _ivar_t {
5263/// unsigned long int *offset; // pointer to ivar offset location
5264/// char *name;
5265/// char *type;
5266/// uint32_t alignment;
5267/// uint32_t size;
5268/// }
5269/// struct _ivar_list_t {
5270/// uint32 entsize; // sizeof(struct _ivar_t)
5271/// uint32 count;
5272/// struct _iver_t list[count];
5273/// }
5274///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005275
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005276llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005277 const ObjCImplementationDecl *ID) {
5278
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005279 std::vector<llvm::Constant*> Ivars, Ivar(5);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005280
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005281 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5282 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005283
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005284 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005285
Daniel Dunbarae032262009-04-20 00:33:43 +00005286 // Collect declared and synthesized ivars in a small vector.
Fariborz Jahanian63a224a2009-03-31 18:11:23 +00005287 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian7c809592009-06-04 01:19:09 +00005288 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005289
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005290 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
5291 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian7c809592009-06-04 01:19:09 +00005292 // Ignore unnamed bit-fields.
5293 if (!IVD->getDeclName())
5294 continue;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005295 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar961202372009-05-03 12:57:56 +00005296 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005297 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5298 Ivar[2] = GetMethodVarType(IVD);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005299 const llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005300 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005301 unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005302 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005303 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005304 Align = llvm::Log2_32(Align);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005305 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00005306 // NOTE. Size of a bitfield does not match gcc's, because of the
5307 // way bitfields are treated special in each. But I am told that
5308 // 'size' for bitfield ivars is ignored by the runtime so it does
5309 // not matter. If it matters, there is enough info to get the
5310 // bitfield right!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005311 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005312 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005313 }
5314 // Return null for empty list.
5315 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005316 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005317 std::vector<llvm::Constant*> Values(3);
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005318 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005319 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5320 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005321 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005322 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005323 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005324 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005325 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5326 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005327 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005328 llvm::GlobalValue::InternalLinkage,
5329 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005330 Prefix + OID->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005331 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005332 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005333 GV->setSection("__DATA, __objc_const");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005334
Chris Lattnerf56501c2009-07-17 23:57:13 +00005335 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00005336 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005337}
5338
5339llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005340 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005341 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005342
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005343 if (!Entry) {
5344 // We use the initializer as a marker of whether this is a forward
5345 // reference or not. At module finalization we add the empty
5346 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005347 Entry =
5348 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5349 llvm::GlobalValue::ExternalLinkage,
5350 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005351 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005352 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005353 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005354
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005355 return Entry;
5356}
5357
5358/// GetOrEmitProtocol - Generate the protocol meta-data:
5359/// @code
5360/// struct _protocol_t {
5361/// id isa; // NULL
5362/// const char * const protocol_name;
5363/// const struct _protocol_list_t * protocol_list; // super protocols
5364/// const struct method_list_t * const instance_methods;
5365/// const struct method_list_t * const class_methods;
5366/// const struct method_list_t *optionalInstanceMethods;
5367/// const struct method_list_t *optionalClassMethods;
5368/// const struct _prop_list_t * properties;
5369/// const uint32_t size; // sizeof(struct _protocol_t)
5370/// const uint32_t flags; // = 0
5371/// }
5372/// @endcode
5373///
5374
5375llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005376 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005377 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005378
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005379 // Early exit if a defining object has already been generated.
5380 if (Entry && Entry->hasInitializer())
5381 return Entry;
5382
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005383 // Construct method lists.
5384 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5385 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005386 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005387 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005388 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005389 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005390 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5391 OptInstanceMethods.push_back(C);
5392 } else {
5393 InstanceMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005394 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005395 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005396
5397 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005398 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005399 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005400 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005401 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5402 OptClassMethods.push_back(C);
5403 } else {
5404 ClassMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005405 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005406 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005407
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005408 std::vector<llvm::Constant*> Values(10);
5409 // isa is NULL
Owen Anderson0b75f232009-07-31 20:28:54 +00005410 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005411 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005412 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5413 PD->protocol_begin(),
5414 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005415
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005416 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005417 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005418 "__DATA, __objc_const",
5419 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005420 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005421 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005422 "__DATA, __objc_const",
5423 ClassMethods);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005424 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005425 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005426 "__DATA, __objc_const",
5427 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005428 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005429 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005430 "__DATA, __objc_const",
5431 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005432 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005433 0, PD, ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005434 uint32_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005435 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005436 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0b75f232009-07-31 20:28:54 +00005437 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005438 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005439 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005440
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005441 if (Entry) {
5442 // Already created, fix the linkage and update the initializer.
Mike Stumpa6ca3342009-03-07 16:33:28 +00005443 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005444 Entry->setInitializer(Init);
5445 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005446 Entry =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005447 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
5448 false, llvm::GlobalValue::WeakAnyLinkage, Init,
5449 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005450 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005451 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005452 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005453 }
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005454 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005455 CGM.AddUsedGlobal(Entry);
5456
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005457 // Use this protocol meta-data to build protocol list table in section
5458 // __DATA, __objc_protolist
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005459 llvm::GlobalVariable *PTGV =
5460 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
5461 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
5462 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005463 PTGV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005464 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbarb25452a2009-04-15 02:56:18 +00005465 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005466 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005467 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005468 return Entry;
5469}
5470
5471/// EmitProtocolList - Generate protocol list meta-data:
5472/// @code
5473/// struct _protocol_list_t {
5474/// long protocol_count; // Note, this is 32/64 bit
5475/// struct _protocol_t[protocol_count];
5476/// }
5477/// @endcode
5478///
5479llvm::Constant *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005480CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
5481 ObjCProtocolDecl::protocol_iterator begin,
5482 ObjCProtocolDecl::protocol_iterator end) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005483 std::vector<llvm::Constant*> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005484
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005485 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005486 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00005487 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005488
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005489 // FIXME: We shouldn't need to do this lookup here, should we?
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005490 llvm::SmallString<256> TmpName;
5491 Name.toVector(TmpName);
5492 llvm::GlobalVariable *GV =
5493 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005494 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005495 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005496
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005497 for (; begin != end; ++begin)
5498 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5499
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005500 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00005501 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005502 ObjCTypes.ProtocolnfABIPtrTy));
5503
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005504 std::vector<llvm::Constant*> Values(2);
Owen Anderson170229f2009-07-14 23:10:40 +00005505 Values[0] =
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005506 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005507 Values[1] =
Owen Anderson47034e12009-07-28 18:33:04 +00005508 llvm::ConstantArray::get(
Owen Anderson9793f0e2009-07-29 22:16:19 +00005509 llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005510 ProtocolRefs.size()),
5511 ProtocolRefs);
5512
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005513 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Owen Andersonc10c8d32009-07-08 19:05:04 +00005514 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005515 llvm::GlobalValue::InternalLinkage,
5516 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005517 Name);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005518 GV->setSection("__DATA, __objc_const");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005519 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005520 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Chris Lattnerf56501c2009-07-17 23:57:13 +00005521 CGM.AddUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005522 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005523 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005524}
5525
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005526/// GetMethodDescriptionConstant - This routine build following meta-data:
5527/// struct _objc_method {
5528/// SEL _cmd;
5529/// char *method_type;
5530/// char *_imp;
5531/// }
5532
5533llvm::Constant *
5534CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
5535 std::vector<llvm::Constant*> Desc(3);
Owen Anderson170229f2009-07-14 23:10:40 +00005536 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005537 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5538 ObjCTypes.SelectorPtrTy);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005539 Desc[1] = GetMethodVarType(MD);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005540 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00005541 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005542 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005543}
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005544
5545/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
5546/// This code gen. amounts to generating code for:
5547/// @code
5548/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
5549/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005550///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00005551LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00005552 CodeGen::CodeGenFunction &CGF,
5553 QualType ObjectTy,
5554 llvm::Value *BaseValue,
5555 const ObjCIvarDecl *Ivar,
5556 unsigned CVRQualifiers) {
5557 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00005558 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5559 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005560}
5561
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005562llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005563 CodeGen::CodeGenFunction &CGF,
5564 const ObjCInterfaceDecl *Interface,
5565 const ObjCIvarDecl *Ivar) {
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005566 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005567}
5568
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005569CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005570 CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00005571 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005572 QualType ResultType,
5573 Selector Sel,
5574 llvm::Value *Receiver,
5575 QualType Arg0Ty,
5576 bool IsSuper,
5577 const CallArgList &CallArgs) {
Mike Stump18bb9282009-05-16 07:57:57 +00005578 // FIXME. Even though IsSuper is passes. This function doese not handle calls
5579 // to 'super' receivers.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005580 CodeGenTypes &Types = CGM.getTypes();
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005581 llvm::Value *Arg0 = Receiver;
5582 if (!IsSuper)
5583 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005584
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005585 // Find the message function name.
Mike Stump18bb9282009-05-16 07:57:57 +00005586 // FIXME. This is too much work to get the ABI-specific result type needed to
5587 // find the message name.
John McCall2da83a32010-02-26 00:48:12 +00005588 const CGFunctionInfo &FnInfo
Rafael Espindolac50c27c2010-03-30 20:24:48 +00005589 = Types.getFunctionInfo(ResultType, CallArgList(),
5590 FunctionType::ExtInfo());
Fariborz Jahaniane29b4f02009-04-30 23:08:58 +00005591 llvm::Constant *Fn = 0;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005592 std::string Name("\01l_");
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00005593 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
Fariborz Jahanian90655412009-02-05 18:00:27 +00005594#if 0
5595 // unlike what is documented. gcc never generates this API!!
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005596 if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
Chris Lattner2dfdb3e2009-04-22 02:53:24 +00005597 Fn = ObjCTypes.getMessageSendIdStretFixupFn();
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005598 // FIXME. Is there a better way of getting these names.
5599 // They are available in RuntimeFunctions vector pair.
5600 Name += "objc_msgSendId_stret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00005601 } else
Fariborz Jahanian90655412009-02-05 18:00:27 +00005602#endif
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005603 if (IsSuper) {
Chris Lattner2dfdb3e2009-04-22 02:53:24 +00005604 Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005605 Name += "objc_msgSendSuper2_stret_fixup";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005606 } else {
5607 Fn = ObjCTypes.getMessageSendStretFixupFn();
5608 Name += "objc_msgSend_stret_fixup";
5609 }
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00005610 } else if (!IsSuper && CGM.ReturnTypeUsesFPRet(ResultType)) {
5611 Fn = ObjCTypes.getMessageSendFpretFixupFn();
5612 Name += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00005613 } else {
Fariborz Jahanian90655412009-02-05 18:00:27 +00005614#if 0
5615// unlike what is documented. gcc never generates this API!!
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005616 if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
Chris Lattner2dfdb3e2009-04-22 02:53:24 +00005617 Fn = ObjCTypes.getMessageSendIdFixupFn();
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005618 Name += "objc_msgSendId_fixup";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005619 } else
Fariborz Jahanian90655412009-02-05 18:00:27 +00005620#endif
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005621 if (IsSuper) {
Chris Lattner2dfdb3e2009-04-22 02:53:24 +00005622 Fn = ObjCTypes.getMessageSendSuper2FixupFn();
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005623 Name += "objc_msgSendSuper2_fixup";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005624 } else {
5625 Fn = ObjCTypes.getMessageSendFixupFn();
5626 Name += "objc_msgSend_fixup";
5627 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005628 }
Fariborz Jahaniane29b4f02009-04-30 23:08:58 +00005629 assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend");
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005630 Name += '_';
5631 std::string SelName(Sel.getAsString());
5632 // Replace all ':' in selector name with '_' ouch!
Mike Stump11289f42009-09-09 15:08:12 +00005633 for (unsigned i = 0; i < SelName.size(); i++)
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005634 if (SelName[i] == ':')
5635 SelName[i] = '_';
5636 Name += SelName;
5637 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5638 if (!GV) {
Daniel Dunbare60aa052009-04-15 19:03:14 +00005639 // Build message ref table entry.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005640 std::vector<llvm::Constant*> Values(2);
5641 Values[0] = Fn;
5642 Values[1] = GetMethodVarName(Sel);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005643 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Owen Andersonc10c8d32009-07-08 19:05:04 +00005644 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Mike Stumpa6ca3342009-03-07 16:33:28 +00005645 llvm::GlobalValue::WeakAnyLinkage,
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005646 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005647 Name);
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005648 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar24645c92009-04-15 19:04:46 +00005649 GV->setAlignment(16);
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005650 GV->setSection("__DATA, __objc_msgrefs, coalesced");
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005651 }
5652 llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005653
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005654 CallArgList ActualArgs;
5655 ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005656 ActualArgs.push_back(std::make_pair(RValue::get(Arg1),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005657 ObjCTypes.MessageRefCPtrTy));
5658 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
John McCallab26cfa2010-02-05 21:31:56 +00005659 const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindolac50c27c2010-03-30 20:24:48 +00005660 FunctionType::ExtInfo());
Fariborz Jahanian4e87c832009-02-05 01:13:09 +00005661 llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0);
5662 Callee = CGF.Builder.CreateLoad(Callee);
Fariborz Jahanian35afdfc2009-02-14 21:25:36 +00005663 const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true);
Fariborz Jahanian4e87c832009-02-05 01:13:09 +00005664 Callee = CGF.Builder.CreateBitCast(Callee,
Owen Anderson9793f0e2009-07-29 22:16:19 +00005665 llvm::PointerType::getUnqual(FTy));
John McCall78a15112010-05-22 01:48:05 +00005666 return CGF.EmitCall(FnInfo1, Callee, Return, ActualArgs);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005667}
5668
5669/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005670CodeGen::RValue
5671CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00005672 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005673 QualType ResultType,
5674 Selector Sel,
5675 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005676 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00005677 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005678 const ObjCMethodDecl *Method) {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005679 return LegacyDispatchedSelector(Sel)
John McCall78a15112010-05-22 01:48:05 +00005680 ? EmitLegacyMessageSend(CGF, Return, ResultType,
5681 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005682 Receiver, CGF.getContext().getObjCIdType(),
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005683 false, CallArgs, Method, ObjCTypes)
John McCall78a15112010-05-22 01:48:05 +00005684 : EmitMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005685 Receiver, CGF.getContext().getObjCIdType(),
5686 false, CallArgs);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005687}
5688
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005689llvm::GlobalVariable *
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005690CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005691 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5692
Daniel Dunbara6468342009-03-02 05:18:14 +00005693 if (!GV) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005694 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005695 false, llvm::GlobalValue::ExternalLinkage,
5696 0, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005697 }
5698
5699 return GV;
5700}
5701
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005702llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5703 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005704 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005705
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005706 if (!Entry) {
Daniel Dunbar15894b72009-04-07 05:48:37 +00005707 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005708 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005709 Entry =
5710 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005711 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005712 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005713 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005714 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005715 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005716 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005717 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005718 CGM.AddUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005719 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005720
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005721 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005722}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005723
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005724llvm::Value *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005725CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005726 const ObjCInterfaceDecl *ID) {
5727 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005728
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005729 if (!Entry) {
5730 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5731 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005732 Entry =
5733 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005734 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005735 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005736 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005737 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005738 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005739 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005740 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005741 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005742 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005743
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005744 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005745}
5746
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005747/// EmitMetaClassRef - Return a Value * of the address of _class_t
5748/// meta-data
5749///
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005750llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5751 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005752 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5753 if (Entry)
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005754 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005755
Daniel Dunbar15894b72009-04-07 05:48:37 +00005756 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005757 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005758 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005759 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005760 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005761 MetaClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005762 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005763 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005764 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005765 ObjCTypes.ClassnfABIPtrTy));
5766
Daniel Dunbare60aa052009-04-15 19:03:14 +00005767 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005768 CGM.AddUsedGlobal(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005769
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005770 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005771}
5772
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005773/// GetClass - Return a reference to the class for the given interface
5774/// decl.
5775llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5776 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian95ace552009-11-17 22:42:00 +00005777 if (ID->hasAttr<WeakImportAttr>()) {
5778 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5779 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5780 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5781 }
5782
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005783 return EmitClassRef(Builder, ID);
5784}
5785
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005786/// Generates a message send where the super is the receiver. This is
5787/// a message send to self with special delivery semantics indicating
5788/// which class's method should be called.
5789CodeGen::RValue
5790CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00005791 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005792 QualType ResultType,
5793 Selector Sel,
5794 const ObjCInterfaceDecl *Class,
5795 bool isCategoryImpl,
5796 llvm::Value *Receiver,
5797 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005798 const CodeGen::CallArgList &CallArgs,
5799 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005800 // ...
5801 // Create and init a super structure; this is a (receiver, class)
5802 // pair we will pass to objc_msgSendSuper.
5803 llvm::Value *ObjCSuper =
5804 CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005805
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005806 llvm::Value *ReceiverAsObject =
5807 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5808 CGF.Builder.CreateStore(ReceiverAsObject,
5809 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005810
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005811 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005812 llvm::Value *Target;
5813 if (IsClassMessage) {
5814 if (isCategoryImpl) {
5815 // Message sent to "super' in a class method defined in
5816 // a category implementation.
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005817 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005818 Target = CGF.Builder.CreateStructGEP(Target, 0);
5819 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00005820 } else
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005821 Target = EmitMetaClassRef(CGF.Builder, Class);
Mike Stump658fe022009-07-30 22:28:39 +00005822 } else
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005823 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005824
Mike Stump18bb9282009-05-16 07:57:57 +00005825 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5826 // ObjCTypes types.
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005827 const llvm::Type *ClassTy =
5828 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
5829 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
5830 CGF.Builder.CreateStore(Target,
5831 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005832
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005833 return (LegacyDispatchedSelector(Sel))
John McCall78a15112010-05-22 01:48:05 +00005834 ? EmitLegacyMessageSend(CGF, Return, ResultType,
5835 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005836 ObjCSuper, ObjCTypes.SuperPtrCTy,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005837 true, CallArgs, Method, ObjCTypes)
John McCall78a15112010-05-22 01:48:05 +00005838 : EmitMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005839 ObjCSuper, ObjCTypes.SuperPtrCTy,
5840 true, CallArgs);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005841}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005842
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005843llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00005844 Selector Sel, bool lval) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005845 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005846
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005847 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005848 llvm::Constant *Casted =
5849 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5850 ObjCTypes.SelectorPtrTy);
5851 Entry =
5852 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
5853 llvm::GlobalValue::InternalLinkage,
5854 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005855 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005856 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005857 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005858
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00005859 if (lval)
5860 return Entry;
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005861 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005862}
Fariborz Jahanian06292952009-02-16 22:52:32 +00005863/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005864/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00005865///
5866void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005867 llvm::Value *src,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005868 llvm::Value *dst,
5869 llvm::Value *ivarOffset) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005870 const llvm::Type * SrcTy = src->getType();
5871 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005872 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005873 assert(Size <= 8 && "does not support size > 8");
5874 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5875 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005876 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5877 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005878 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5879 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005880 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5881 src, dst, ivarOffset);
Fariborz Jahanian06292952009-02-16 22:52:32 +00005882 return;
5883}
5884
5885/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5886/// objc_assign_strongCast (id src, id *dst)
5887///
5888void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005889 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005890 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005891 const llvm::Type * SrcTy = src->getType();
5892 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005893 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005894 assert(Size <= 8 && "does not support size > 8");
5895 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005896 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005897 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5898 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005899 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5900 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00005901 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005902 src, dst, "weakassign");
5903 return;
5904}
5905
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005906void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005907 CodeGen::CodeGenFunction &CGF,
5908 llvm::Value *DestPtr,
5909 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00005910 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005911 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5912 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005913 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00005914 DestPtr, SrcPtr, Size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005915 return;
5916}
5917
Fariborz Jahanian06292952009-02-16 22:52:32 +00005918/// EmitObjCWeakRead - Code gen for loading value of a __weak
5919/// object: objc_read_weak (id *src)
5920///
5921llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005922 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005923 llvm::Value *AddrWeakObj) {
Eli Friedmana374b682009-03-07 03:57:15 +00005924 const llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005925 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5926 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00005927 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005928 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00005929 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00005930 return read_weak;
5931}
5932
5933/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
5934/// objc_assign_weak (id src, id *dst)
5935///
5936void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005937 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005938 const llvm::Type * SrcTy = src->getType();
5939 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005940 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005941 assert(Size <= 8 && "does not support size > 8");
5942 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5943 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005944 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5945 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005946 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5947 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00005948 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005949 src, dst, "weakassign");
5950 return;
5951}
5952
5953/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
5954/// objc_assign_global (id src, id *dst)
5955///
5956void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00005957 llvm::Value *src, llvm::Value *dst,
5958 bool threadlocal) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005959 const llvm::Type * SrcTy = src->getType();
5960 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005961 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005962 assert(Size <= 8 && "does not support size > 8");
5963 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5964 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005965 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5966 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005967 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5968 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00005969 if (!threadlocal)
5970 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
5971 src, dst, "globalassign");
5972 else
5973 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
5974 src, dst, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00005975 return;
5976}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005977
John McCallc20acd32010-07-21 00:41:47 +00005978namespace {
John McCallcda666c2010-07-21 07:22:38 +00005979 struct CallSyncExit : EHScopeStack::Cleanup {
John McCallc20acd32010-07-21 00:41:47 +00005980 llvm::Value *SyncExitFn;
5981 llvm::Value *SyncArg;
5982 CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg)
5983 : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
5984
5985 void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
5986 CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow();
5987 }
5988 };
5989}
5990
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005991void
John McCallbd309292010-07-06 01:34:17 +00005992CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
5993 const ObjCAtSynchronizedStmt &S) {
5994 // Evaluate the lock operand. This should dominate the cleanup.
5995 llvm::Value *SyncArg = CGF.EmitScalarExpr(S.getSynchExpr());
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00005996
John McCallbd309292010-07-06 01:34:17 +00005997 // Acquire the lock.
5998 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
5999 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
6000 ->setDoesNotThrow();
6001
6002 // Register an all-paths cleanup to release the lock.
John McCallcda666c2010-07-21 07:22:38 +00006003 CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup,
6004 ObjCTypes.getSyncExitFn(),
6005 SyncArg);
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006006
John McCallbd309292010-07-06 01:34:17 +00006007 // Emit the body of the statement.
6008 CGF.EmitStmt(S.getSynchBody());
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006009
John McCallbd309292010-07-06 01:34:17 +00006010 // Pop the lock-release cleanup.
6011 CGF.PopCleanupBlock();
6012}
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006013
John McCallbd309292010-07-06 01:34:17 +00006014namespace {
6015 struct CatchHandler {
6016 const VarDecl *Variable;
6017 const Stmt *Body;
6018 llvm::BasicBlock *Block;
6019 llvm::Value *TypeInfo;
6020 };
John McCall5c08ab92010-07-13 22:12:14 +00006021
John McCallcda666c2010-07-21 07:22:38 +00006022 struct CallObjCEndCatch : EHScopeStack::Cleanup {
John McCall5c08ab92010-07-13 22:12:14 +00006023 CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) :
6024 MightThrow(MightThrow), Fn(Fn) {}
6025 bool MightThrow;
6026 llvm::Value *Fn;
6027
6028 void Emit(CodeGenFunction &CGF, bool IsForEH) {
6029 if (!MightThrow) {
6030 CGF.Builder.CreateCall(Fn)->setDoesNotThrow();
6031 return;
6032 }
6033
6034 CGF.EmitCallOrInvoke(Fn, 0, 0);
6035 }
6036 };
John McCallbd309292010-07-06 01:34:17 +00006037}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006038
John McCall2ca705e2010-07-24 00:37:23 +00006039llvm::Constant *
6040CGObjCNonFragileABIMac::GetEHType(QualType T) {
6041 // There's a particular fixed type info for 'id'.
6042 if (T->isObjCIdType() ||
6043 T->isObjCQualifiedIdType()) {
6044 llvm::Constant *IDEHType =
6045 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6046 if (!IDEHType)
6047 IDEHType =
6048 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6049 false,
6050 llvm::GlobalValue::ExternalLinkage,
6051 0, "OBJC_EHTYPE_id");
6052 return IDEHType;
6053 }
6054
6055 // All other types should be Objective-C interface pointer types.
6056 const ObjCObjectPointerType *PT =
6057 T->getAs<ObjCObjectPointerType>();
6058 assert(PT && "Invalid @catch type.");
6059 const ObjCInterfaceType *IT = PT->getInterfaceType();
6060 assert(IT && "Invalid @catch type.");
6061 return GetInterfaceEHType(IT->getDecl(), false);
6062}
6063
John McCallbd309292010-07-06 01:34:17 +00006064void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6065 const ObjCAtTryStmt &S) {
6066 // Jump destination for falling out of catch bodies.
6067 CodeGenFunction::JumpDest Cont;
6068 if (S.getNumCatchStmts())
6069 Cont = CGF.getJumpDestInCurrentScope("eh.cont");
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006070
John McCallbd309292010-07-06 01:34:17 +00006071 CodeGenFunction::FinallyInfo FinallyInfo;
6072 if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
6073 FinallyInfo = CGF.EnterFinallyBlock(Finally->getFinallyBody(),
6074 ObjCTypes.getObjCBeginCatchFn(),
6075 ObjCTypes.getObjCEndCatchFn(),
6076 ObjCTypes.getExceptionRethrowFn());
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006077
John McCallbd309292010-07-06 01:34:17 +00006078 llvm::SmallVector<CatchHandler, 8> Handlers;
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006079
John McCallbd309292010-07-06 01:34:17 +00006080 // Enter the catch, if there is one.
6081 if (S.getNumCatchStmts()) {
6082 for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
6083 const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I);
Douglas Gregor46a572b2010-04-26 16:46:50 +00006084 const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006085
John McCallbd309292010-07-06 01:34:17 +00006086 Handlers.push_back(CatchHandler());
6087 CatchHandler &Handler = Handlers.back();
6088 Handler.Variable = CatchDecl;
6089 Handler.Body = CatchStmt->getCatchBody();
6090 Handler.Block = CGF.createBasicBlock("catch");
6091
6092 // @catch(...) always matches.
Douglas Gregor96c79492010-04-23 22:50:49 +00006093 if (!CatchDecl) {
John McCallbd309292010-07-06 01:34:17 +00006094 Handler.TypeInfo = 0; // catch-all
6095 // Don't consider any other catches.
Douglas Gregor96c79492010-04-23 22:50:49 +00006096 break;
6097 }
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006098
John McCall2ca705e2010-07-24 00:37:23 +00006099 Handler.TypeInfo = GetEHType(CatchDecl->getType());
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006100 }
John McCallbd309292010-07-06 01:34:17 +00006101
6102 EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
6103 for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
6104 Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block);
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006105 }
John McCallbd309292010-07-06 01:34:17 +00006106
6107 // Emit the try body.
6108 CGF.EmitStmt(S.getTryBody());
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006109
John McCallbd309292010-07-06 01:34:17 +00006110 // Leave the try.
6111 if (S.getNumCatchStmts())
6112 CGF.EHStack.popCatch();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006113
John McCallbd309292010-07-06 01:34:17 +00006114 // Remember where we were.
6115 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006116
John McCallbd309292010-07-06 01:34:17 +00006117 // Emit the handlers.
6118 for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
6119 CatchHandler &Handler = Handlers[I];
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006120
John McCallbd309292010-07-06 01:34:17 +00006121 CGF.EmitBlock(Handler.Block);
6122 llvm::Value *RawExn = CGF.Builder.CreateLoad(CGF.getExceptionSlot());
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006123
John McCallbd309292010-07-06 01:34:17 +00006124 // Enter the catch.
6125 llvm::CallInst *Exn =
6126 CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), RawExn,
6127 "exn.adjusted");
6128 Exn->setDoesNotThrow();
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006129
John McCallbd309292010-07-06 01:34:17 +00006130 // Add a cleanup to leave the catch.
John McCall5c08ab92010-07-13 22:12:14 +00006131 bool EndCatchMightThrow = (Handler.Variable == 0);
John McCallcda666c2010-07-21 07:22:38 +00006132 CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup,
6133 EndCatchMightThrow,
6134 ObjCTypes.getObjCEndCatchFn());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006135
John McCallbd309292010-07-06 01:34:17 +00006136 // Bind the catch parameter if it exists.
6137 if (const VarDecl *CatchParam = Handler.Variable) {
6138 const llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType());
6139 llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType);
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006140
John McCallbd309292010-07-06 01:34:17 +00006141 CGF.EmitLocalBlockVarDecl(*CatchParam);
6142 CGF.Builder.CreateStore(CastExn, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006143 }
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006144
John McCallbd309292010-07-06 01:34:17 +00006145 CGF.ObjCEHValueStack.push_back(Exn);
6146 CGF.EmitStmt(Handler.Body);
6147 CGF.ObjCEHValueStack.pop_back();
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006148
John McCallbd309292010-07-06 01:34:17 +00006149 // Leave the earlier cleanup.
6150 CGF.PopCleanupBlock();
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006151
John McCallbd309292010-07-06 01:34:17 +00006152 CGF.EmitBranchThroughCleanup(Cont);
6153 }
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006154
John McCallbd309292010-07-06 01:34:17 +00006155 // Go back to the try-statement fallthrough.
6156 CGF.Builder.restoreIP(SavedIP);
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006157
John McCallbd309292010-07-06 01:34:17 +00006158 // Pop out of the normal cleanup on the finally.
6159 if (S.getFinallyStmt())
6160 CGF.ExitFinallyBlock(FinallyInfo);
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006161
John McCallad5d61e2010-07-23 21:56:41 +00006162 if (Cont.isValid())
6163 CGF.EmitBlock(Cont.getBlock());
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006164}
6165
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006166/// EmitThrowStmt - Generate code for a throw statement.
6167void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6168 const ObjCAtThrowStmt &S) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006169 llvm::Value *Exception;
Fariborz Jahanian3336de12010-05-28 17:34:43 +00006170 llvm::Constant *FunctionThrowOrRethrow;
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006171 if (const Expr *ThrowExpr = S.getThrowExpr()) {
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006172 Exception = CGF.EmitScalarExpr(ThrowExpr);
Fariborz Jahanian3336de12010-05-28 17:34:43 +00006173 FunctionThrowOrRethrow = ObjCTypes.getExceptionThrowFn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006174 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006175 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006176 "Unexpected rethrow outside @catch block.");
6177 Exception = CGF.ObjCEHValueStack.back();
Fariborz Jahanian3336de12010-05-28 17:34:43 +00006178 FunctionThrowOrRethrow = ObjCTypes.getExceptionRethrowFn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006179 }
6180
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006181 llvm::Value *ExceptionAsObject =
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006182 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
6183 llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
6184 if (InvokeDest) {
Fariborz Jahanian3336de12010-05-28 17:34:43 +00006185 CGF.Builder.CreateInvoke(FunctionThrowOrRethrow,
John McCallbd309292010-07-06 01:34:17 +00006186 CGF.getUnreachableBlock(), InvokeDest,
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006187 &ExceptionAsObject, &ExceptionAsObject + 1);
John McCallbd309292010-07-06 01:34:17 +00006188 } else {
6189 CGF.Builder.CreateCall(FunctionThrowOrRethrow, ExceptionAsObject)
6190 ->setDoesNotReturn();
6191 CGF.Builder.CreateUnreachable();
6192 }
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00006193
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006194 // Clear the insertion point to indicate we are in unreachable code.
6195 CGF.Builder.ClearInsertionPoint();
6196}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006197
John McCall2ca705e2010-07-24 00:37:23 +00006198llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006199CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006200 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006201 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006202
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006203 // If we don't need a definition, return the entry if found or check
6204 // if we use an external reference.
6205 if (!ForDefinition) {
6206 if (Entry)
6207 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00006208
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006209 // If this type (or a super class) has the __objc_exception__
6210 // attribute, emit an external reference.
Douglas Gregor78bd61f2009-06-18 16:11:24 +00006211 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006212 return Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006213 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006214 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006215 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006216 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006217 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006218 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006219
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006220 // Otherwise we need to either make a new entry or fill in the
6221 // initializer.
6222 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar15894b72009-04-07 05:48:37 +00006223 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006224 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006225 llvm::GlobalVariable *VTableGV =
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006226 CGM.getModule().getGlobalVariable(VTableName);
6227 if (!VTableGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006228 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6229 false,
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006230 llvm::GlobalValue::ExternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006231 0, VTableName);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006232
Chris Lattner5e016ae2010-06-27 07:15:29 +00006233 llvm::Value *VTableIdx =
6234 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006235
6236 std::vector<llvm::Constant*> Values(3);
Owen Andersonade90fd2009-07-29 18:54:39 +00006237 Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006238 Values[1] = GetClassName(ID->getIdentifier());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006239 Values[2] = GetClassGlobal(ClassName);
Owen Anderson170229f2009-07-14 23:10:40 +00006240 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00006241 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006242
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006243 if (Entry) {
6244 Entry->setInitializer(Init);
6245 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00006246 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006247 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006248 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006249 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006250 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006251 }
6252
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00006253 if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden)
Daniel Dunbar15894b72009-04-07 05:48:37 +00006254 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar710cb202010-04-25 20:39:32 +00006255 Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6256 ObjCTypes.EHTypeTy));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006257
6258 if (ForDefinition) {
6259 Entry->setSection("__DATA,__objc_const");
6260 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6261 } else {
6262 Entry->setSection("__DATA,__datacoal_nt,coalesced");
6263 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006264
6265 return Entry;
6266}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006267
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006268/* *** */
6269
Daniel Dunbarb036db82008-08-13 03:21:16 +00006270CodeGen::CGObjCRuntime *
6271CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
Daniel Dunbar303e2c22008-08-11 02:45:11 +00006272 return new CGObjCMac(CGM);
6273}
Fariborz Jahanian279eda62009-01-21 22:04:16 +00006274
6275CodeGen::CGObjCRuntime *
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00006276CodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00006277 return new CGObjCNonFragileABIMac(CGM);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00006278}