blob: d9d79e1587526e0b1185bdeee920c3c319fbb282 [file] [log] [blame]
Daniel Dunbarc17a4d32008-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 Dunbarf77ac862008-08-11 21:35:06 +000015
Daniel Dunbar198bcb42010-03-31 01:09:11 +000016#include "CGRecordLayout.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000017#include "CodeGenModule.h"
Daniel Dunbarb7ec2462008-08-16 03:19:19 +000018#include "CodeGenFunction.h"
John McCallf1549f62010-07-06 01:34:17 +000019#include "CGException.h"
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000020#include "clang/AST/ASTContext.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000021#include "clang/AST/Decl.h"
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000022#include "clang/AST/DeclObjC.h"
Anders Carlsson19cc4ab2009-07-18 19:43:29 +000023#include "clang/AST/RecordLayout.h"
Chris Lattner16f00492009-04-26 01:32:48 +000024#include "clang/AST/StmtObjC.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000025#include "clang/Basic/LangOptions.h"
Chandler Carruth06057ce2010-06-15 23:19:56 +000026#include "clang/Frontend/CodeGenOptions.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000027
John McCall87bb5822010-07-31 23:20:56 +000028#include "llvm/InlineAsm.h"
29#include "llvm/IntrinsicInst.h"
Owen Anderson69243822009-07-13 04:10:07 +000030#include "llvm/LLVMContext.h"
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000031#include "llvm/Module.h"
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +000032#include "llvm/ADT/DenseSet.h"
Daniel Dunbar33063492009-09-07 00:20:42 +000033#include "llvm/ADT/SetVector.h"
34#include "llvm/ADT/SmallString.h"
Fariborz Jahanian191dcd72009-12-12 21:26:21 +000035#include "llvm/ADT/SmallPtrSet.h"
John McCall8e3f8612010-07-13 22:12:14 +000036#include "llvm/Support/CallSite.h"
Daniel Dunbar33063492009-09-07 00:20:42 +000037#include "llvm/Support/raw_ostream.h"
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +000038#include "llvm/Target/TargetData.h"
Torok Edwinf42e4a62009-08-24 13:25:12 +000039#include <cstdio>
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000040
41using namespace clang;
Daniel Dunbar46f45b92008-09-09 01:06:48 +000042using namespace CodeGen;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000043
Daniel Dunbar97776872009-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 Dunbar1d7e5392009-05-03 08:55:17 +000048static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
49 const ObjCInterfaceDecl *OID,
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +000050 const ObjCImplementationDecl *ID,
Daniel Dunbar1d7e5392009-05-03 08:55:17 +000051 const ObjCIvarDecl *Ivar) {
Daniel Dunbare83be122010-04-02 21:14:02 +000052 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar532d4da2009-05-03 13:15:50 +000053
Daniel Dunbar61ac1d22010-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 Dunbar3a2c80f2010-04-02 15:43:29 +000057
Daniel Dunbar532d4da2009-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 Dunbar6bff2512009-08-03 17:06:42 +000060 const ASTRecordLayout *RL;
Daniel Dunbar532d4da2009-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 Dunbare83be122010-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 Dunbar532d4da2009-05-03 13:15:50 +000081 return RL->getFieldOffset(Index);
Daniel Dunbar1d7e5392009-05-03 08:55:17 +000082}
83
84uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
85 const ObjCInterfaceDecl *OID,
86 const ObjCIvarDecl *Ivar) {
Daniel Dunbar9f89f2b2009-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 Dunbar97776872009-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 Dunbar1d7e5392009-05-03 08:55:17 +0000102 // Compute (type*) ( (char *) BaseValue + Offset)
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +0000103 const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
Daniel Dunbar1d7e5392009-05-03 08:55:17 +0000104 QualType IvarTy = Ivar->getType();
105 const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
Daniel Dunbar97776872009-04-22 07:32:20 +0000106 llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr);
Daniel Dunbar97776872009-04-22 07:32:20 +0000107 V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
Owen Anderson96e0fc72009-07-29 22:16:19 +0000108 V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000109
John McCall0953e762009-09-24 19:53:00 +0000110 Qualifiers Quals = CGF.MakeQualifiers(IvarTy);
111 Quals.addCVRQualifiers(CVRQualifiers);
112
Daniel Dunbar56229f52010-04-05 16:20:33 +0000113 if (!Ivar->isBitField())
114 return LValue::MakeAddr(V, Quals);
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +0000115
Daniel Dunbar56229f52010-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 Dunbar97776872009-04-22 07:32:20 +0000123
Daniel Dunbarf0fe5bc2010-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 Dunbarf0fe5bc2010-04-05 21:36:35 +0000130
Daniel Dunbarab970f92010-04-13 20:58:55 +0000131 // We always construct a single, possibly unaligned, access for this case.
Daniel Dunbar2df25692010-04-15 05:09:32 +0000132 CGBitFieldInfo::AccessInfo AI;
Daniel Dunbarab970f92010-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 Dunbar2df25692010-04-15 05:09:32 +0000141 CGBitFieldInfo *Info =
142 new (CGF.CGM.getContext()) CGBitFieldInfo(BitFieldSize, 1, &AI,
143 IvarTy->isSignedIntegerType());
144
Daniel Dunbar56229f52010-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 Dunbarefbf4872010-04-06 01:07:44 +0000147 return LValue::MakeBitfield(V, *Info, Quals.getCVRQualifiers());
Daniel Dunbar97776872009-04-22 07:32:20 +0000148}
149
150///
151
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000152namespace {
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000153
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000154typedef std::vector<llvm::Constant*> ConstantVector;
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000155
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +0000158
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000159class ObjCCommonTypesHelper {
Owen Andersona1cf15f2009-07-14 23:10:40 +0000160protected:
161 llvm::LLVMContext &VMContext;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000162
Fariborz Jahaniand0f8a8d2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000170 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
171 Params, true),
172 "objc_msgSend");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000173 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000174
Fariborz Jahaniand0f8a8d2009-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 Anderson0032b272009-08-13 21:57:51 +0000181 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000182 Params, true),
183 "objc_msgSend_stret");
184
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000185 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000186
Fariborz Jahaniand0f8a8d2009-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 Anderson0032b272009-08-13 21:57:51 +0000194 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
195 llvm::Type::getDoubleTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000196 Params,
197 true),
198 "objc_msgSend_fpret");
199
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000200 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000201
Fariborz Jahaniand0f8a8d2009-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 Anderson96e0fc72009-07-29 22:16:19 +0000208 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000209 Params, true),
210 SuperName);
211 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000212
Fariborz Jahaniand0f8a8d2009-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 Anderson96e0fc72009-07-29 22:16:19 +0000219 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000220 Params, true),
221 SuperName);
222 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000223
Fariborz Jahaniand0f8a8d2009-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 Andersona1cf15f2009-07-14 23:10:40 +0000231 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000232 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000233 Params, true),
234 "objc_msgSendSuper_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000235 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000236
Fariborz Jahaniand0f8a8d2009-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 Andersona1cf15f2009-07-14 23:10:40 +0000244 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000245 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000246 Params, true),
247 "objc_msgSendSuper2_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000248 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000249
Fariborz Jahaniand0f8a8d2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000254
Fariborz Jahaniand0f8a8d2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000259
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000260protected:
261 CodeGen::CodeGenModule &CGM;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000262
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000263public:
Fariborz Jahanian0a855d02009-03-23 19:10:40 +0000264 const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000265 const llvm::Type *Int8PtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000266
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000267 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
268 const llvm::Type *ObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000269
Fariborz Jahanian6d657c42008-11-18 20:18:11 +0000270 /// PtrObjectPtrTy - LLVM type for id *
271 const llvm::Type *PtrObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000272
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000273 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000274 const llvm::Type *SelectorPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000275 /// ProtocolPtrTy - LLVM type for external protocol handles
276 /// (typeof(Protocol))
277 const llvm::Type *ExternalProtocolPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000278
Daniel Dunbar19cd87e2008-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 Dunbar6bff2512009-08-03 17:06:42 +0000283
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000284 /// SuperTy - LLVM type for struct objc_super.
285 const llvm::StructType *SuperTy;
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000286 /// SuperPtrTy - LLVM type for struct objc_super *.
287 const llvm::Type *SuperPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000288
Fariborz Jahanian30bc5712009-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 Dunbar6bff2512009-08-03 17:06:42 +0000292
Fariborz Jahanian30bc5712009-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 Dunbar6bff2512009-08-03 17:06:42 +0000298
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000299 // MethodTy - LLVM type for struct objc_method.
300 const llvm::StructType *MethodTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000301
Fariborz Jahaniand55b6fc2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000306
Chris Lattner72db6c32009-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 McCallead608a2010-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 Lattner72db6c32009-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 McCall04a67a62010-02-05 21:31:56 +0000319 Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000320 FunctionType::ExtInfo()),
321 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000322 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
323 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000324
Chris Lattner72db6c32009-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 McCallead608a2010-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 Lattner72db6c32009-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 McCall04a67a62010-02-05 21:31:56 +0000339 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000340 FunctionType::ExtInfo()),
341 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000342 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
343 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000344
Fariborz Jahanian6cc59062010-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 Lattner72db6c32009-04-22 02:44:54 +0000363 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000364 CodeGen::CodeGenTypes &Types = CGM.getTypes();
365 ASTContext &Ctx = CGM.getContext();
Chris Lattner72db6c32009-04-22 02:44:54 +0000366 // void objc_enumerationMutation (id)
John McCallead608a2010-02-26 00:48:12 +0000367 llvm::SmallVector<CanQualType,1> Params;
368 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000369 const llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000370 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000371 FunctionType::ExtInfo()),
372 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000373 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
374 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000375
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000376 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattner72db6c32009-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 Dunbar6bff2512009-08-03 17:06:42 +0000381 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000382 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000383 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000384 }
385
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000386 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner96508e12009-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 Anderson96e0fc72009-07-29 22:16:19 +0000392 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner96508e12009-04-17 22:12:36 +0000393 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
394 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000395
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000396 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattnerbbccd612009-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 Andersona1cf15f2009-07-14 23:10:40 +0000401 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000402 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000403 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
404 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000405
Fariborz Jahanian021a7a62010-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 Jahaniandb286862009-01-22 00:37:21 +0000416 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000417 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +0000418 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnerbbccd612009-04-22 02:38:11 +0000419 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
420 Args.push_back(ObjectPtrTy->getPointerTo());
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +0000421 Args.push_back(LongTy);
Owen Andersona1cf15f2009-07-14 23:10:40 +0000422 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000423 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000424 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
425 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000426
Fariborz Jahanian082b02e2009-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 Anderson96e0fc72009-07-29 22:16:19 +0000433 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000434 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
435 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000436
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000437 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000438 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000439 // id objc_assign_strongCast(id, id *)
Chris Lattnerbbccd612009-04-22 02:38:11 +0000440 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
441 Args.push_back(ObjectPtrTy->getPointerTo());
Owen Andersona1cf15f2009-07-14 23:10:40 +0000442 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000443 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000444 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
445 }
Anders Carlssonf57c5b22009-02-16 22:59:18 +0000446
447 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattnerbbccd612009-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 Anderson0032b272009-08-13 21:57:51 +0000452 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000453 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
454 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000455
Fariborz Jahanian69677ea2010-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 Dunbar1c566672009-02-24 01:43:46 +0000465 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerb02e53b2009-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 Anderson0032b272009-08-13 21:57:51 +0000470 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000471 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
472 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000473
Daniel Dunbar1c566672009-02-24 01:43:46 +0000474 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattnerbbccd612009-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 Anderson0032b272009-08-13 21:57:51 +0000479 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000480 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
481 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000482
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000483 llvm::Constant *getSendFn(bool IsSuper) const {
484 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
485 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000486
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000487 llvm::Constant *getSendFn2(bool IsSuper) const {
488 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
489 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000490
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000491 llvm::Constant *getSendStretFn(bool IsSuper) const {
492 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
493 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000494
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000495 llvm::Constant *getSendStretFn2(bool IsSuper) const {
496 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
497 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000498
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000499 llvm::Constant *getSendFpretFn(bool IsSuper) const {
500 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
501 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000502
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000503 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
504 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
505 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000506
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000507 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
508 ~ObjCCommonTypesHelper(){}
509};
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000510
Fariborz Jahanianee0af742009-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 Jahanianee0af742009-01-21 22:04:16 +0000514public:
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000515 /// SymtabTy - LLVM type for struct objc_symtab.
516 const llvm::StructType *SymtabTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000517 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
518 const llvm::Type *SymtabPtrTy;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000519 /// ModuleTy - LLVM type for struct objc_module.
520 const llvm::StructType *ModuleTy;
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000521
Daniel Dunbar6efc0c52008-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 Dunbar6efc0c52008-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 Dunbar86e253a2008-08-22 20:34:54 +0000545 /// CategoryTy - LLVM type for struct objc_category.
546 const llvm::StructType *CategoryTy;
Daniel Dunbar27f9d772008-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 Dunbar27f9d772008-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 Dunbar27f9d772008-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 Dunbar6bff2512009-08-03 17:06:42 +0000565
Anders Carlsson124526b2008-09-09 10:10:21 +0000566 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
567 const llvm::Type *ExceptionDataTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000568
Anders Carlsson124526b2008-09-09 10:10:21 +0000569 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000570 llvm::Constant *getExceptionTryEnterFn() {
571 std::vector<const llvm::Type*> Params;
Owen Anderson96e0fc72009-07-29 22:16:19 +0000572 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
Owen Andersona1cf15f2009-07-14 23:10:40 +0000573 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000574 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000575 Params, false),
576 "objc_exception_try_enter");
Chris Lattner34b02a12009-04-22 02:26:14 +0000577 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000578
579 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000580 llvm::Constant *getExceptionTryExitFn() {
581 std::vector<const llvm::Type*> Params;
Owen Anderson96e0fc72009-07-29 22:16:19 +0000582 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
Owen Andersona1cf15f2009-07-14 23:10:40 +0000583 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000584 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000585 Params, false),
586 "objc_exception_try_exit");
Chris Lattner34b02a12009-04-22 02:26:14 +0000587 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000588
589 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000590 llvm::Constant *getExceptionExtractFn() {
591 std::vector<const llvm::Type*> Params;
Owen Anderson96e0fc72009-07-29 22:16:19 +0000592 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
593 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner34b02a12009-04-22 02:26:14 +0000594 Params, false),
595 "objc_exception_extract");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000596
Chris Lattner34b02a12009-04-22 02:26:14 +0000597 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000598
Anders Carlsson124526b2008-09-09 10:10:21 +0000599 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattner34b02a12009-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 Dunbar6bff2512009-08-03 17:06:42 +0000604 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000605 llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000606 Params, false),
607 "objc_exception_match");
608
Chris Lattner34b02a12009-04-22 02:26:14 +0000609 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000610
Anders Carlsson124526b2008-09-09 10:10:21 +0000611 /// SetJmpFn - LLVM _setjmp function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000612 llvm::Constant *getSetJmpFn() {
613 std::vector<const llvm::Type*> Params;
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +0000614 Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
Chris Lattner34b02a12009-04-22 02:26:14 +0000615 return
Owen Anderson0032b272009-08-13 21:57:51 +0000616 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Chris Lattner34b02a12009-04-22 02:26:14 +0000617 Params, false),
618 "_setjmp");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000619
Chris Lattner34b02a12009-04-22 02:26:14 +0000620 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000621
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000622public:
623 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000624 ~ObjCTypesHelper() {}
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000625};
626
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000627/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000628/// modern abi
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000629class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000630public:
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000631
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000632 // MethodListnfABITy - LLVM for struct _method_list_t
633 const llvm::StructType *MethodListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000634
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000635 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
636 const llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000637
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000638 // ProtocolnfABITy = LLVM for struct _protocol_t
639 const llvm::StructType *ProtocolnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000640
Daniel Dunbar948e2582009-02-15 07:36:20 +0000641 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
642 const llvm::Type *ProtocolnfABIPtrTy;
643
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000644 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
645 const llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000646
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000647 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
648 const llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000649
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000650 // ClassnfABITy - LLVM for struct _class_t
651 const llvm::StructType *ClassnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000652
Fariborz Jahanianaa23b572009-01-23 23:53:38 +0000653 // ClassnfABIPtrTy - LLVM for struct _class_t*
654 const llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000655
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000656 // IvarnfABITy - LLVM for struct _ivar_t
657 const llvm::StructType *IvarnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000658
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000659 // IvarListnfABITy - LLVM for struct _ivar_list_t
660 const llvm::StructType *IvarListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000661
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000662 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
663 const llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000664
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000665 // ClassRonfABITy - LLVM for struct _class_ro_t
666 const llvm::StructType *ClassRonfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000667
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000668 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
669 const llvm::Type *ImpnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000670
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000671 // CategorynfABITy - LLVM for struct _category_t
672 const llvm::StructType *CategorynfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000673
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000674 // New types for nonfragile abi messaging.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000675
Fariborz Jahanian2e4672b2009-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 Jahanian83a8a752009-02-04 20:42:28 +0000682 // MessageRefCTy - clang type for struct _message_ref_t
683 QualType MessageRefCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000684
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000685 // MessageRefPtrTy - LLVM for struct _message_ref_t*
686 const llvm::Type *MessageRefPtrTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000687 // MessageRefCPtrTy - clang type for struct _message_ref_t*
688 QualType MessageRefCPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000689
Fariborz Jahanianef163782009-02-05 01:13:09 +0000690 // MessengerTy - Type of the messenger (shown as IMP above)
691 const llvm::FunctionType *MessengerTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000692
Fariborz Jahanian2e4672b2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000699
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000700 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
701 const llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000702
Chris Lattner1c02f862009-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 Anderson96e0fc72009-07-29 22:16:19 +0000708 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner1c02f862009-04-22 02:53:24 +0000709 Params, true),
710 "objc_msgSend_fixup");
711 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000712
Chris Lattner1c02f862009-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 Anderson96e0fc72009-07-29 22:16:19 +0000718 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner1c02f862009-04-22 02:53:24 +0000719 Params, true),
720 "objc_msgSend_fpret_fixup");
721 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000722
Chris Lattner1c02f862009-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 Anderson96e0fc72009-07-29 22:16:19 +0000728 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner1c02f862009-04-22 02:53:24 +0000729 Params, true),
730 "objc_msgSend_stret_fixup");
731 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000732
Chris Lattner1c02f862009-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 Anderson96e0fc72009-07-29 22:16:19 +0000738 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner1c02f862009-04-22 02:53:24 +0000739 Params, true),
740 "objc_msgSendId_fixup");
741 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000742
Chris Lattner1c02f862009-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 Anderson96e0fc72009-07-29 22:16:19 +0000748 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner1c02f862009-04-22 02:53:24 +0000749 Params, true),
750 "objc_msgSendId_stret_fixup");
751 }
752 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000753 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner1c02f862009-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 Anderson96e0fc72009-07-29 22:16:19 +0000758 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner1c02f862009-04-22 02:53:24 +0000759 Params, true),
760 "objc_msgSendSuper2_fixup");
761 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000762
Chris Lattner1c02f862009-04-22 02:53:24 +0000763 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000764 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner1c02f862009-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 Anderson96e0fc72009-07-29 22:16:19 +0000769 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner1c02f862009-04-22 02:53:24 +0000770 Params, true),
771 "objc_msgSendSuper2_stret_fixup");
772 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000773
774
775
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000776 /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C
777 /// exception personality function.
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000778 llvm::Value *getEHPersonalityPtr() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000779 llvm::Constant *Personality =
Owen Anderson0032b272009-08-13 21:57:51 +0000780 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000781 true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000782 "__objc_personality_v0");
Owen Anderson3c4972d2009-07-29 18:54:39 +0000783 return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy);
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000784 }
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000785
Chris Lattner8a569112009-04-22 02:15:23 +0000786 llvm::Constant *getUnwindResumeOrRethrowFn() {
787 std::vector<const llvm::Type*> Params;
788 Params.push_back(Int8PtrTy);
Owen Andersona1cf15f2009-07-14 23:10:40 +0000789 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000790 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000791 Params, false),
Daniel Dunbarb2987d12010-02-10 18:49:11 +0000792 (CGM.getLangOptions().SjLjExceptions ? "_Unwind_SjLj_Resume" :
793 "_Unwind_Resume_or_Rethrow"));
Chris Lattner8a569112009-04-22 02:15:23 +0000794 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000795
Chris Lattner8a569112009-04-22 02:15:23 +0000796 llvm::Constant *getObjCEndCatchFn() {
Owen Anderson0032b272009-08-13 21:57:51 +0000797 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Chris Lattnerb59761b2009-07-01 04:13:52 +0000798 false),
Chris Lattner8a569112009-04-22 02:15:23 +0000799 "objc_end_catch");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000800
Chris Lattner8a569112009-04-22 02:15:23 +0000801 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000802
Chris Lattner8a569112009-04-22 02:15:23 +0000803 llvm::Constant *getObjCBeginCatchFn() {
804 std::vector<const llvm::Type*> Params;
805 Params.push_back(Int8PtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000806 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
Chris Lattner8a569112009-04-22 02:15:23 +0000807 Params, false),
808 "objc_begin_catch");
809 }
Daniel Dunbare588b992009-03-01 04:46:24 +0000810
811 const llvm::StructType *EHTypeTy;
812 const llvm::Type *EHTypePtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000813
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000814 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
815 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000816};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000817
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000818class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000819public:
820 // FIXME - accessibility
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000821 class GC_IVAR {
Fariborz Jahanian820e0202009-03-11 00:07:04 +0000822 public:
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000823 unsigned ivar_bytepos;
824 unsigned ivar_size;
825 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000826 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar0941b492009-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 Jahaniana5a10c32009-03-10 16:22:08 +0000832 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000833
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000834 class SKIP_SCAN {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000835 public:
836 unsigned skip;
837 unsigned scan;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000838 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000839 : skip(_skip), scan(_scan) {}
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000840 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000841
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000842protected:
843 CodeGen::CodeGenModule &CGM;
Owen Anderson69243822009-07-13 04:10:07 +0000844 llvm::LLVMContext &VMContext;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000845 // FIXME! May not be needing this after all.
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000846 unsigned ObjCABI;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000847
Fariborz Jahanian9397e1d2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000851
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000852 /// LazySymbols - Symbols to generate a lazy reference for. See
853 /// DefinedSymbols and FinishModule().
Daniel Dunbar33063492009-09-07 00:20:42 +0000854 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000855
Daniel Dunbar242d4dc2008-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 Dunbar33063492009-09-07 00:20:42 +0000860 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000861
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000862 /// ClassNames - uniqued class names.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000863 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000864
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000865 /// MethodVarNames - uniqued method variable names.
866 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000867
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +0000868 /// DefinedCategoryNames - list of category names in form Class_Category.
869 llvm::SetVector<std::string> DefinedCategoryNames;
870
Daniel Dunbar6efc0c52008-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 Dunbar6bff2512009-08-03 17:06:42 +0000874
Daniel Dunbarc45ef602008-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 Dunbar6bff2512009-08-03 17:06:42 +0000878
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000879 /// PropertyNames - uniqued method variable names.
880 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000881
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000882 /// ClassReferences - uniqued class references.
883 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000884
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000885 /// SelectorReferences - uniqued selector references.
886 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000887
Daniel Dunbar6efc0c52008-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 Dunbar6bff2512009-08-03 17:06:42 +0000892
Daniel Dunbar0c0e7a62008-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 Dunbar6bff2512009-08-03 17:06:42 +0000896
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000897 /// DefinedClasses - List of defined classes.
898 std::vector<llvm::GlobalValue*> DefinedClasses;
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000899
900 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
901 std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000902
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000903 /// DefinedCategories - List of defined categories.
904 std::vector<llvm::GlobalValue*> DefinedCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000905
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000906 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
907 std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000908
Fariborz Jahanian56210f72009-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 Dunbarc575ce72009-10-19 01:21:19 +0000913 llvm::SmallVectorImpl<char> &NameOut);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000914
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000920
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000923
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000924 // FIXME: This is a horrible name.
925 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +0000926 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000927
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000931
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000935
Fariborz Jahanian058a1b72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000939
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000940 /// BuildIvarLayout - Builds ivar layout bitmap for the class
941 /// implementation for the __strong or __weak case.
942 ///
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000943 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
944 bool ForStrongLayout);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +0000945
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +0000946 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000947
Daniel Dunbard58edcb2009-05-03 14:10:34 +0000948 void BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000949 unsigned int BytePos, bool ForStrongLayout,
950 bool &HasUnion);
Daniel Dunbar5a5a8032009-05-03 21:05:10 +0000951 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000952 const llvm::StructLayout *Layout,
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000953 const RecordDecl *RD,
Chris Lattnerf1690852009-03-31 08:48:01 +0000954 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000955 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahanian81adc052009-04-24 16:17:09 +0000956 bool &HasUnion);
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000957
Fariborz Jahaniand80d81b2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000962
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000963 /// EmitPropertyList - Emit the given property list. The return
964 /// value has type PropertyListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000965 llvm::Constant *EmitPropertyList(llvm::Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000966 const Decl *Container,
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000967 const ObjCContainerDecl *OCD,
968 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000969
Fariborz Jahanian191dcd72009-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 Jahanianda320092009-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 Jahanianb21f07e2009-03-08 20:18:37 +0000981
Daniel Dunbarfd65d372009-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 Lattnerad64e022009-07-17 23:57:13 +0000987 /// global to the "llvm.used" list.
Daniel Dunbar35bd7632009-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 Dunbarc1583062009-04-14 17:42:51 +0000995 /// "llvm.used".
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000996 llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000997 llvm::Constant *Init,
998 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +0000999 unsigned Align,
1000 bool AddToUsed);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00001001
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001002 CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001003 ReturnValueSlot Return,
Fariborz Jahaniand0f8a8d2009-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 Dunbard6c93d72009-09-17 04:01:22 +00001010 const ObjCMethodDecl *OMD,
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001011 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00001012
Daniel Dunbarfce176b2010-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 Jahanianee0af742009-01-21 22:04:16 +00001017public:
Owen Anderson69243822009-07-13 04:10:07 +00001018 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
Mike Stump1eb44332009-09-09 15:08:12 +00001019 CGM(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001020
David Chisnall0d13f6f2010-01-23 02:40:42 +00001021 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001022
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001023 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
1024 const ObjCContainerDecl *CD=0);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001025
Fariborz Jahanianda320092009-01-29 19:24:30 +00001026 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001027
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00001032
Fariborz Jahanianda320092009-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 Jahanian89ecd412010-08-04 16:57:49 +00001038 virtual llvm::Constant *GCBlockLayout(CodeGen::CodeGenFunction &CGF,
1039 const llvm::SmallVectorImpl<const BlockDeclRefExpr *> &);
1040
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001041};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001042
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001043class CGObjCMac : public CGObjCCommonMac {
1044private:
1045 ObjCTypesHelper ObjCTypes;
Daniel Dunbarf77ac862008-08-11 21:35:06 +00001046
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001047 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001048 /// information.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001049 void EmitModuleInfo();
1050
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001051 /// EmitModuleSymols - Emit module symbols, the list of defined
1052 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001053 llvm::Constant *EmitModuleSymbols();
1054
Daniel Dunbarf77ac862008-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 Dunbar6efc0c52008-08-13 03:21:16 +00001058
Daniel Dunbar27f9d772008-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 Dunbar6bff2512009-08-03 17:06:42 +00001066 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001067 const ObjCInterfaceDecl *ID);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00001068
1069 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1070 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001071
Daniel Dunbar14c80b72008-08-23 09:25:55 +00001072 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001073 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001074 QualType ResultType,
1075 Selector Sel,
Daniel Dunbar14c80b72008-08-23 09:25:55 +00001076 llvm::Value *Arg0,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001077 QualType Arg0Ty,
1078 bool IsSuper,
1079 const CallArgList &CallArgs);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00001080
Daniel Dunbar27f9d772008-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 Jahanian46b86c62009-01-28 19:12:34 +00001087 bool ForClass);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001088
Daniel Dunbarf56f1912008-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 Dunbar27f9d772008-08-21 04:36:09 +00001094 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001095 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001096 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1097 llvm::Constant *Protocols,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001098 const ConstantVector &Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001099
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001100 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001101
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001102 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001103
1104 /// EmitMethodList - Emit the method list for the given
Daniel Dunbaraf05bb92008-08-26 08:29:31 +00001105 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001106 llvm::Constant *EmitMethodList(llvm::Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001107 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001108 const ConstantVector &Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001109
1110 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001111 /// method declarations.
Daniel Dunbar6efc0c52008-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 Dunbar9c29bf52009-10-18 20:48:59 +00001121 llvm::Constant *EmitMethodDescList(llvm::Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001122 const char *Section,
1123 const ConstantVector &Methods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001124
Daniel Dunbar0c0e7a62008-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 Jahanianda320092009-01-29 19:24:30 +00001128 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-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 Jahanianda320092009-01-29 19:24:30 +00001134 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001135
Daniel Dunbar6efc0c52008-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 Dunbarae226fa2008-08-27 02:31:56 +00001140 llvm::Constant *
1141 EmitProtocolExtension(const ObjCProtocolDecl *PD,
1142 const ConstantVector &OptInstanceMethods,
1143 const ConstantVector &OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001144
1145 /// EmitProtocolList - Generate the list of referenced
1146 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001147 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Daniel Dunbardbc933702008-08-21 21:57:41 +00001148 ObjCProtocolDecl::protocol_iterator begin,
1149 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001150
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001151 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1152 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001153 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1154 bool lval=false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001155
1156public:
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001157 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001158
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001159 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001160
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001161 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001162 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001163 QualType ResultType,
1164 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001165 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001166 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001167 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001168 const ObjCMethodDecl *Method);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001169
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001170 virtual CodeGen::RValue
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001171 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001172 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001173 QualType ResultType,
1174 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001175 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001176 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001177 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001178 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001179 const CallArgList &CallArgs,
1180 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001181
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001182 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001183 const ObjCInterfaceDecl *ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001184
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001185 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1186 bool lval = false);
Fariborz Jahaniandf9ccc62009-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 McCall5a180392010-07-24 00:37:23 +00001193 virtual llvm::Constant *GetEHType(QualType T);
1194
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001195 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001196
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001197 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001198
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001199 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001200 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001201
Chris Lattner74391b42009-03-22 21:03:39 +00001202 virtual llvm::Constant *GetPropertyGetFunction();
1203 virtual llvm::Constant *GetPropertySetFunction();
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001204 virtual llvm::Constant *GetCopyStructFunction();
Chris Lattner74391b42009-03-22 21:03:39 +00001205 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001206
John McCallf1549f62010-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 Carlsson64d5d6c2008-09-09 10:04:29 +00001212 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1213 const ObjCAtThrowStmt &S);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001214 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001215 llvm::Value *AddrWeakObj);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001216 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001217 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001218 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001219 llvm::Value *src, llvm::Value *dest,
1220 bool threadlocal = false);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00001221 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001222 llvm::Value *src, llvm::Value *dest,
1223 llvm::Value *ivarOffset);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001224 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1225 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001226 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1227 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001228 llvm::Value *size);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001229
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001230 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1231 QualType ObjectTy,
1232 llvm::Value *BaseValue,
1233 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001234 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001235 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001236 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001237 const ObjCIvarDecl *Ivar);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001238};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001239
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001240class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001241private:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001242 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001243 llvm::GlobalVariable* ObjCEmptyCacheVar;
1244 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001245
Daniel Dunbar11394522009-04-18 08:51:00 +00001246 /// SuperClassReferences - uniqued super class references.
1247 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001248
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001249 /// MetaClassReferences - uniqued meta class references.
1250 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbare588b992009-03-01 04:46:24 +00001251
1252 /// EHTypeReferences - uniqued class ehtype references.
1253 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001254
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001255 /// NonLegacyDispatchMethods - List of methods for which we do *not* generate
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001256 /// legacy messaging dispatch.
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001257 llvm::DenseSet<Selector> NonLegacyDispatchMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001258
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00001259 /// DefinedMetaClasses - List of defined meta-classes.
1260 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1261
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001262 /// LegacyDispatchedSelector - Returns true if SEL is not in the list of
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001263 /// NonLegacyDispatchMethods; false otherwise.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001264 bool LegacyDispatchedSelector(Selector Sel);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001265
Fariborz Jahanianaa23b572009-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 Dunbar8158a2f2009-04-08 04:21:03 +00001269
Daniel Dunbar463b8762009-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 Dunbar6bff2512009-08-03 17:06:42 +00001276 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1277 unsigned InstanceStart,
1278 unsigned InstanceSize,
1279 const ObjCImplementationDecl *ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001280 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001281 llvm::Constant *IsAGV,
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001282 llvm::Constant *SuperClassGV,
Fariborz Jahaniancf555162009-01-31 00:59:10 +00001283 llvm::Constant *ClassRoGV,
1284 bool HiddenVisibility);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001285
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001286 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001287
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00001288 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001289
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001290 /// EmitMethodList - Emit the method list for the given
1291 /// implementation. The return value has type MethodListnfABITy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001292 llvm::Constant *EmitMethodList(llvm::Twine Name,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001293 const char *Section,
Fariborz Jahanian98abf4b2009-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 Dunbar6bff2512009-08-03 17:06:42 +00001301
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001302 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00001303 const ObjCIvarDecl *Ivar,
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00001304 unsigned long int offset);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001305
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00001310
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00001316
Fariborz Jahanianda320092009-01-29 19:24:30 +00001317 /// EmitProtocolList - Generate the list of referenced
1318 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001319 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Fariborz Jahanianda320092009-01-29 19:24:30 +00001320 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian46551122009-02-04 00:22:57 +00001321 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001322
Fariborz Jahanian46551122009-02-04 00:22:57 +00001323 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001324 ReturnValueSlot Return,
Fariborz Jahanian46551122009-02-04 00:22:57 +00001325 QualType ResultType,
1326 Selector Sel,
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00001327 llvm::Value *Receiver,
Fariborz Jahanian46551122009-02-04 00:22:57 +00001328 QualType Arg0Ty,
1329 bool IsSuper,
1330 const CallArgList &CallArgs);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00001331
1332 /// GetClassGlobal - Return the global variable for the Objective-C
1333 /// class of the given name.
Fariborz Jahanian0f902942009-04-14 18:41:56 +00001334 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001335
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001336 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar11394522009-04-18 08:51:00 +00001337 /// for the given class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001338 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00001339 const ObjCInterfaceDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001340
Daniel Dunbar11394522009-04-18 08:51:00 +00001341 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1342 /// for the given super class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001343 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1344 const ObjCInterfaceDecl *ID);
1345
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001346 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1347 /// meta-data
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001348 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001349 const ObjCInterfaceDecl *ID);
1350
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001351 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1352 /// the given ivar.
1353 ///
Daniel Dunbar5e88bea2009-04-19 00:31:15 +00001354 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001355 const ObjCInterfaceDecl *ID,
1356 const ObjCIvarDecl *Ivar);
1357
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00001358 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1359 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001360 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1361 bool lval=false);
Daniel Dunbare588b992009-03-01 04:46:24 +00001362
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001363 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbare588b992009-03-01 04:46:24 +00001364 /// interface. The return value has type EHTypePtrTy.
John McCall5a180392010-07-24 00:37:23 +00001365 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001366 bool ForDefinition);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001367
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001368 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001369 return "OBJC_METACLASS_$_";
1370 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001371
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001372 const char *getClassSymbolPrefix() const {
1373 return "OBJC_CLASS_$_";
1374 }
1375
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00001376 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001377 uint32_t &InstanceStart,
1378 uint32_t &InstanceSize);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001379
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001380 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001381 Selector GetNullarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001382 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1383 return CGM.getContext().Selectors.getSelector(0, &II);
1384 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001385
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001386 Selector GetUnarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001387 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1388 return CGM.getContext().Selectors.getSelector(1, &II);
1389 }
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001390
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001391 /// ImplementationIsNonLazy - Check whether the given category or
1392 /// class implementation is "non-lazy".
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00001393 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001394
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001395public:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001396 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001397 // FIXME. All stubs for now!
1398 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001399
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001400 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001401 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001402 QualType ResultType,
1403 Selector Sel,
1404 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001405 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001406 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001407 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001408
1409 virtual CodeGen::RValue
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001410 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001411 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001412 QualType ResultType,
1413 Selector Sel,
1414 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001415 bool isCategoryImpl,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001416 llvm::Value *Receiver,
1417 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001418 const CallArgList &CallArgs,
1419 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001420
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001421 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001422 const ObjCInterfaceDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001423
Fariborz Jahanian03b29602010-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 Jahaniandf9ccc62009-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 Dunbar6bff2512009-08-03 17:06:42 +00001433
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00001434 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001435
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001436 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001437 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00001438 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001439
John McCall5a180392010-07-24 00:37:23 +00001440 virtual llvm::Constant *GetEHType(QualType T);
1441
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001442 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001443 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001444 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001445 virtual llvm::Constant *GetPropertySetFunction() {
1446 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001447 }
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001448
1449 virtual llvm::Constant *GetCopyStructFunction() {
1450 return ObjCTypes.getCopyStructFn();
1451 }
1452
Chris Lattner74391b42009-03-22 21:03:39 +00001453 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001454 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbar28ed0842009-02-16 18:48:45 +00001455 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001456
John McCallf1549f62010-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 Jahanianaa23b572009-01-23 23:53:38 +00001461 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlssonf57c5b22009-02-16 22:59:18 +00001462 const ObjCAtThrowStmt &S);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001463 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001464 llvm::Value *AddrWeakObj);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001465 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001466 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001467 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001468 llvm::Value *src, llvm::Value *dest,
1469 bool threadlocal = false);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001470 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001471 llvm::Value *src, llvm::Value *dest,
1472 llvm::Value *ivarOffset);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001473 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001474 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001475 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1476 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001477 llvm::Value *size);
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001478 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1479 QualType ObjectTy,
1480 llvm::Value *BaseValue,
1481 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001482 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001483 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001484 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001485 const ObjCIvarDecl *Ivar);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001486};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001487
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001488} // end anonymous namespace
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001489
1490/* *** Helper Functions *** */
1491
1492/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Andersona1cf15f2009-07-14 23:10:40 +00001493static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001494 llvm::Constant *C,
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001495 unsigned idx0,
1496 unsigned idx1) {
1497 llvm::Value *Idxs[] = {
Owen Anderson0032b272009-08-13 21:57:51 +00001498 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1499 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001500 };
Owen Anderson3c4972d2009-07-29 18:54:39 +00001501 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001502}
1503
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001504/// hasObjCExceptionAttribute - Return true if this class or any super
1505/// class has the __objc_exception__ attribute.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001506static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor68584ed2009-06-18 16:11:24 +00001507 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidis40b598e2009-06-30 02:34:44 +00001508 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001509 return true;
1510 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor68584ed2009-06-18 16:11:24 +00001511 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001512 return false;
1513}
1514
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001515/* *** CGObjCMac Public Interface *** */
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001516
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001517CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00001518 ObjCTypes(cgm) {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001519 ObjCABI = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001520 EmitImageInfo();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001521}
1522
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +00001523/// GetClass - Return a reference to the class for the given interface
1524/// decl.
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001525llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001526 const ObjCInterfaceDecl *ID) {
1527 return EmitClassRef(Builder, ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001528}
1529
1530/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001531llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1532 bool lval) {
1533 return EmitSelector(Builder, Sel, lval);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001534}
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001535llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001536 *Method) {
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001537 return EmitSelector(Builder, Method->getSelector());
1538}
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001539
John McCall5a180392010-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 Dunbarbbce49b2008-08-12 00:12:39 +00001545/// Generate a constant CFString object.
Daniel Dunbar6bff2512009-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 Dunbarbbce49b2008-08-12 00:12:39 +00001553*/
1554
Fariborz Jahanian33e982b2010-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 Jahanianaa23b572009-01-23 23:53:38 +00001564llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall0d13f6f2010-01-23 02:40:42 +00001565 const StringLiteral *SL) {
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001566 return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
1567 CGM.GetAddrOfConstantCFString(SL) :
1568 CGM.GetAddrOfConstantNSString(SL));
Daniel Dunbarc17a4d32008-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 Dunbar8f2926b2008-08-23 03:46:30 +00001574CodeGen::RValue
1575CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001576 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001577 QualType ResultType,
1578 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001579 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001580 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001581 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001582 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001583 const CodeGen::CallArgList &CallArgs,
1584 const ObjCMethodDecl *Method) {
Daniel Dunbare8b470d2008-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 Dunbar6bff2512009-08-03 17:06:42 +00001587 llvm::Value *ObjCSuper =
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001588 CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001589 llvm::Value *ReceiverAsObject =
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001590 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001591 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001592 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001593
Daniel Dunbarf56f1912008-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 Jahanian7ce77922009-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 Stumpb3589f42009-07-30 22:28:39 +00001607 } else {
Fariborz Jahanian7ce77922009-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 Dunbar6bff2512009-08-03 17:06:42 +00001612 }
Fariborz Jahanian182f2682009-11-14 02:18:31 +00001613 }
1614 else if (isCategoryImpl)
1615 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1616 else {
Fariborz Jahanianb0069ee2009-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 Dunbarf56f1912008-08-25 08:19:24 +00001620 }
Mike Stumpf5408fe2009-05-16 07:57:57 +00001621 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1622 // ObjCTypes types.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001623 const llvm::Type *ClassTy =
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001624 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001625 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001626 CGF.Builder.CreateStore(Target,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001627 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCallef072fd2010-05-22 01:48:05 +00001628 return EmitLegacyMessageSend(CGF, Return, ResultType,
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001629 EmitSelector(CGF.Builder, Sel),
1630 ObjCSuper, ObjCTypes.SuperPtrCTy,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001631 true, CallArgs, Method, ObjCTypes);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001632}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001633
1634/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001635CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001636 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001637 QualType ResultType,
1638 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001639 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001640 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001641 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001642 const ObjCMethodDecl *Method) {
John McCallef072fd2010-05-22 01:48:05 +00001643 return EmitLegacyMessageSend(CGF, Return, ResultType,
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001644 EmitSelector(CGF.Builder, Sel),
1645 Receiver, CGF.getContext().getObjCIdType(),
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001646 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00001647}
1648
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001649CodeGen::RValue
1650CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001651 ReturnValueSlot Return,
Daniel Dunbard6c93d72009-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 Dunbar19cd87e2008-08-30 03:02:31 +00001660 CallArgList ActualArgs;
Fariborz Jahaniand019d962009-04-24 21:07:43 +00001661 if (!IsSuper)
1662 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Daniel Dunbar46f45b92008-09-09 01:06:48 +00001663 ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001664 ActualArgs.push_back(std::make_pair(RValue::get(Sel),
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001665 CGF.getContext().getObjCSelType()));
1666 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001667
Daniel Dunbar541b63b2009-02-02 23:23:47 +00001668 CodeGenTypes &Types = CGM.getTypes();
John McCall04a67a62010-02-05 21:31:56 +00001669 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindola264ba482010-03-30 20:24:48 +00001670 FunctionType::ExtInfo());
Daniel Dunbar67939662009-09-17 04:01:40 +00001671 const llvm::FunctionType *FTy =
1672 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001673
Anders Carlsson7e70fb22010-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 Jahaniand0f8a8d2009-05-11 19:25:47 +00001679 llvm::Constant *Fn = NULL;
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001680 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001681 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001682 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001683 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1684 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1685 : ObjCTypes.getSendFpretFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001686 } else {
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001687 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001688 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001689 }
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001690 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
John McCallef072fd2010-05-22 01:48:05 +00001691 return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001692}
1693
Fariborz Jahanian93ce50d2010-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 Jahanian89ecd412010-08-04 16:57:49 +00001710llvm::Constant *CGObjCCommonMac::GCBlockLayout(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian44034db2010-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 Jahanian5af12352010-08-05 15:52:12 +00001714 if ((CGM.getLangOptions().getGCMode() == LangOptions::NonGC) ||
1715 DeclRefs.empty())
Fariborz Jahanian44034db2010-08-04 18:44:59 +00001716 return NullPtr;
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001717 bool hasUnion = false;
Fariborz Jahanian93ce50d2010-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 Jahaniana1f024c2010-08-06 16:28:55 +00001731 if ((Ty->isRecordType() || Ty->isUnionType()) && !BDRE->isByRef()) {
Fariborz Jahaniane1a48982010-08-05 21:00:25 +00001732 BuildAggrIvarRecordLayout(Ty->getAs<RecordType>(),
1733 FieldOffset,
1734 true,
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001735 hasUnion);
Fariborz Jahaniane1a48982010-08-05 21:00:25 +00001736 continue;
1737 }
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001738
Fariborz Jahanian93ce50d2010-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 Jahaniana1f024c2010-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 Jahanian93ce50d2010-08-04 23:55:24 +00001761
1762 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00001763 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-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 Jahanian89ecd412010-08-04 16:57:49 +00001776}
1777
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001778llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001779 const ObjCProtocolDecl *PD) {
Daniel Dunbarc67876d2008-09-04 04:33:15 +00001780 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00001781 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc67876d2008-09-04 04:33:15 +00001782 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1783
Owen Anderson3c4972d2009-07-29 18:54:39 +00001784 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001785 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001786}
1787
Fariborz Jahanianda320092009-01-29 19:24:30 +00001788void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stumpf5408fe2009-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 Dunbar0c0e7a62008-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 Dunbar6bff2512009-08-03 17:06:42 +00001796 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001797 GetOrEmitProtocol(PD);
1798}
1799
Fariborz Jahanianda320092009-01-29 19:24:30 +00001800llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001801 if (DefinedProtocols.count(PD->getIdentifier()))
1802 return GetOrEmitProtocol(PD);
1803 return GetOrEmitProtocolRef(PD);
1804}
1805
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001806/*
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +00001815
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001816See EmitProtocolExtension().
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001817*/
Daniel Dunbar0c0e7a62008-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 Dunbar242d4dc2008-08-25 06:02:07 +00001825 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00001826 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00001827 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1828
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001829 // Construct method lists.
1830 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1831 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001832 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001833 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-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 Dunbar6bff2512009-08-03 17:06:42 +00001840 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001841 }
1842
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001843 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001844 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-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 Dunbar6bff2512009-08-03 17:06:42 +00001851 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001852 }
1853
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001854 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001855 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001856 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001857 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001858 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardbc933702008-08-21 21:57:41 +00001859 PD->protocol_begin(),
1860 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001861 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001862 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001863 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1864 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001865 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001866 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001867 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1868 ClassMethods);
Owen Anderson08e25242009-07-27 22:29:56 +00001869 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001870 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001871
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001872 if (Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001873 // Already created, fix the linkage and update the initializer.
1874 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001875 Entry->setInitializer(Init);
1876 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001877 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00001878 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001879 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001880 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001881 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001882 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001883 // FIXME: Is this necessary? Why only for protocol?
1884 Entry->setAlignment(4);
1885 }
Chris Lattnerad64e022009-07-17 23:57:13 +00001886 CGM.AddUsedGlobal(Entry);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001887
1888 return Entry;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001889}
1890
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001891llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001892 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1893
1894 if (!Entry) {
Daniel Dunbar0c0e7a62008-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 Dunbar6bff2512009-08-03 17:06:42 +00001898 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00001899 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001900 llvm::GlobalValue::ExternalLinkage,
1901 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001902 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001903 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001904 // FIXME: Is this necessary? Why only for protocol?
1905 Entry->setAlignment(4);
1906 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001907
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001908 return Entry;
1909}
1910
1911/*
1912 struct _objc_protocol_extension {
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +00001917 };
1918*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001919llvm::Constant *
1920CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1921 const ConstantVector &OptInstanceMethods,
1922 const ConstantVector &OptClassMethods) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001923 uint64_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00001924 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001925 std::vector<llvm::Constant*> Values(4);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001926 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001927 Values[1] =
1928 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001929 + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001930 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1931 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001932 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001933 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001934 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1935 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001936 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00001937 0, PD, ObjCTypes);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001938
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001939 // Return null if no extension bits are used.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001940 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001941 Values[3]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001942 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001943
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001944 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00001945 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001946
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001947 // No special section, but goes in llvm.used
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001948 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001949 Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001950 0, 0, true);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001951}
1952
1953/*
1954 struct objc_protocol_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001955 struct objc_protocol_list *next;
1956 long count;
1957 Protocol *list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001958 };
1959*/
Daniel Dunbardbc933702008-08-21 21:57:41 +00001960llvm::Constant *
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001961CGObjCMac::EmitProtocolList(llvm::Twine Name,
Daniel Dunbardbc933702008-08-21 21:57:41 +00001962 ObjCProtocolDecl::protocol_iterator begin,
1963 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001964 std::vector<llvm::Constant*> ProtocolRefs;
1965
Daniel Dunbardbc933702008-08-21 21:57:41 +00001966 for (; begin != end; ++begin)
1967 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001968
1969 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001970 if (ProtocolRefs.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001971 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001972
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001973 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00001974 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001975
1976 std::vector<llvm::Constant*> Values(3);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001977 // This field is only used by the runtime.
Owen Andersonc9c88b42009-07-31 20:28:54 +00001978 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001979 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +00001984 ProtocolRefs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001985
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001986 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001987 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001988 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00001989 4, false);
Owen Anderson3c4972d2009-07-29 18:54:39 +00001990 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001991}
1992
Fariborz Jahanian191dcd72009-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 Dunbar6efc0c52008-08-13 03:21:16 +00002013/*
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002014 struct _objc_property {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002015 const char * const name;
2016 const char * const attributes;
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002017 };
2018
2019 struct _objc_property_list {
Daniel Dunbar6bff2512009-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 Dunbarc8ef5512008-08-23 00:19:03 +00002023 };
2024*/
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002025llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002026 const Decl *Container,
2027 const ObjCContainerDecl *OCD,
2028 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002029 std::vector<llvm::Constant*> Properties, Prop(2);
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002030 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002031 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2032 E = OCD->prop_end(); I != E; ++I) {
Steve Naroff93983f82009-01-11 12:47:58 +00002033 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002034 PropertySet.insert(PD->getIdentifier());
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002035 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00002036 Prop[1] = GetPropertyTypeString(PD, Container);
Owen Anderson08e25242009-07-27 22:29:56 +00002037 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002038 Prop));
2039 }
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00002040 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002041 for (ObjCInterfaceDecl::protocol_iterator P = OID->protocol_begin(),
2042 E = OID->protocol_end(); P != E; ++P)
Fariborz Jahanian6afbdf52010-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 Dunbarc8ef5512008-08-23 00:19:03 +00002052
2053 // Return null for empty list.
2054 if (Properties.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002055 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002056
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002057 unsigned PropertySize =
Duncan Sands9408c452009-05-09 07:08:47 +00002058 CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002059 std::vector<llvm::Constant*> Values(3);
Owen Anderson4a28d5d2009-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 Dunbar6bff2512009-08-03 17:06:42 +00002062 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002063 Properties.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002064 Values[2] = llvm::ConstantArray::get(AT, Properties);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002065 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002066
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002067 llvm::GlobalVariable *GV =
2068 CreateMetadataVar(Name, Init,
2069 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002070 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002071 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002072 true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002073 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002074}
2075
2076/*
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002077 struct objc_method_description_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002078 int count;
2079 struct objc_method_description list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002080 };
2081*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002082llvm::Constant *
2083CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
2084 std::vector<llvm::Constant*> Desc(2);
Owen Andersona1cf15f2009-07-14 23:10:40 +00002085 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002086 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
2087 ObjCTypes.SelectorPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002088 Desc[1] = GetMethodVarType(MD);
Owen Anderson08e25242009-07-27 22:29:56 +00002089 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002090 Desc);
2091}
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002092
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002093llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002094 const char *Section,
2095 const ConstantVector &Methods) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002096 // Return null for empty list.
2097 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002098 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002099
2100 std::vector<llvm::Constant*> Values(2);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002101 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002102 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002103 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002104 Values[1] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002105 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002106
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002107 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002108 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002109 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002110}
2111
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002112/*
2113 struct _objc_category {
Daniel Dunbar6bff2512009-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 Dunbar86e253a2008-08-22 20:34:54 +00002121 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002122*/
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00002123void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Duncan Sands9408c452009-05-09 07:08:47 +00002124 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002125
Mike Stumpf5408fe2009-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 Dunbar86e253a2008-08-22 20:34:54 +00002130 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002131 const ObjCCategoryDecl *Category =
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002132 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002133
2134 llvm::SmallString<256> ExtName;
2135 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2136 << OCD->getName();
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002137
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002138 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002139 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002140 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002141 // Instance methods should always be defined.
2142 InstanceMethods.push_back(GetMethodConstant(*i));
2143 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002144 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002145 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002146 // Class methods should always be defined.
2147 ClassMethods.push_back(GetMethodConstant(*i));
2148 }
2149
Daniel Dunbar86e253a2008-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 Jahanian679cd7f2009-04-29 20:40:05 +00002153 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002154 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002155 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002156 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002157 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002158 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002159 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002160 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002161 ClassMethods);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002162 if (Category) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002163 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002164 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002165 Category->protocol_begin(),
2166 Category->protocol_end());
2167 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002168 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002169 }
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002170 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002171
2172 // If there is no category @interface then there can be no properties.
2173 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002174 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002175 OCD, Category, ObjCTypes);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002176 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002177 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002178 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002179
Owen Anderson08e25242009-07-27 22:29:56 +00002180 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002181 Values);
2182
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002183 llvm::GlobalVariable *GV =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002184 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002185 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002186 4, true);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002187 DefinedCategories.push_back(GV);
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00002188 DefinedCategoryNames.insert(ExtName.str());
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002189}
2190
Daniel Dunbar27f9d772008-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 Dunbar27f9d772008-08-21 04:36:09 +00002202/*
2203 struct _objc_class {
Daniel Dunbar6bff2512009-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 Dunbar27f9d772008-08-21 04:36:09 +00002217 };
2218
2219 See EmitClassExtension();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002220*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002221void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002222 DefinedSymbols.insert(ID->getIdentifier());
2223
Chris Lattner8ec03f52008-11-24 03:54:41 +00002224 std::string ClassName = ID->getNameAsString();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002225 // FIXME: Gross
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002226 ObjCInterfaceDecl *Interface =
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002227 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002228 llvm::Constant *Protocols =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002229 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Daniel Dunbardbc933702008-08-21 21:57:41 +00002230 Interface->protocol_begin(),
2231 Interface->protocol_end());
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002232 unsigned Flags = eClassFlags_Factory;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00002233 if (ID->getNumIvarInitializers())
2234 Flags |= eClassFlags_HasCXXStructors;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002235 unsigned Size =
Daniel Dunbar2bebbf02009-05-03 10:46:44 +00002236 CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002237
2238 // FIXME: Set CXX-structors flag.
Daniel Dunbar04d40782009-04-14 06:00:08 +00002239 if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002240 Flags |= eClassFlags_Hidden;
2241
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002242 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002243 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002244 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002245 // Instance methods should always be defined.
2246 InstanceMethods.push_back(GetMethodConstant(*i));
2247 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002248 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002249 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002250 // Class methods should always be defined.
2251 ClassMethods.push_back(GetMethodConstant(*i));
2252 }
2253
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002254 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002255 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-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 Dunbar27f9d772008-08-21 04:36:09 +00002270 std::vector<llvm::Constant*> Values(12);
Daniel Dunbar5384b092009-05-03 08:56:52 +00002271 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002272 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002273 // Record a reference to the super class.
2274 LazySymbols.insert(Super->getIdentifier());
2275
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002276 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002277 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002278 ObjCTypes.ClassPtrTy);
2279 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002280 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002281 }
2282 Values[ 2] = GetClassName(ID->getIdentifier());
2283 // Version is always 0.
Owen Anderson4a28d5d2009-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 Jahanian46b86c62009-01-28 19:12:34 +00002287 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002288 Values[ 7] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002289 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002290 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002291 InstanceMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002292 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002293 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002294 Values[ 9] = Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002295 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002296 Values[11] = EmitClassExtension(ID);
Owen Anderson08e25242009-07-27 22:29:56 +00002297 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002298 Values);
Fariborz Jahanianb0069ee2009-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 Dunbar27f9d772008-08-21 04:36:09 +00002315 DefinedClasses.push_back(GV);
2316}
2317
2318llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2319 llvm::Constant *Protocols,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002320 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002321 unsigned Flags = eClassFlags_Meta;
Duncan Sands9408c452009-05-09 07:08:47 +00002322 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002323
Daniel Dunbar04d40782009-04-14 06:00:08 +00002324 if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002325 Flags |= eClassFlags_Hidden;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002326
Daniel Dunbar27f9d772008-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 Dunbar6bff2512009-08-03 17:06:42 +00002332 Values[ 0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002333 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002334 ObjCTypes.ClassPtrTy);
Daniel Dunbar86e253a2008-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 Dunbar27f9d772008-08-21 04:36:09 +00002338 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002339 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002340 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002341 ObjCTypes.ClassPtrTy);
2342 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002343 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002344 }
2345 Values[ 2] = GetClassName(ID->getIdentifier());
2346 // Version is always 0.
Owen Anderson4a28d5d2009-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 Jahanian46b86c62009-01-28 19:12:34 +00002350 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002351 Values[ 7] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00002352 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002353 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002354 Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002355 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002356 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002357 Values[ 9] = Protocols;
2358 // ivar_layout for metaclass is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002359 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002360 // The class extension is always unused for metaclasses.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002361 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00002362 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002363 Values);
2364
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002365 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner8ec03f52008-11-24 03:54:41 +00002366 Name += ID->getNameAsCString();
Daniel Dunbarf56f1912008-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 Anderson1c431b32009-07-08 19:05:04 +00002376 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002377 llvm::GlobalValue::InternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00002378 Init, Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002379 }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002380 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbar58a29122009-03-09 22:18:41 +00002381 GV->setAlignment(4);
Chris Lattnerad64e022009-07-17 23:57:13 +00002382 CGM.AddUsedGlobal(GV);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002383
2384 return GV;
2385}
2386
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002387llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00002388 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002389
Mike Stumpf5408fe2009-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 Dunbarf56f1912008-08-25 08:19:24 +00002394
2395 // Check for an existing forward reference.
Fariborz Jahanianb0d27942009-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 Dunbar6bff2512009-08-03 17:06:42 +00002398 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2399 true)) {
Daniel Dunbarf56f1912008-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 Anderson1c431b32009-07-08 19:05:04 +00002406 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002407 llvm::GlobalValue::ExternalLinkage,
2408 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00002409 Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002410 }
2411}
2412
Fariborz Jahanianb0069ee2009-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 Dunbar27f9d772008-08-21 04:36:09 +00002429/*
2430 struct objc_class_ext {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002431 uint32_t size;
2432 const char *weak_ivar_layout;
2433 struct _objc_property_list *properties;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002434 };
2435*/
2436llvm::Constant *
2437CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002438 uint64_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00002439 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002440
2441 std::vector<llvm::Constant*> Values(3);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002442 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanianc71303d2009-04-22 23:00:43 +00002443 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002444 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002445 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002446
2447 // Return null if no extension bits are used.
2448 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002449 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002450
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002451 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00002452 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002453 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002454 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002455 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002456}
2457
2458/*
2459 struct objc_ivar {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002460 char *ivar_name;
2461 char *ivar_type;
2462 int ivar_offset;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002463 };
2464
2465 struct objc_ivar_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002466 int ivar_count;
2467 struct objc_ivar list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002468 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002469*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002470llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002471 bool ForClass) {
Daniel Dunbar27f9d772008-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 Andersonc9c88b42009-07-31 20:28:54 +00002480 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002481
2482 ObjCInterfaceDecl *OID =
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002483 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002484
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00002485 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00002486 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002487
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00002488 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2489 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00002490 // Ignore unnamed bit-fields.
2491 if (!IVD->getDeclName())
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002492 continue;
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00002493 Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2494 Ivar[1] = GetMethodVarType(IVD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002495 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
Daniel Dunbar97776872009-04-22 07:32:20 +00002496 ComputeIvarBaseOffset(CGM, OID, IVD));
Owen Anderson08e25242009-07-27 22:29:56 +00002497 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002498 }
2499
2500 // Return null for empty list.
2501 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002502 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002503
2504 std::vector<llvm::Constant*> Values(2);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002505 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00002506 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002507 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002508 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002509 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002510
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002511 llvm::GlobalVariable *GV;
2512 if (ForClass)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002513 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002514 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002515 4, true);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002516 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002517 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002518 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002519 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002520 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002521}
2522
2523/*
2524 struct objc_method {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002525 SEL method_name;
2526 char *method_types;
2527 void *method;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002528 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002529
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002530 struct objc_method_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002531 struct objc_method_list *obsolete;
2532 int count;
2533 struct objc_method methods_list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002534 };
2535*/
Daniel Dunbarc45ef602008-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 Dunbarae226fa2008-08-27 02:31:56 +00002540llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002541 // FIXME: Use DenseMap::lookup
2542 llvm::Function *Fn = MethodDefinitions[MD];
2543 if (!Fn)
2544 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002545
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002546 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002547 Method[0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002548 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002549 ObjCTypes.SelectorPtrTy);
2550 Method[1] = GetMethodVarType(MD);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002551 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00002552 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002553}
2554
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002555llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002556 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002557 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002558 // Return null for empty list.
2559 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002560 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002561
2562 std::vector<llvm::Constant*> Values(3);
Owen Andersonc9c88b42009-07-31 20:28:54 +00002563 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002564 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00002565 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002566 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002567 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002568 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002569
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002570 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002571 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002572 ObjCTypes.MethodListPtrTy);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002573}
2574
Fariborz Jahanian493dab72009-01-26 21:38:32 +00002575llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002576 const ObjCContainerDecl *CD) {
Daniel Dunbarc575ce72009-10-19 01:21:19 +00002577 llvm::SmallString<256> Name;
Fariborz Jahanian679a5022009-01-10 21:06:09 +00002578 GetNameForMethod(OMD, CD, Name);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002579
Daniel Dunbar541b63b2009-02-02 23:23:47 +00002580 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00002581 const llvm::FunctionType *MethodTy =
Daniel Dunbar541b63b2009-02-02 23:23:47 +00002582 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002583 llvm::Function *Method =
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00002584 llvm::Function::Create(MethodTy,
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002585 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00002586 Name.str(),
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002587 &CGM.getModule());
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002588 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002589
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002590 return Method;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002591}
2592
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002593llvm::GlobalVariable *
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002594CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002595 llvm::Constant *Init,
2596 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +00002597 unsigned Align,
2598 bool AddToUsed) {
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002599 const llvm::Type *Ty = Init->getType();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002600 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00002601 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerad64e022009-07-17 23:57:13 +00002602 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002603 if (Section)
2604 GV->setSection(Section);
Daniel Dunbar35bd7632009-03-09 20:50:13 +00002605 if (Align)
2606 GV->setAlignment(Align);
2607 if (AddToUsed)
Chris Lattnerad64e022009-07-17 23:57:13 +00002608 CGM.AddUsedGlobal(GV);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002609 return GV;
2610}
2611
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002612llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002613 // Abuse this interface function as a place to finalize.
2614 FinishModule();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002615 return NULL;
2616}
2617
Chris Lattner74391b42009-03-22 21:03:39 +00002618llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002619 return ObjCTypes.getGetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00002620}
2621
Chris Lattner74391b42009-03-22 21:03:39 +00002622llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002623 return ObjCTypes.getSetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00002624}
2625
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00002626llvm::Constant *CGObjCMac::GetCopyStructFunction() {
2627 return ObjCTypes.getCopyStructFn();
2628}
2629
Chris Lattner74391b42009-03-22 21:03:39 +00002630llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002631 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson2abd89c2008-08-31 04:05:03 +00002632}
2633
John McCallf1549f62010-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 McCallcc505292010-07-21 06:59:36 +00002643namespace {
John McCall1f0fca52010-07-21 07:22:38 +00002644 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCallcc505292010-07-21 06:59:36 +00002645 const Stmt &S;
John McCall0b251722010-08-04 05:59:32 +00002646 llvm::Value *SyncArgSlot;
John McCallcc505292010-07-21 06:59:36 +00002647 llvm::Value *CallTryExitVar;
2648 llvm::Value *ExceptionData;
2649 ObjCTypesHelper &ObjCTypes;
2650 PerformFragileFinally(const Stmt *S,
John McCall0b251722010-08-04 05:59:32 +00002651 llvm::Value *SyncArgSlot,
John McCallcc505292010-07-21 06:59:36 +00002652 llvm::Value *CallTryExitVar,
2653 llvm::Value *ExceptionData,
2654 ObjCTypesHelper *ObjCTypes)
John McCall0b251722010-08-04 05:59:32 +00002655 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCallcc505292010-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 McCall0b251722010-08-04 05:59:32 +00002684 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCallcc505292010-07-21 06:59:36 +00002685 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2686 ->setDoesNotThrow();
2687 }
2688 }
2689 };
John McCall87bb5822010-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 McCall0b251722010-08-04 05:59:32 +00002706
John McCall87bb5822010-07-31 23:20:56 +00002707 void emitWriteHazard();
John McCall0b251722010-08-04 05:59:32 +00002708 void emitHazardsInNewBlocks();
John McCall87bb5822010-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 McCall87bb5822010-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 McCall0b251722010-08-04 05:59:32 +00002775void FragileHazards::emitHazardsInNewBlocks() {
John McCall87bb5822010-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 McCall0b251722010-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 McCall87bb5822010-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 McCallcc505292010-07-21 06:59:36 +00002838}
2839
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002840/*
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002841
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002842 Objective-C setjmp-longjmp (sjlj) Exception Handling
2843 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002844
John McCallf1549f62010-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 Dunbar6bff2512009-08-03 17:06:42 +00002877 The basic framework for a @try-catch-finally is as follows:
2878 {
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002879 objc_exception_data d;
2880 id _rethrow = null;
Anders Carlsson190d00e2009-02-07 21:26:04 +00002881 bool _call_try_exit = true;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002882
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002883 objc_exception_try_enter(&d);
2884 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002885 ... try body ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002886 } else {
Daniel Dunbar6bff2512009-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 Dunbar18ccc772008-09-28 01:03:14 +00002903 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00002904 ... jump-through-finally to finally_end ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002905
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002906 finally:
Anders Carlsson190d00e2009-02-07 21:26:04 +00002907 if (_call_try_exit)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002908 objc_exception_try_exit(&d);
Anders Carlsson190d00e2009-02-07 21:26:04 +00002909
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002910 ... finally block ....
Daniel Dunbar898d5082008-09-30 01:06:03 +00002911 ... dispatch to finally destination ...
2912
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002913 finally_rethrow:
Daniel Dunbar898d5082008-09-30 01:06:03 +00002914 objc_exception_throw(_rethrow);
2915
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002916 finally_end:
2917 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002918
Daniel Dunbar6bff2512009-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 Dunbar18ccc772008-09-28 01:03:14 +00002923
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002924 We specialize this framework for a few particular circumstances:
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002925
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002926 - If there are no catch blocks, then we avoid emitting the second
2927 exception handling context.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002928
Daniel Dunbar6bff2512009-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 Dunbar18ccc772008-09-28 01:03:14 +00002931
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002932 - FIXME: If there is no @finally block we can do a few more
2933 simplifications.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002934
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002935 Rethrows and Jumps-Through-Finally
2936 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002937
John McCallf1549f62010-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 Dunbar18ccc772008-09-28 01:03:14 +00002940
John McCallf1549f62010-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 Dunbar898d5082008-09-30 01:06:03 +00002945
John McCallf1549f62010-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 Dunbar18ccc772008-09-28 01:03:14 +00002950*/
2951
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00002952void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2953 const Stmt &S) {
2954 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallf1549f62010-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 Dunbar6bff2512009-08-03 17:06:42 +00002965
Daniel Dunbar1c566672009-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 McCall0b251722010-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 Dunbar1c566672009-02-24 01:43:46 +00002972 if (!isTry) {
John McCall0b251722010-08-04 05:59:32 +00002973 llvm::Value *SyncArg =
Daniel Dunbar1c566672009-02-24 01:43:46 +00002974 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2975 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallf1549f62010-07-06 01:34:17 +00002976 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
2977 ->setDoesNotThrow();
John McCall0b251722010-08-04 05:59:32 +00002978
2979 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
2980 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar1c566672009-02-24 01:43:46 +00002981 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00002982
John McCall0b251722010-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 McCall87bb5822010-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 McCallf1549f62010-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 McCall0b251722010-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 McCallf1549f62010-07-06 01:34:17 +00003002 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlsson190d00e2009-02-07 21:26:04 +00003003 "_call_try_exit");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003004
John McCallf1549f62010-07-06 01:34:17 +00003005 // Push a normal cleanup to leave the try scope.
John McCall1f0fca52010-07-21 07:22:38 +00003006 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall0b251722010-08-04 05:59:32 +00003007 SyncArgSlot,
John McCall1f0fca52010-07-21 07:22:38 +00003008 CallTryExitVar,
3009 ExceptionData,
3010 &ObjCTypes);
John McCallf1549f62010-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 Dunbar55e87422008-11-11 02:29:29 +00003029 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3030 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallf1549f62010-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 Carlsson80f25672008-09-09 17:59:25 +00003034
John McCallf1549f62010-07-06 01:34:17 +00003035 // Emit the protected block.
Anders Carlsson80f25672008-09-09 17:59:25 +00003036 CGF.EmitBlock(TryBlock);
John McCall0b251722010-08-04 05:59:32 +00003037 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003038 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallf1549f62010-07-06 01:34:17 +00003039 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall0b251722010-08-04 05:59:32 +00003040
3041 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003042
John McCallf1549f62010-07-06 01:34:17 +00003043 // Emit the exception handler block.
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003044 CGF.EmitBlock(TryHandler);
Daniel Dunbar55e40722008-09-27 07:03:52 +00003045
John McCall87bb5822010-07-31 23:20:56 +00003046 // Don't optimize loads of the in-scope locals across this point.
3047 Hazards.emitWriteHazard();
3048
John McCallf1549f62010-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 McCall0b251722010-08-04 05:59:32 +00003053 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003054 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallf1549f62010-07-06 01:34:17 +00003055
3056 // Otherwise, we have to match against the caught exceptions.
3057 } else {
John McCall0b251722010-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 McCallf1549f62010-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 Gregor8f5e3dd2010-04-23 22:50:49 +00003069 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003070
John McCall0b251722010-08-04 05:59:32 +00003071 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallf1549f62010-07-06 01:34:17 +00003072
John McCall0b251722010-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 Carlsson80f25672008-09-09 17:59:25 +00003080
John McCall0b251722010-08-04 05:59:32 +00003081 llvm::CallInst *SetJmpResult =
3082 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3083 "setjmp.result");
3084 SetJmpResult->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003085
John McCall0b251722010-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 Dunbar6bff2512009-08-03 17:06:42 +00003097
Daniel Dunbar55e40722008-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 Gregor8f5e3dd2010-04-23 22:50:49 +00003102 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3103 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson80f25672008-09-09 17:59:25 +00003104
Douglas Gregorc00d8e12010-04-26 16:46:50 +00003105 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff14108da2009-07-10 23:34:53 +00003106 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar129271a2008-09-27 07:36:24 +00003107
Anders Carlsson80f25672008-09-09 17:59:25 +00003108 // catch(...) always matches.
Daniel Dunbar55e40722008-09-27 07:03:52 +00003109 if (!CatchParam) {
3110 AllMatched = true;
3111 } else {
John McCall183700f2009-09-21 23:43:11 +00003112 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003113
John McCallf1549f62010-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 Dunbar97f61d12008-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 Friedman818e96f2009-07-11 00:57:02 +00003118 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbar55e40722008-09-27 07:03:52 +00003119 AllMatched = true;
Anders Carlsson80f25672008-09-09 17:59:25 +00003120 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003121
John McCallf1549f62010-07-06 01:34:17 +00003122 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003123 if (AllMatched) {
John McCallf1549f62010-07-06 01:34:17 +00003124 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3125
Anders Carlssondde0a942008-09-11 09:15:33 +00003126 if (CatchParam) {
Steve Naroff7ba138a2009-03-03 19:52:17 +00003127 CGF.EmitLocalBlockVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003128 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallf1549f62010-07-06 01:34:17 +00003129
3130 // These types work out because ConvertType(id) == i8*.
Steve Naroff7ba138a2009-03-03 19:52:17 +00003131 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlssondde0a942008-09-11 09:15:33 +00003132 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003133
Anders Carlssondde0a942008-09-11 09:15:33 +00003134 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003135
3136 // The scope of the catch variable ends right here.
3137 CatchVarCleanups.ForceCleanup();
3138
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003139 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson80f25672008-09-09 17:59:25 +00003140 break;
3141 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003142
Steve Naroff14108da2009-07-10 23:34:53 +00003143 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall506b57e2010-05-17 21:00:27 +00003144 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallf1549f62010-07-06 01:34:17 +00003145
3146 // FIXME: @catch (Class c) ?
John McCall506b57e2010-05-17 21:00:27 +00003147 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3148 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson80f25672008-09-09 17:59:25 +00003149
3150 // Check if the @catch block matches the exception object.
John McCall506b57e2010-05-17 21:00:27 +00003151 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003152
John McCallf1549f62010-07-06 01:34:17 +00003153 llvm::CallInst *Match =
Chris Lattner34b02a12009-04-22 02:26:14 +00003154 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3155 Class, Caught, "match");
John McCallf1549f62010-07-06 01:34:17 +00003156 Match->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003157
John McCallf1549f62010-07-06 01:34:17 +00003158 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3159 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003160
3161 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003162 MatchedBlock, NextCatchBlock);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003163
Anders Carlsson80f25672008-09-09 17:59:25 +00003164 // Emit the @catch block.
3165 CGF.EmitBlock(MatchedBlock);
John McCallf1549f62010-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 McCall0b251722010-08-04 05:59:32 +00003169 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallf1549f62010-07-06 01:34:17 +00003170
Steve Naroff7ba138a2009-03-03 19:52:17 +00003171 CGF.EmitLocalBlockVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003172 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003173
John McCallf1549f62010-07-06 01:34:17 +00003174 // Initialize the catch variable.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003175 llvm::Value *Tmp =
3176 CGF.Builder.CreateBitCast(Caught,
3177 CGF.ConvertType(CatchParam->getType()),
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003178 "tmp");
Steve Naroff7ba138a2009-03-03 19:52:17 +00003179 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003180
Anders Carlssondde0a942008-09-11 09:15:33 +00003181 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003182
3183 // We're done with the catch variable.
3184 CatchVarCleanups.ForceCleanup();
3185
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003186 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003187
Anders Carlsson80f25672008-09-09 17:59:25 +00003188 CGF.EmitBlock(NextCatchBlock);
3189 }
3190
John McCallf1549f62010-07-06 01:34:17 +00003191 CGF.ObjCEHValueStack.pop_back();
3192
John McCall0b251722010-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 Carlssonf3a79a92009-02-09 20:38:58 +00003212 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar55e40722008-09-27 07:03:52 +00003213 }
Anders Carlsson80f25672008-09-09 17:59:25 +00003214 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003215
John McCall87bb5822010-07-31 23:20:56 +00003216 // Insert read hazards as required in the new blocks.
John McCall0b251722010-08-04 05:59:32 +00003217 Hazards.emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00003218
John McCallf1549f62010-07-06 01:34:17 +00003219 // Pop the cleanup.
John McCall0b251722010-08-04 05:59:32 +00003220 CGF.Builder.restoreIP(TryFallthroughIP);
3221 if (CGF.HaveInsertPoint())
3222 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallf1549f62010-07-06 01:34:17 +00003223 CGF.PopCleanupBlock();
John McCall0b251722010-08-04 05:59:32 +00003224 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003225
John McCallf1549f62010-07-06 01:34:17 +00003226 // Emit the rethrow block.
John McCall87bb5822010-07-31 23:20:56 +00003227 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallff8e1152010-07-23 21:56:41 +00003228 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallf1549f62010-07-06 01:34:17 +00003229 if (CGF.HaveInsertPoint()) {
John McCall0b251722010-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 McCallf1549f62010-07-06 01:34:17 +00003237 ->setDoesNotThrow();
3238 CGF.Builder.CreateUnreachable();
Fariborz Jahanianf2878e52008-11-21 19:21:53 +00003239 }
Anders Carlsson80f25672008-09-09 17:59:25 +00003240
John McCall87bb5822010-07-31 23:20:56 +00003241 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00003242}
3243
3244void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar898d5082008-09-30 01:06:03 +00003245 const ObjCAtThrowStmt &S) {
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003246 llvm::Value *ExceptionAsObject;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003247
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003248 if (const Expr *ThrowExpr = S.getThrowExpr()) {
3249 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003250 ExceptionAsObject =
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003251 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
3252 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003253 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003254 "Unexpected rethrow outside @catch block.");
Anders Carlsson273558f2009-02-07 21:37:21 +00003255 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003256 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003257
John McCallf1549f62010-07-06 01:34:17 +00003258 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3259 ->setDoesNotReturn();
Anders Carlsson80f25672008-09-09 17:59:25 +00003260 CGF.Builder.CreateUnreachable();
Daniel Dunbara448fb22008-11-11 23:11:34 +00003261
3262 // Clear the insertion point to indicate we are in unreachable code.
3263 CGF.Builder.ClearInsertionPoint();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00003264}
3265
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003266/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00003267/// object: objc_read_weak (id *src)
3268///
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003269llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003270 llvm::Value *AddrWeakObj) {
Eli Friedman8339b352009-03-07 03:57:15 +00003271 const llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003272 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3273 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3274 ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00003275 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003276 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00003277 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00003278 return read_weak;
3279}
3280
Fariborz Jahanian3e283e32008-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 Stump1eb44332009-09-09 15:08:12 +00003285 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003286 const llvm::Type * SrcTy = src->getType();
3287 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003288 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00003291 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003292 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3293 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003294 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3295 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00003296 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003297 src, dst, "weakassign");
3298 return;
3299}
3300
Fariborz Jahanian58626502008-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 Jahanian021a7a62010-07-20 20:30:03 +00003305 llvm::Value *src, llvm::Value *dst,
3306 bool threadlocal) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003307 const llvm::Type * SrcTy = src->getType();
3308 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003309 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00003312 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003313 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3314 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003315 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3316 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-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 Jahanian58626502008-11-19 00:59:10 +00003323 return;
3324}
3325
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003326/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003327/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003328///
3329void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003330 llvm::Value *src, llvm::Value *dst,
3331 llvm::Value *ivarOffset) {
3332 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003333 const llvm::Type * SrcTy = src->getType();
3334 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003335 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00003338 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003339 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3340 }
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003341 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3342 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003343 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3344 src, dst, ivarOffset);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003345 return;
3346}
3347
Fariborz Jahanian58626502008-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 Stump1eb44332009-09-09 15:08:12 +00003352 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003353 const llvm::Type * SrcTy = src->getType();
3354 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003355 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00003358 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003359 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3360 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003361 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3362 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00003363 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian58626502008-11-19 00:59:10 +00003364 src, dst, "weakassign");
3365 return;
3366}
3367
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003368void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003369 llvm::Value *DestPtr,
3370 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00003371 llvm::Value *size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003372 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3373 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003374 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00003375 DestPtr, SrcPtr, size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003376 return;
3377}
3378
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00003379/// EmitObjCValueForIvar - Code Gen for ivar reference.
3380///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00003381LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3382 QualType ObjectTy,
3383 llvm::Value *BaseValue,
3384 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00003385 unsigned CVRQualifiers) {
John McCallc12c5bb2010-05-15 11:32:37 +00003386 const ObjCInterfaceDecl *ID =
3387 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00003388 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3389 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00003390}
3391
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003392llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00003393 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003394 const ObjCIvarDecl *Ivar) {
Daniel Dunbar97776872009-04-22 07:32:20 +00003395 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003396 return llvm::ConstantInt::get(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003397 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3398 Offset);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003399}
3400
Daniel Dunbarf77ac862008-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 Dunbarfce176b2010-04-25 20:39:01 +00003412 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003413 eImageInfo_GarbageCollected = (1 << 1),
3414 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003415 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3416
Daniel Dunbarfce176b2010-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 Dunbarc7c6dc02009-04-20 07:11:47 +00003419 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003420};
3421
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003422void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbarf77ac862008-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 Dunbar6bff2512009-08-03 17:06:42 +00003431
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003432 // We never allow @synthesize of a superclass property.
3433 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003434
Chris Lattner77b89b82010-06-27 07:15:29 +00003435 const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
3436
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003437 // Emitted as int[2];
3438 llvm::Constant *values[2] = {
Chris Lattner77b89b82010-06-27 07:15:29 +00003439 llvm::ConstantInt::get(Int32Ty, version),
3440 llvm::ConstantInt::get(Int32Ty, flags)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003441 };
Chris Lattner77b89b82010-06-27 07:15:29 +00003442 llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
Daniel Dunbar63c5b502009-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 Dunbar6bff2512009-08-03 17:06:42 +00003449 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003450 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
Owen Anderson7db6d832009-07-28 18:33:04 +00003451 llvm::ConstantArray::get(AT, values, 2),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003452 Section,
3453 0,
3454 true);
3455 GV->setConstant(true);
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003456}
3457
Daniel Dunbar4e2d7d02008-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 Sands9408c452009-05-09 07:08:47 +00003470 uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003471
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003472 std::vector<llvm::Constant*> Values(4);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003473 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
3474 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00003475 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003476 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003477 Values[3] = EmitModuleSymbols();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003478 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson08e25242009-07-27 22:29:56 +00003479 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003480 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00003481 4, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003482}
3483
3484llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003485 unsigned NumClasses = DefinedClasses.size();
3486 unsigned NumCategories = DefinedCategories.size();
3487
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003488 // Return null if no symbols were defined.
3489 if (!NumClasses && !NumCategories)
Owen Andersonc9c88b42009-07-31 20:28:54 +00003490 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003491
3492 std::vector<llvm::Constant*> Values(5);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003493 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Andersonc9c88b42009-07-31 20:28:54 +00003494 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003495 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3496 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003497
Daniel Dunbar86e253a2008-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 Dunbar27f9d772008-08-21 04:36:09 +00003500 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003501 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00003502 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003503 ObjCTypes.Int8PtrTy);
3504 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003505 Symbols[NumClasses + i] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003506 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003507 ObjCTypes.Int8PtrTy);
3508
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003509 Values[4] =
Owen Anderson96e0fc72009-07-29 22:16:19 +00003510 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003511 NumClasses + NumCategories),
3512 Symbols);
3513
Nick Lewycky0d36dd22009-09-19 20:00:52 +00003514 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003515
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003516 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003517 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3518 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003519 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00003520 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003521}
3522
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003523llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003524 const ObjCInterfaceDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003525 LazySymbols.insert(ID->getIdentifier());
3526
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003527 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003528
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003529 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003530 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003531 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003532 ObjCTypes.ClassPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003533 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003534 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3535 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003536 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003537 }
3538
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00003539 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003540}
3541
Fariborz Jahanian03b29602010-06-17 19:56:20 +00003542llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3543 bool lvalue) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003544 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003545
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003546 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003547 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003548 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003549 ObjCTypes.SelectorPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003550 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003551 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3552 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003553 4, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003554 }
3555
Fariborz Jahanian03b29602010-06-17 19:56:20 +00003556 if (lvalue)
3557 return Entry;
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00003558 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003559}
3560
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00003561llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003562 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003563
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003564 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003565 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003566 llvm::ConstantArray::get(VMContext,
3567 Ident->getNameStart()),
Daniel Dunbar6633e3c2010-07-29 22:57:21 +00003568 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003569 1, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003570
Owen Andersona1cf15f2009-07-14 23:10:40 +00003571 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003572}
3573
Fariborz Jahaniand80d81b2009-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 Dunbar6bff2512009-08-03 17:06:42 +00003577 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Andersonc9c88b42009-07-31 20:28:54 +00003578 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00003579}
3580
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003581void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003582 unsigned int BytePos,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003583 bool ForStrongLayout,
3584 bool &HasUnion) {
3585 const RecordDecl *RD = RT->getDecl();
3586 // FIXME - Use iterator.
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00003587 llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003588 const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003589 const llvm::StructLayout *RecLayout =
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003590 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003591
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003592 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3593 ForStrongLayout, HasUnion);
3594}
3595
Daniel Dunbar5a5a8032009-05-03 21:05:10 +00003596void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003597 const llvm::StructLayout *Layout,
3598 const RecordDecl *RD,
Chris Lattnerf1690852009-03-31 08:48:01 +00003599 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003600 unsigned int BytePos, bool ForStrongLayout,
3601 bool &HasUnion) {
Fariborz Jahanian820e0202009-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 Jahanian7fb16272009-04-21 18:33:06 +00003607 FieldDecl *LastFieldBitfield = 0;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003608 uint64_t MaxFieldOffset = 0;
3609 uint64_t MaxSkippedFieldOffset = 0;
3610 uint64_t LastBitfieldOffset = 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003611
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003612 if (RecFields.empty())
3613 return;
Chris Lattnerf1690852009-03-31 08:48:01 +00003614 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3615 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3616
Chris Lattnerf1690852009-03-31 08:48:01 +00003617 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003618 FieldDecl *Field = RecFields[i];
Daniel Dunbare05cc982009-05-03 23:35:23 +00003619 uint64_t FieldOffset;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00003620 if (RD) {
Daniel Dunbarf8f8eba2010-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 Carlssonfc514ab2009-07-24 17:23:54 +00003625 } else
Daniel Dunbare05cc982009-05-03 23:35:23 +00003626 FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003627
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003628 // Skip over unnamed or bitfields
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003629 if (!Field->getIdentifier() || Field->isBitField()) {
3630 LastFieldBitfield = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003631 LastBitfieldOffset = FieldOffset;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003632 continue;
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003633 }
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003634
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003635 LastFieldBitfield = 0;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003636 QualType FQT = Field->getType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003637 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003638 if (FQT->isUnionType())
3639 HasUnion = true;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003640
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003641 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003642 BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003643 ForStrongLayout, HasUnion);
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003644 continue;
3645 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003646
Chris Lattnerf1690852009-03-31 08:48:01 +00003647 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003648 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003649 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003650 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003651 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003652 FQT = CArray->getElementType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003653 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3654 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003655 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003656 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003657 FQT = CArray->getElementType();
3658 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003659
3660 assert(!FQT->isUnionType() &&
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003661 "layout for array of unions not supported");
3662 if (FQT->isRecordType()) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003663 int OldIndex = IvarsInfo.size() - 1;
3664 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003665
Ted Kremenek6217b802009-07-29 21:53:49 +00003666 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003667 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003668 ForStrongLayout, HasUnion);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003669
Fariborz Jahanian820e0202009-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 Dunbar6bff2512009-08-03 17:06:42 +00003673 for (int FirstIndex = IvarsInfo.size() - 1,
3674 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003675 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar8b2926c2009-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 Jahanian820e0202009-03-11 00:07:04 +00003682 }
3683 continue;
3684 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003685 }
Fariborz Jahanian820e0202009-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 McCall0953e762009-09-24 19:53:00 +00003688 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003689
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003690 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall0953e762009-09-24 19:53:00 +00003691 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3692 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00003693 if (IsUnion) {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003694 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar487993b2009-05-03 13:32:01 +00003695 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003696 MaxUnionIvarSize = UnionIvarSize;
3697 MaxField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003698 MaxFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003699 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00003700 } else {
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003701 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003702 FieldSize / WordSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003703 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003704 } else if ((ForStrongLayout &&
John McCall0953e762009-09-24 19:53:00 +00003705 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3706 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00003707 if (IsUnion) {
Mike Stumpf5408fe2009-05-16 07:57:57 +00003708 // FIXME: Why the asymmetry? We divide by word size in bits on other
3709 // side.
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003710 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar487993b2009-05-03 13:32:01 +00003711 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003712 MaxSkippedUnionIvarSize = UnionIvarSize;
3713 MaxSkippedField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003714 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003715 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00003716 } else {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003717 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003718 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003719 FieldSize / ByteSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003720 }
3721 }
3722 }
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003723
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003724 if (LastFieldBitfield) {
3725 // Last field was a bitfield. Must update skip info.
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003726 Expr *BitWidth = LastFieldBitfield->getBitWidth();
3727 uint64_t BitFieldSize =
Eli Friedman9a901bb2009-04-26 19:19:15 +00003728 BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
Daniel Dunbar487993b2009-05-03 13:32:01 +00003729 GC_IVAR skivar;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003730 skivar.ivar_bytepos = BytePos + LastBitfieldOffset;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003731 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3732 + ((BitFieldSize % ByteSizeInBits) != 0);
3733 SkipIvars.push_back(skivar);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003734 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003735
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003736 if (MaxField)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003737 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003738 MaxUnionIvarSize));
3739 if (MaxSkippedField)
Daniel Dunbar900c1982009-05-03 23:31:46 +00003740 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003741 MaxSkippedUnionIvarSize));
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00003742}
3743
Fariborz Jahanianb8fd2eb2010-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 Jahanian9397e1d2009-03-11 20:59:05 +00003750 unsigned int WordsToScan, WordsToSkip;
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00003751 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003752
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003753 // Build the string of skip/scan nibbles
Fariborz Jahanian8c2f2d12009-04-24 17:15:27 +00003754 llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003755 unsigned int WordSize =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003756 CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003757 if (IvarsInfo[0].ivar_bytepos == 0) {
3758 WordsToSkip = 0;
3759 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003760 } else {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003761 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3762 WordsToScan = IvarsInfo[0].ivar_size;
3763 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003764 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003765 unsigned int TailPrevGCObjC =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003766 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003767 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003768 // consecutive 'scanned' object pointers.
3769 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003770 } else {
Fariborz Jahanian9397e1d2009-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 Jahanianc8ce9c82009-03-12 22:50:49 +00003776 SKIP_SCAN SkScan;
3777 SkScan.skip = WordsToSkip;
3778 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003779 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003780
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003781 // Skip the hole.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003782 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3783 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003784 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003785 WordsToSkip = 0;
3786 WordsToScan = IvarsInfo[i].ivar_size;
3787 }
3788 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003789 if (WordsToScan > 0) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003790 SKIP_SCAN SkScan;
3791 SkScan.skip = WordsToSkip;
3792 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003793 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003794 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003795
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003796 if (!SkipIvars.empty()) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003797 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003798 int LastByteSkipped =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003799 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003800 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003801 int LastByteScanned =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003802 IvarsInfo[LastIndex].ivar_bytepos +
3803 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003804 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramer54d76db2009-12-25 15:43:36 +00003805 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003806 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003807 SKIP_SCAN SkScan;
3808 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3809 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003810 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-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 Jahanian81adc052009-04-24 16:17:09 +00003815 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003816 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-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 Jahanian93ce50d2010-08-04 23:55:24 +00003826
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003827 // Generate the string.
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003828 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-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 Jahanian93ce50d2010-08-04 23:55:24 +00003834
Fariborz Jahanian9397e1d2009-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 Jahanian93ce50d2010-08-04 23:55:24 +00003838
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003839 // next (skip small, scan)
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003840 if (skip_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003841 byte = skip_small << 4;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003842 if (scan_big > 0) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003843 byte |= 0xf;
3844 --scan_big;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003845 } else if (scan_small) {
Fariborz Jahanian9397e1d2009-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 Dunbar31682fd2009-05-03 23:21:22 +00003855 if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003856 byte = scan_small;
3857 BitMap += byte;
3858 }
3859 }
3860 // null terminate string.
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003861 unsigned char zero = 0;
3862 BitMap += zero;
Fariborz Jahanian93ce50d2010-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 Dunbar6bff2512009-08-03 17:06:42 +00003871
Fariborz Jahanian93ce50d2010-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 Jahanianb8fd2eb2010-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 Jahanian93ce50d2010-08-04 23:55:24 +00003923 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003924 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003925
3926 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003927 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian3d2ad662009-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 Jahanian93ce50d2010-08-04 23:55:24 +00003938 return C;
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00003939}
3940
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003941llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003942 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3943
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003944 // FIXME: Avoid std::string copying.
3945 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003946 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Owen Anderson0032b272009-08-13 21:57:51 +00003947 llvm::ConstantArray::get(VMContext, Sel.getAsString()),
Daniel Dunbar6633e3c2010-07-29 22:57:21 +00003948 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003949 1, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003950
Owen Andersona1cf15f2009-07-14 23:10:40 +00003951 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003952}
3953
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003954// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003955llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar27f9d772008-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 Jahanian56210f72009-01-21 23:34:32 +00003960llvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003961 return GetMethodVarName(&CGM.getContext().Idents.get(Name));
3962}
3963
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00003964llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel7794bb82009-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 Dunbar6efc0c52008-08-13 03:21:16 +00003969
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003970 if (!Entry)
3971 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson0032b272009-08-13 21:57:51 +00003972 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbar6633e3c2010-07-29 22:57:21 +00003973 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003974 1, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003975
Owen Andersona1cf15f2009-07-14 23:10:40 +00003976 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003977}
3978
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003979llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003980 std::string TypeStr;
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003981 CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
3982 TypeStr);
Devang Patel7794bb82009-03-04 18:21:39 +00003983
3984 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3985
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003986 if (!Entry)
3987 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson0032b272009-08-13 21:57:51 +00003988 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbar6633e3c2010-07-29 22:57:21 +00003989 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003990 1, true);
Devang Patel7794bb82009-03-04 18:21:39 +00003991
Owen Andersona1cf15f2009-07-14 23:10:40 +00003992 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003993}
3994
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003995// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003996llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003997 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003998
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003999 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004000 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004001 llvm::ConstantArray::get(VMContext,
4002 Ident->getNameStart()),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004003 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004004 1, true);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004005
Owen Andersona1cf15f2009-07-14 23:10:40 +00004006 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004007}
4008
4009// FIXME: Merge into a single cstring creation function.
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00004010// FIXME: This Decl should be more precise.
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004011llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004012CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4013 const Decl *Container) {
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00004014 std::string TypeStr;
4015 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004016 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4017}
4018
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004019void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004020 const ObjCContainerDecl *CD,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004021 llvm::SmallVectorImpl<char> &Name) {
4022 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian679a5022009-01-10 21:06:09 +00004023 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004024 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4025 << '[' << CD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004026 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004027 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer900fc632010-04-17 09:33:03 +00004028 OS << '(' << CID << ')';
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004029 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00004030}
4031
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004032void CGObjCMac::FinishModule() {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004033 EmitModuleInfo();
4034
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004035 // Emit the dummy bodies for any protocols which were referenced but
4036 // never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004037 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerad64e022009-07-17 23:57:13 +00004038 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4039 if (I->second->hasInitializer())
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004040 continue;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004041
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004042 std::vector<llvm::Constant*> Values(5);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004043 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004044 Values[1] = GetClassName(I->first);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004045 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004046 Values[3] = Values[4] =
Owen Andersonc9c88b42009-07-31 20:28:54 +00004047 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004048 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson08e25242009-07-27 22:29:56 +00004049 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004050 Values));
Chris Lattnerad64e022009-07-17 23:57:13 +00004051 CGM.AddUsedGlobal(I->second);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004052 }
4053
Daniel Dunbar242d4dc2008-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 Dunbar33063492009-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 Dunbar242d4dc2008-08-25 06:02:07 +00004064
Daniel Dunbar33063492009-09-07 00:20:42 +00004065 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbar33063492009-09-07 00:20:42 +00004066 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4067 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar01eb9b92009-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 Lattnerafd5eda2010-04-17 18:26:20 +00004070 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004071 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004072 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanianb9c5b3d2010-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 Lattnerafd5eda2010-04-17 18:26:20 +00004079
Daniel Dunbar33063492009-09-07 00:20:42 +00004080 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004081 }
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004082}
4083
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004084CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004085 : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00004086 ObjCTypes(cgm) {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004087 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004088 ObjCABI = 2;
4089}
4090
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004091/* *** */
4092
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004093ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004094 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004095 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4096 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004097
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004098 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004099 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004100 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004101 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00004102 Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004103
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004104 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004105 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004106 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004107
Mike Stumpf5408fe2009-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 Dunbar6efc0c52008-08-13 03:21:16 +00004110 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004111 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004112
Fariborz Jahanianee0af742009-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 Dunbar6bff2512009-08-03 17:06:42 +00004117
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004118 // FIXME: This is leaked.
4119 // FIXME: Merge with rewriter code?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004120
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004121 // struct _objc_super {
4122 // id self;
4123 // Class cls;
4124 // }
Abramo Bagnara465d41b2010-05-11 21:36:43 +00004125 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00004126 Ctx.getTranslationUnitDecl(),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004127 SourceLocation(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004128 &Ctx.Idents.get("_objc_super"));
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004129 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004130 Ctx.getObjCIdType(), 0, 0, false));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004131 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004132 Ctx.getObjCClassType(), 0, 0, false));
Douglas Gregor838db382010-02-11 01:19:42 +00004133 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004134
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004135 SuperCTy = Ctx.getTagDeclType(RD);
4136 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004137
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004138 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004139 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4140
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004141 // struct _prop_t {
4142 // char *name;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004143 // char *attributes;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004144 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004145 PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004146 CGM.getModule().addTypeName("struct._prop_t",
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004147 PropertyTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004148
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004149 // struct _prop_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004150 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004151 // uint32_t count_of_properties;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004152 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004153 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004154 PropertyListTy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004155 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004156 llvm::ArrayType::get(PropertyTy, 0),
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004157 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004158 CGM.getModule().addTypeName("struct._prop_list_t",
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004159 PropertyListTy);
4160 // struct _prop_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004161 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004162
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004163 // struct _objc_method {
4164 // SEL _cmd;
4165 // char *method_type;
4166 // char *_imp;
4167 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004168 MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004169 Int8PtrTy,
4170 Int8PtrTy,
4171 NULL);
4172 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004173
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004174 // struct _objc_cache *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004175 CacheTy = llvm::OpaqueType::get(VMContext);
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004176 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004177 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004178}
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004179
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004180ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004181 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004182 // struct _objc_method_description {
4183 // SEL name;
4184 // char *types;
4185 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004186 MethodDescriptionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004187 llvm::StructType::get(VMContext, SelectorPtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004188 Int8PtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004189 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004190 CGM.getModule().addTypeName("struct._objc_method_description",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004191 MethodDescriptionTy);
4192
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004193 // struct _objc_method_description_list {
4194 // int count;
4195 // struct _objc_method_description[1];
4196 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004197 MethodDescriptionListTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004198 llvm::StructType::get(VMContext, IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004199 llvm::ArrayType::get(MethodDescriptionTy, 0),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004200 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004201 CGM.getModule().addTypeName("struct._objc_method_description_list",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004202 MethodDescriptionListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004203
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004204 // struct _objc_method_description_list *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004205 MethodDescriptionListPtrTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004206 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004207
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004208 // Protocol description structures
4209
Fariborz Jahanian10a42312009-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 Dunbar6bff2512009-08-03 17:06:42 +00004216 ProtocolExtensionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004217 llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004218 MethodDescriptionListPtrTy,
4219 MethodDescriptionListPtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004220 PropertyListPtrTy,
4221 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004222 CGM.getModule().addTypeName("struct._objc_protocol_extension",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004223 ProtocolExtensionTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004224
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004225 // struct _objc_protocol_extension *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004226 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004227
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004228 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004229
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004230 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
4231 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004232
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004233 const llvm::Type *T =
Mike Stump1eb44332009-09-09 15:08:12 +00004234 llvm::StructType::get(VMContext,
Owen Anderson47a434f2009-08-05 23:18:46 +00004235 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004236 LongTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004237 llvm::ArrayType::get(ProtocolTyHolder, 0),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004238 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004239 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
4240
Fariborz Jahanian10a42312009-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 Anderson47a434f2009-08-05 23:18:46 +00004248 T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004249 Int8PtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004250 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Daniel Dunbar6efc0c52008-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 Dunbar6bff2512009-08-03 17:06:42 +00004257 CGM.getModule().addTypeName("struct._objc_protocol_list",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004258 ProtocolListTy);
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004259 // struct _objc_protocol_list *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004260 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004261
4262 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004263 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004264 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004265
4266 // Class description structures
4267
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004268 // struct _objc_ivar {
4269 // char *ivar_name;
4270 // char *ivar_type;
4271 // int ivar_offset;
4272 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004273 IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004274 Int8PtrTy,
4275 IntTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004276 NULL);
4277 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
4278
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004279 // struct _objc_ivar_list *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004280 IvarListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004281 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004282 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004283
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004284 // struct _objc_method_list *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004285 MethodListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004286 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004287 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004288
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004289 // struct _objc_class_extension *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004290 ClassExtensionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004291 llvm::StructType::get(VMContext, IntTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004292 Int8PtrTy,
4293 PropertyListPtrTy,
4294 NULL);
4295 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004296 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004297
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004298 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004299
Fariborz Jahanian10a42312009-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 Anderson47a434f2009-08-05 23:18:46 +00004314 T = llvm::StructType::get(VMContext,
4315 llvm::PointerType::getUnqual(ClassTyHolder),
Owen Anderson96e0fc72009-07-29 22:16:19 +00004316 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar27f9d772008-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 Dunbar6bff2512009-08-03 17:06:42 +00004329
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004330 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
4331 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004332 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004333
Fariborz Jahanian10a42312009-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 Anderson47a434f2009-08-05 23:18:46 +00004342 CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar86e253a2008-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 Dunbar27f9d772008-08-21 04:36:09 +00004352 // Global metadata structures
4353
Fariborz Jahanian10a42312009-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 Anderson47a434f2009-08-05 23:18:46 +00004361 SymtabTy = llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004362 SelectorPtrTy,
4363 ShortTy,
4364 ShortTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004365 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004366 NULL);
4367 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004368 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004369
Fariborz Jahaniandb286862009-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 Dunbar6bff2512009-08-03 17:06:42 +00004376 ModuleTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004377 llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004378 LongTy,
4379 Int8PtrTy,
4380 SymtabPtrTy,
4381 NULL);
4382 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00004383
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004384
Mike Stumpf5408fe2009-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 Carlsson124526b2008-09-09 10:10:21 +00004387 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004388
Anders Carlsson124526b2008-09-09 10:10:21 +00004389 // Exceptions
Owen Anderson96e0fc72009-07-29 22:16:19 +00004390 const llvm::Type *StackPtrTy = llvm::ArrayType::get(
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00004391 llvm::Type::getInt8PtrTy(VMContext), 4);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004392
4393 ExceptionDataTy =
Chris Lattner77b89b82010-06-27 07:15:29 +00004394 llvm::StructType::get(VMContext,
4395 llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
4396 SetJmpBufferSize),
Anders Carlsson124526b2008-09-09 10:10:21 +00004397 StackPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004398 CGM.getModule().addTypeName("struct._objc_exception_data",
Anders Carlsson124526b2008-09-09 10:10:21 +00004399 ExceptionDataTy);
4400
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00004401}
4402
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004403ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004404 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian30bc5712009-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 Anderson47a434f2009-08-05 23:18:46 +00004410 MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004411 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004412 llvm::ArrayType::get(MethodTy, 0),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004413 NULL);
4414 CGM.getModule().addTypeName("struct.__method_list_t",
4415 MethodListnfABITy);
4416 // struct method_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004417 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004418
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004419 // struct _protocol_t {
4420 // id isa; // NULL
4421 // const char * const protocol_name;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004422 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanian30bc5712009-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 Jahaniand55b6fc2009-01-23 01:46:23 +00004427 // const struct _prop_list_t * properties;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004428 // const uint32_t size; // sizeof(struct _protocol_t)
4429 // const uint32_t flags; // = 0
4430 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004431
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004432 // Holder for struct _protocol_list_t *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004433 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004434
Owen Anderson47a434f2009-08-05 23:18:46 +00004435 ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004436 Int8PtrTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004437 llvm::PointerType::getUnqual(
Fariborz Jahaniand55b6fc2009-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 Dunbar948e2582009-02-15 07:36:20 +00004449
4450 // struct _protocol_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004451 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004452
Fariborz Jahanianda320092009-01-29 19:24:30 +00004453 // struct _protocol_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004454 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar948e2582009-02-15 07:36:20 +00004455 // struct _protocol_t *[protocol_count];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004456 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004457 ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004458 llvm::ArrayType::get(
Daniel Dunbar948e2582009-02-15 07:36:20 +00004459 ProtocolnfABIPtrTy, 0),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004460 NULL);
4461 CGM.getModule().addTypeName("struct._objc_protocol_list",
4462 ProtocolListnfABITy);
Daniel Dunbar948e2582009-02-15 07:36:20 +00004463 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004464 ProtocolListnfABITy);
4465
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004466 // struct _objc_protocol_list*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004467 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004468
Fariborz Jahanian30bc5712009-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 Stump1eb44332009-09-09 15:08:12 +00004476 IvarnfABITy = llvm::StructType::get(VMContext,
Owen Anderson47a434f2009-08-05 23:18:46 +00004477 llvm::PointerType::getUnqual(LongTy),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004478 Int8PtrTy,
4479 Int8PtrTy,
4480 IntTy,
4481 IntTy,
4482 NULL);
4483 CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004484
Fariborz Jahanian30bc5712009-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 Anderson47a434f2009-08-05 23:18:46 +00004490 IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004491 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004492 llvm::ArrayType::get(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004493 IvarnfABITy, 0),
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004494 NULL);
4495 CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004496
Owen Anderson96e0fc72009-07-29 22:16:19 +00004497 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004498
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004499 // struct _class_ro_t {
Fariborz Jahanian30bc5712009-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 Dunbar6bff2512009-08-03 17:06:42 +00004512
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004513 // FIXME. Add 'reserved' field in 64bit abi mode!
Owen Anderson47a434f2009-08-05 23:18:46 +00004514 ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahaniand55b6fc2009-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 Dunbar6bff2512009-08-03 17:06:42 +00004527
Fariborz Jahaniand55b6fc2009-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 Anderson96e0fc72009-07-29 22:16:19 +00004532 ImpnfABITy = llvm::PointerType::getUnqual(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004533 llvm::FunctionType::get(ObjectPtrTy, Params, false));
4534
Fariborz Jahaniand55b6fc2009-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 Dunbar6bff2512009-08-03 17:06:42 +00004542
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004543 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Owen Andersona1cf15f2009-07-14 23:10:40 +00004544 ClassnfABITy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004545 llvm::StructType::get(VMContext,
4546 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar6bff2512009-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 Jahaniand55b6fc2009-01-23 01:46:23 +00004552 CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4553
4554 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004555 ClassnfABITy);
4556
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004557 // LLVM for struct _class_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004558 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004559
Fariborz Jahaniand55b6fc2009-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 Jahanian45c2ba02009-01-23 17:41:22 +00004567 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004568 CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004569 ClassnfABIPtrTy,
Fariborz Jahanian45c2ba02009-01-23 17:41:22 +00004570 MethodListnfABIPtrTy,
4571 MethodListnfABIPtrTy,
4572 ProtocolListnfABIPtrTy,
4573 PropertyListPtrTy,
4574 NULL);
4575 CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004576
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004577 // New types for nonfragile abi messaging.
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004578 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4579 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004580
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004581 // MessageRefTy - LLVM for:
4582 // struct _message_ref_t {
4583 // IMP messenger;
4584 // SEL name;
4585 // };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004586
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004587 // First the clang type for struct _message_ref_t
Abramo Bagnara465d41b2010-05-11 21:36:43 +00004588 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00004589 Ctx.getTranslationUnitDecl(),
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004590 SourceLocation(),
4591 &Ctx.Idents.get("_message_ref_t"));
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004592 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004593 Ctx.VoidPtrTy, 0, 0, false));
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004594 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004595 Ctx.getObjCSelType(), 0, 0, false));
Douglas Gregor838db382010-02-11 01:19:42 +00004596 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004597
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004598 MessageRefCTy = Ctx.getTagDeclType(RD);
4599 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4600 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004601
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004602 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004603 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004604
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004605 // SuperMessageRefTy - LLVM for:
4606 // struct _super_message_ref_t {
4607 // SUPER_IMP messenger;
4608 // SEL name;
4609 // };
Owen Anderson47a434f2009-08-05 23:18:46 +00004610 SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004611 SelectorPtrTy,
4612 NULL);
4613 CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004614
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004615 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004616 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4617
Daniel Dunbare588b992009-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 Anderson47a434f2009-08-05 23:18:46 +00004624 EHTypeTy = llvm::StructType::get(VMContext,
4625 llvm::PointerType::getUnqual(Int8PtrTy),
Daniel Dunbare588b992009-03-01 04:46:24 +00004626 Int8PtrTy,
4627 ClassnfABIPtrTy,
4628 NULL);
Daniel Dunbar4ff36842009-03-02 06:08:11 +00004629 CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004630 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00004631}
4632
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004633llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004634 FinishNonFragileABIModule();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004635
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004636 return NULL;
4637}
4638
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004639void CGObjCNonFragileABIMac::AddModuleClassList(const
4640 std::vector<llvm::GlobalValue*>
4641 &Container,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004642 const char *SymbolName,
4643 const char *SectionName) {
4644 unsigned NumClasses = Container.size();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004645
Daniel Dunbar463b8762009-05-15 21:48:48 +00004646 if (!NumClasses)
4647 return;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004648
Daniel Dunbar463b8762009-05-15 21:48:48 +00004649 std::vector<llvm::Constant*> Symbols(NumClasses);
4650 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00004651 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar463b8762009-05-15 21:48:48 +00004652 ObjCTypes.Int8PtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004653 llvm::Constant* Init =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004654 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004655 NumClasses),
4656 Symbols);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004657
Daniel Dunbar463b8762009-05-15 21:48:48 +00004658 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00004659 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004660 llvm::GlobalValue::InternalLinkage,
4661 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00004662 SymbolName);
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004663 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Daniel Dunbar463b8762009-05-15 21:48:48 +00004664 GV->setSection(SectionName);
Chris Lattnerad64e022009-07-17 23:57:13 +00004665 CGM.AddUsedGlobal(GV);
Daniel Dunbar463b8762009-05-15 21:48:48 +00004666}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004667
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004668void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4669 // nonfragile abi has no module definition.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004670
Daniel Dunbar463b8762009-05-15 21:48:48 +00004671 // Build list of all implemented class addresses in array
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004672 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004673 AddModuleClassList(DefinedClasses,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004674 "\01L_OBJC_LABEL_CLASS_$",
4675 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004676
Fariborz Jahaniana03d0dd2009-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 Jahaniana03d0dd2009-11-17 21:37:35 +00004682 }
4683
Fariborz Jahanian0e93d252009-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 Jahaniana03d0dd2009-11-17 21:37:35 +00004690
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004691 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004692 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4693 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004694
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004695 // Build list of all implemented category addresses in array
4696 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004697 AddModuleClassList(DefinedCategories,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004698 "\01L_OBJC_LABEL_CATEGORY_$",
4699 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004700 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004701 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4702 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004703
Daniel Dunbarfce176b2010-04-25 20:39:01 +00004704 EmitImageInfo();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004705}
4706
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004707/// LegacyDispatchedSelector - Returns true if SEL is not in the list of
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00004708/// NonLegacyDispatchMethods; false otherwise. What this means is that
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004709/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004710/// message dispatch call for all the rest.
4711///
4712bool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) {
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004713 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
4714 default:
4715 assert(0 && "Invalid dispatch method!");
4716 case CodeGenOptions::Legacy:
Daniel Dunbar2feefe82010-02-01 21:07:33 +00004717 return true;
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004718 case CodeGenOptions::NonLegacy:
Fariborz Jahanian776dbf92010-04-19 17:53:30 +00004719 return false;
Daniel Dunbarf643b9b2010-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 Jahanian4523eb02009-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 Dunbar6bff2512009-08-03 17:06:42 +00004737
Fariborz Jahanian4523eb02009-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 Dunbar6bff2512009-08-03 17:06:42 +00004746 // "countByEnumeratingWithState:objects:count"
Fariborz Jahanianbe53be42009-05-13 16:19:02 +00004747 IdentifierInfo *KeyIdents[] = {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004748 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4749 &CGM.getContext().Idents.get("objects"),
4750 &CGM.getContext().Idents.get("count")
Fariborz Jahanianbe53be42009-05-13 16:19:02 +00004751 };
4752 NonLegacyDispatchMethods.insert(
4753 CGM.getContext().Selectors.getSelector(3, KeyIdents));
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004754 }
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004755
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00004756 return (NonLegacyDispatchMethods.count(Sel) == 0);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004757}
4758
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004759// Metadata flags
4760enum MetaDataDlags {
4761 CLS = 0x0,
4762 CLS_META = 0x1,
4763 CLS_ROOT = 0x2,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004764 OBJC2_CLS_HIDDEN = 0x10,
Fariborz Jahanian058a1b72009-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 Jahanianda320092009-01-29 19:24:30 +00004776/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian058a1b72009-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 Dunbar6bff2512009-08-03 17:06:42 +00004783 unsigned flags,
4784 unsigned InstanceStart,
4785 unsigned InstanceSize,
4786 const ObjCImplementationDecl *ID) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004787 std::string ClassName = ID->getNameAsString();
4788 std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
Owen Anderson4a28d5d2009-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 Jahanian058a1b72009-01-24 20:21:50 +00004792 // FIXME. For 64bit targets add 0 here.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004793 Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4794 : BuildIvarLayout(ID, true);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004795 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian493dab72009-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 Dunbar6bff2512009-08-03 17:06:42 +00004801 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004802 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-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 Dunbar6bff2512009-08-03 17:06:42 +00004808 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004809 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004810 // Instance methods should always be defined.
4811 Methods.push_back(GetMethodConstant(*i));
4812 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004813 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004814 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004815 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004816
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004817 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4818 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004819
Fariborz Jahanian939abce2009-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 Jahanian493dab72009-01-26 21:38:32 +00004828 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004829 Values[ 5] = EmitMethodList(MethodListName,
4830 "__DATA, __objc_const", Methods);
4831
Fariborz Jahanianda320092009-01-29 19:24:30 +00004832 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4833 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004834 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004835 + OID->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00004836 OID->protocol_begin(),
4837 OID->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004838
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00004839 if (flags & CLS_META)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004840 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00004841 else
4842 Values[ 7] = EmitIvarList(ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004843 Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4844 : BuildIvarLayout(ID, false);
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00004845 if (flags & CLS_META)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004846 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00004847 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004848 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4849 ID, ID->getClassInterface(), ObjCTypes);
Owen Anderson08e25242009-07-27 22:29:56 +00004850 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004851 Values);
4852 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar6bff2512009-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 Jahanian09796d62009-01-31 02:43:27 +00004859 CLASS_RO_GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004860 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00004861 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004862 return CLASS_RO_GV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00004863
Fariborz Jahanian058a1b72009-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 Jahanian84394a52009-01-24 21:21:53 +00004876llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar6bff2512009-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 Jahanian058a1b72009-01-24 20:21:50 +00004882 std::vector<llvm::Constant*> Values(5);
4883 Values[0] = IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004884 Values[1] = SuperClassGV;
4885 if (!Values[1])
4886 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004887 Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
4888 Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4889 Values[4] = ClassRoGV; // &CLASS_RO_GV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004890 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004891 Values);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004892 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4893 GV->setInitializer(Init);
Fariborz Jahaniandd0db2a2009-01-31 01:07:39 +00004894 GV->setSection("__DATA, __objc_data");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00004895 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004896 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004897 if (HiddenVisibility)
4898 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004899 return GV;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004900}
4901
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004902bool
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00004903CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004904 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004905}
4906
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00004907void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00004908 uint32_t &InstanceStart,
4909 uint32_t &InstanceSize) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004910 const ASTRecordLayout &RL =
Daniel Dunbarb4c79e02009-05-04 21:26:30 +00004911 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004912
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00004913 // InstanceSize is really instance end.
Anders Carlsson243a6852009-07-18 21:26:44 +00004914 InstanceSize = llvm::RoundUpToAlignment(RL.getDataSize(), 8) / 8;
Daniel Dunbar6e8575b2009-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 Dunbarb02532a2009-04-19 23:41:48 +00004921}
4922
Fariborz Jahanianaa23b572009-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 Dunbar6bff2512009-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 Jahanianaa23b572009-01-23 23:53:38 +00004934 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004935 CGM.getModule(),
4936 ObjCTypes.ImpnfABITy,
4937 false,
4938 llvm::GlobalValue::ExternalLinkage,
4939 0,
4940 "_objc_empty_vtable");
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004941 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004942 assert(ID->getClassInterface() &&
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004943 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbar6c1aac82009-04-20 20:18:54 +00004944 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004945 uint32_t InstanceStart =
Duncan Sands9408c452009-05-09 07:08:47 +00004946 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004947 uint32_t InstanceSize = InstanceStart;
4948 uint32_t flags = CLS_META;
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00004949 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4950 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004951
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004952 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004953
4954 bool classIsHidden =
Daniel Dunbar04d40782009-04-14 06:00:08 +00004955 CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004956 if (classIsHidden)
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004957 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00004958 if (ID->getNumIvarInitializers())
4959 flags |= eClassFlags_ABI2_HasCXXStructors;
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004960 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004961 // class is root
4962 flags |= CLS_ROOT;
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004963 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004964 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004965 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004966 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004967 const ObjCInterfaceDecl *Root = ID->getClassInterface();
4968 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4969 Root = Super;
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004970 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004971 if (Root->hasAttr<WeakImportAttr>())
4972 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004973 // work on super class metadata symbol.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004974 std::string SuperClassName =
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004975 ObjCMetaClassName +
4976 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004977 SuperClassGV = GetClassGlobal(SuperClassName);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004978 if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
4979 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004980 }
4981 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4982 InstanceStart,
4983 InstanceSize,ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004984 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004985 llvm::GlobalVariable *MetaTClass =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004986 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4987 classIsHidden);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004988 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00004989
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004990 // Metadata for the class
4991 flags = CLS;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004992 if (classIsHidden)
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004993 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00004994 if (ID->getNumIvarInitializers())
4995 flags |= eClassFlags_ABI2_HasCXXStructors;
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004996
Douglas Gregor68584ed2009-06-18 16:11:24 +00004997 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004998 flags |= CLS_EXCEPTION;
4999
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005000 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005001 flags |= CLS_ROOT;
5002 SuperClassGV = 0;
Chris Lattnerb7b58b12009-04-19 06:02:28 +00005003 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005004 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00005005 std::string RootClassName =
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005006 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005007 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005008 if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
5009 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005010 }
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005011 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005012 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00005013 InstanceStart,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005014 InstanceSize,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00005015 ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005016
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005017 TClassName = ObjCClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005018 llvm::GlobalVariable *ClassMD =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005019 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5020 classIsHidden);
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00005021 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005022
Daniel Dunbar74d4b122009-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 Dunbar8158a2f2009-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 Jahanianaa23b572009-01-23 23:53:38 +00005030}
5031
Fariborz Jahanian8cfd3972009-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 Dunbar6bff2512009-08-03 17:06:42 +00005041 const ObjCProtocolDecl *PD) {
5042
Fariborz Jahanian960cd062009-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 Dunbar6bff2512009-08-03 17:06:42 +00005046 llvm::Constant *Init =
5047 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5048 ObjCTypes.ExternalProtocolPtrTy);
5049
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005050 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
5051 ProtocolName += PD->getNameAsCString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005052
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005053 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5054 if (PTGV)
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005055 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005056 PTGV = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005057 CGM.getModule(),
5058 Init->getType(), false,
5059 llvm::GlobalValue::WeakAnyLinkage,
5060 Init,
5061 ProtocolName);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005062 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5063 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005064 CGM.AddUsedGlobal(PTGV);
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005065 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005066}
5067
Fariborz Jahanianeb062d92009-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 Dunbar74d4b122009-05-15 22:33:15 +00005078void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005079 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005080 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005081 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5082 "_$_" + OCD->getNameAsString());
5083 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005084 Interface->getNameAsString());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005085
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005086 std::vector<llvm::Constant*> Values(6);
5087 Values[0] = GetClassName(OCD->getIdentifier());
5088 // meta-class entry symbol
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005089 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Fariborz Jahanian2cdcc4c2009-11-17 22:02:21 +00005090 if (Interface->hasAttr<WeakImportAttr>())
5091 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5092
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005093 Values[1] = ClassGV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005094 std::vector<llvm::Constant*> Methods;
5095 std::string MethodListName(Prefix);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005096 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005097 "_$_" + OCD->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005098
5099 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005100 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005101 // Instance methods should always be defined.
5102 Methods.push_back(GetMethodConstant(*i));
5103 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005104
5105 Values[2] = EmitMethodList(MethodListName,
5106 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005107 Methods);
5108
5109 MethodListName = Prefix;
5110 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5111 OCD->getNameAsString();
5112 Methods.clear();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005113 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005114 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005115 // Class methods should always be defined.
5116 Methods.push_back(GetMethodConstant(*i));
5117 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005118
5119 Values[3] = EmitMethodList(MethodListName,
5120 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005121 Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005122 const ObjCCategoryDecl *Category =
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00005123 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005124 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005125 llvm::SmallString<256> ExtName;
5126 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5127 << OCD->getName();
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005128 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005129 + Interface->getName() + "_$_"
5130 + Category->getName(),
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005131 Category->protocol_begin(),
5132 Category->protocol_end());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005133 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5134 OCD, Category, ObjCTypes);
Mike Stumpb3589f42009-07-30 22:28:39 +00005135 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00005136 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5137 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005138 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005139
5140 llvm::Constant *Init =
5141 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005142 Values);
5143 llvm::GlobalVariable *GCATV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005144 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005145 false,
5146 llvm::GlobalValue::InternalLinkage,
5147 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005148 ExtCatName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005149 GCATV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005150 CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005151 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerad64e022009-07-17 23:57:13 +00005152 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005153 DefinedCategories.push_back(GCATV);
Daniel Dunbar74d4b122009-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 Jahanianeb062d92009-01-26 18:32:24 +00005158}
Fariborz Jahanian493dab72009-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 Dunbar6bff2512009-08-03 17:06:42 +00005164 const ObjCMethodDecl *MD) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005165 // FIXME: Use DenseMap::lookup
5166 llvm::Function *Fn = MethodDefinitions[MD];
5167 if (!Fn)
5168 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005169
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005170 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005171 Method[0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00005172 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005173 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005174 Method[1] = GetMethodVarType(MD);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005175 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005176 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian493dab72009-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 Dunbar9c29bf52009-10-18 20:48:59 +00005186llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
5187 const char *Section,
5188 const ConstantVector &Methods) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005189 // Return null for empty list.
5190 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00005191 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005192
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005193 std::vector<llvm::Constant*> Values(3);
5194 // sizeof(struct _objc_method)
Duncan Sands9408c452009-05-09 07:08:47 +00005195 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005196 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005197 // method_count
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005198 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00005199 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005200 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00005201 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005202 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005203
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005204 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005205 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005206 llvm::GlobalValue::InternalLinkage,
5207 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005208 Name);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005209 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005210 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005211 GV->setSection(Section);
Chris Lattnerad64e022009-07-17 23:57:13 +00005212 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005213 return llvm::ConstantExpr::getBitCast(GV,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005214 ObjCTypes.MethodListnfABIPtrTy);
5215}
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005216
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005217/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5218/// the given ivar.
Daniel Dunbare83be122010-04-02 21:14:02 +00005219llvm::GlobalVariable *
5220CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5221 const ObjCIvarDecl *Ivar) {
5222 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbara81419d2009-05-05 00:36:57 +00005223 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregor6ab35242009-04-09 21:40:53 +00005224 '.' + Ivar->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005225 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005226 CGM.getModule().getGlobalVariable(Name);
5227 if (!IvarOffsetGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005228 IvarOffsetGV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005229 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005230 false,
5231 llvm::GlobalValue::ExternalLinkage,
5232 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00005233 Name);
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005234 return IvarOffsetGV;
5235}
5236
Daniel Dunbare83be122010-04-02 21:14:02 +00005237llvm::Constant *
5238CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5239 const ObjCIvarDecl *Ivar,
5240 unsigned long int Offset) {
Daniel Dunbar737c5022009-04-19 00:44:02 +00005241 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005242 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar737c5022009-04-19 00:44:02 +00005243 Offset));
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005244 IvarOffsetGV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005245 CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbar737c5022009-04-19 00:44:02 +00005246
Mike Stumpf5408fe2009-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 Dunbar737c5022009-04-19 00:44:02 +00005249 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5250 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
5251 CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden)
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00005252 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar04d40782009-04-14 06:00:08 +00005253 else
Fariborz Jahanian77c9fd22009-04-06 18:30:00 +00005254 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005255 IvarOffsetGV->setSection("__DATA, __objc_const");
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005256 return IvarOffsetGV;
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005257}
5258
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005259/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar11394522009-04-18 08:51:00 +00005260/// implementation. The return value has type
Fariborz Jahanian98abf4b2009-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 Dunbar3e5f0d82009-04-20 06:54:31 +00005275
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005276llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005277 const ObjCImplementationDecl *ID) {
5278
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005279 std::vector<llvm::Constant*> Ivars, Ivar(5);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005280
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005281 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5282 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005283
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005284 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005285
Daniel Dunbar91636d62009-04-20 00:33:43 +00005286 // Collect declared and synthesized ivars in a small vector.
Fariborz Jahanian18191882009-03-31 18:11:23 +00005287 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00005288 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005289
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00005290 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
5291 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00005292 // Ignore unnamed bit-fields.
5293 if (!IVD->getDeclName())
5294 continue;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005295 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005296 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00005297 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5298 Ivar[2] = GetMethodVarType(IVD);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005299 const llvm::Type *FieldTy =
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00005300 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Duncan Sands9408c452009-05-09 07:08:47 +00005301 unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005302 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005303 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005304 Align = llvm::Log2_32(Align);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005305 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbar91636d62009-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 Anderson4a28d5d2009-07-24 23:12:58 +00005311 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson08e25242009-07-27 22:29:56 +00005312 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005313 }
5314 // Return null for empty list.
5315 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00005316 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005317 std::vector<llvm::Constant*> Values(3);
Duncan Sands9408c452009-05-09 07:08:47 +00005318 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Anderson4a28d5d2009-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 Anderson96e0fc72009-07-29 22:16:19 +00005321 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005322 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00005323 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005324 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005325 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5326 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005327 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005328 llvm::GlobalValue::InternalLinkage,
5329 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005330 Prefix + OID->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005331 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005332 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005333 GV->setSection("__DATA, __objc_const");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005334
Chris Lattnerad64e022009-07-17 23:57:13 +00005335 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005336 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005337}
5338
5339llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005340 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005341 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005342
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00005347 Entry =
5348 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5349 llvm::GlobalValue::ExternalLinkage,
5350 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005351 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianda320092009-01-29 19:24:30 +00005352 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00005353 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005354
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00005376 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005377 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005378
Fariborz Jahanianda320092009-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 Jahanianda320092009-01-29 19:24:30 +00005383 // Construct method lists.
5384 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5385 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005386 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005387 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005388 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005389 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005390 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5391 OptInstanceMethods.push_back(C);
5392 } else {
5393 InstanceMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005394 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00005395 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005396
5397 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005398 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005399 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005400 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005401 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5402 OptClassMethods.push_back(C);
5403 } else {
5404 ClassMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005405 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00005406 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005407
Fariborz Jahanianda320092009-01-29 19:24:30 +00005408 std::vector<llvm::Constant*> Values(10);
5409 // isa is NULL
Owen Andersonc9c88b42009-07-31 20:28:54 +00005410 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005411 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005412 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5413 PD->protocol_begin(),
5414 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005415
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005416 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005417 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005418 "__DATA, __objc_const",
5419 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005420 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005421 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005422 "__DATA, __objc_const",
5423 ClassMethods);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005424 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005425 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005426 "__DATA, __objc_const",
5427 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005428 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005429 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005430 "__DATA, __objc_const",
5431 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005432 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005433 0, PD, ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005434 uint32_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00005435 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005436 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Andersonc9c88b42009-07-31 20:28:54 +00005437 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005438 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanianda320092009-01-29 19:24:30 +00005439 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005440
Fariborz Jahanianda320092009-01-29 19:24:30 +00005441 if (Entry) {
5442 // Already created, fix the linkage and update the initializer.
Mike Stump286acbd2009-03-07 16:33:28 +00005443 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005444 Entry->setInitializer(Init);
5445 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005446 Entry =
Daniel Dunbar9c29bf52009-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 Jahanian09796d62009-01-31 02:43:27 +00005450 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005451 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanianda320092009-01-29 19:24:30 +00005452 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00005453 }
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005454 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005455 CGM.AddUsedGlobal(Entry);
5456
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005457 // Use this protocol meta-data to build protocol list table in section
5458 // __DATA, __objc_protolist
Daniel Dunbar9c29bf52009-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 Jahanian09796d62009-01-31 02:43:27 +00005463 PTGV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005464 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbar0bf21992009-04-15 02:56:18 +00005465 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005466 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005467 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanianda320092009-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 Dunbar9c29bf52009-10-18 20:48:59 +00005480CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
5481 ObjCProtocolDecl::protocol_iterator begin,
5482 ObjCProtocolDecl::protocol_iterator end) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005483 std::vector<llvm::Constant*> ProtocolRefs;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005484
Fariborz Jahanianda320092009-01-29 19:24:30 +00005485 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005486 if (begin == end)
Owen Andersonc9c88b42009-07-31 20:28:54 +00005487 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005488
Daniel Dunbar948e2582009-02-15 07:36:20 +00005489 // FIXME: We shouldn't need to do this lookup here, should we?
Daniel Dunbar9c29bf52009-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 Jahanianda320092009-01-29 19:24:30 +00005494 if (GV)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005495 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005496
Daniel Dunbar948e2582009-02-15 07:36:20 +00005497 for (; begin != end; ++begin)
5498 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5499
Fariborz Jahanianda320092009-01-29 19:24:30 +00005500 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00005501 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005502 ObjCTypes.ProtocolnfABIPtrTy));
5503
Fariborz Jahanianda320092009-01-29 19:24:30 +00005504 std::vector<llvm::Constant*> Values(2);
Owen Andersona1cf15f2009-07-14 23:10:40 +00005505 Values[0] =
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005506 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005507 Values[1] =
Owen Anderson7db6d832009-07-28 18:33:04 +00005508 llvm::ConstantArray::get(
Owen Anderson96e0fc72009-07-29 22:16:19 +00005509 llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005510 ProtocolRefs.size()),
5511 ProtocolRefs);
5512
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005513 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Owen Anderson1c431b32009-07-08 19:05:04 +00005514 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanianda320092009-01-29 19:24:30 +00005515 llvm::GlobalValue::InternalLinkage,
5516 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005517 Name);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005518 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005519 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005520 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Chris Lattnerad64e022009-07-17 23:57:13 +00005521 CGM.AddUsedGlobal(GV);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005522 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar948e2582009-02-15 07:36:20 +00005523 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005524}
5525
Fariborz Jahanian3819a0b2009-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 Andersona1cf15f2009-07-14 23:10:40 +00005536 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005537 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5538 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005539 Desc[1] = GetMethodVarType(MD);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005540 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00005541 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005542 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005543}
Fariborz Jahanian45012a72009-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 Dunbar6bff2512009-08-03 17:06:42 +00005550///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00005551LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall506b57e2010-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 Dunbar97776872009-04-22 07:32:20 +00005558 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5559 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005560}
5561
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00005562llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005563 CodeGen::CodeGenFunction &CGF,
5564 const ObjCInterfaceDecl *Interface,
5565 const ObjCIvarDecl *Ivar) {
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005566 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00005567}
5568
Fariborz Jahanian46551122009-02-04 00:22:57 +00005569CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005570 CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00005571 ReturnValueSlot Return,
Daniel Dunbar6bff2512009-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 Stumpf5408fe2009-05-16 07:57:57 +00005578 // FIXME. Even though IsSuper is passes. This function doese not handle calls
5579 // to 'super' receivers.
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005580 CodeGenTypes &Types = CGM.getTypes();
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005581 llvm::Value *Arg0 = Receiver;
5582 if (!IsSuper)
5583 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005584
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005585 // Find the message function name.
Mike Stumpf5408fe2009-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 McCallead608a2010-02-26 00:48:12 +00005588 const CGFunctionInfo &FnInfo
Rafael Espindola264ba482010-03-30 20:24:48 +00005589 = Types.getFunctionInfo(ResultType, CallArgList(),
5590 FunctionType::ExtInfo());
Fariborz Jahanian70b51c72009-04-30 23:08:58 +00005591 llvm::Constant *Fn = 0;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005592 std::string Name("\01l_");
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00005593 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
Fariborz Jahanianc1708522009-02-05 18:00:27 +00005594#if 0
5595 // unlike what is documented. gcc never generates this API!!
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005596 if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
Chris Lattner1c02f862009-04-22 02:53:24 +00005597 Fn = ObjCTypes.getMessageSendIdStretFixupFn();
Fariborz Jahanian83a8a752009-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 Stumpb3589f42009-07-30 22:28:39 +00005601 } else
Fariborz Jahanianc1708522009-02-05 18:00:27 +00005602#endif
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005603 if (IsSuper) {
Chris Lattner1c02f862009-04-22 02:53:24 +00005604 Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005605 Name += "objc_msgSendSuper2_stret_fixup";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005606 } else {
5607 Fn = ObjCTypes.getMessageSendStretFixupFn();
5608 Name += "objc_msgSend_stret_fixup";
5609 }
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00005610 } else if (!IsSuper && CGM.ReturnTypeUsesFPRet(ResultType)) {
5611 Fn = ObjCTypes.getMessageSendFpretFixupFn();
5612 Name += "objc_msgSend_fpret_fixup";
Mike Stumpb3589f42009-07-30 22:28:39 +00005613 } else {
Fariborz Jahanianc1708522009-02-05 18:00:27 +00005614#if 0
5615// unlike what is documented. gcc never generates this API!!
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005616 if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
Chris Lattner1c02f862009-04-22 02:53:24 +00005617 Fn = ObjCTypes.getMessageSendIdFixupFn();
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005618 Name += "objc_msgSendId_fixup";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005619 } else
Fariborz Jahanianc1708522009-02-05 18:00:27 +00005620#endif
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005621 if (IsSuper) {
Chris Lattner1c02f862009-04-22 02:53:24 +00005622 Fn = ObjCTypes.getMessageSendSuper2FixupFn();
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005623 Name += "objc_msgSendSuper2_fixup";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005624 } else {
5625 Fn = ObjCTypes.getMessageSendFixupFn();
5626 Name += "objc_msgSend_fixup";
5627 }
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005628 }
Fariborz Jahanian70b51c72009-04-30 23:08:58 +00005629 assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend");
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005630 Name += '_';
5631 std::string SelName(Sel.getAsString());
5632 // Replace all ':' in selector name with '_' ouch!
Mike Stump1eb44332009-09-09 15:08:12 +00005633 for (unsigned i = 0; i < SelName.size(); i++)
Fariborz Jahanian83a8a752009-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 Dunbar33af70f2009-04-15 19:03:14 +00005639 // Build message ref table entry.
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005640 std::vector<llvm::Constant*> Values(2);
5641 Values[0] = Fn;
5642 Values[1] = GetMethodVarName(Sel);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005643 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Owen Anderson1c431b32009-07-08 19:05:04 +00005644 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Mike Stump286acbd2009-03-07 16:33:28 +00005645 llvm::GlobalValue::WeakAnyLinkage,
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005646 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005647 Name);
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005648 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf59c1a62009-04-15 19:04:46 +00005649 GV->setAlignment(16);
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005650 GV->setSection("__DATA, __objc_msgrefs, coalesced");
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005651 }
5652 llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005653
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005654 CallArgList ActualArgs;
5655 ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005656 ActualArgs.push_back(std::make_pair(RValue::get(Arg1),
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005657 ObjCTypes.MessageRefCPtrTy));
5658 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
John McCall04a67a62010-02-05 21:31:56 +00005659 const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindola264ba482010-03-30 20:24:48 +00005660 FunctionType::ExtInfo());
Fariborz Jahanianef163782009-02-05 01:13:09 +00005661 llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0);
5662 Callee = CGF.Builder.CreateLoad(Callee);
Fariborz Jahanian3ab75bd2009-02-14 21:25:36 +00005663 const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true);
Fariborz Jahanianef163782009-02-05 01:13:09 +00005664 Callee = CGF.Builder.CreateBitCast(Callee,
Owen Anderson96e0fc72009-07-29 22:16:19 +00005665 llvm::PointerType::getUnqual(FTy));
John McCallef072fd2010-05-22 01:48:05 +00005666 return CGF.EmitCall(FnInfo1, Callee, Return, ActualArgs);
Fariborz Jahanian46551122009-02-04 00:22:57 +00005667}
5668
5669/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005670CodeGen::RValue
5671CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00005672 ReturnValueSlot Return,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005673 QualType ResultType,
5674 Selector Sel,
5675 llvm::Value *Receiver,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005676 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00005677 const ObjCInterfaceDecl *Class,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005678 const ObjCMethodDecl *Method) {
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00005679 return LegacyDispatchedSelector(Sel)
John McCallef072fd2010-05-22 01:48:05 +00005680 ? EmitLegacyMessageSend(CGF, Return, ResultType,
5681 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005682 Receiver, CGF.getContext().getObjCIdType(),
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005683 false, CallArgs, Method, ObjCTypes)
John McCallef072fd2010-05-22 01:48:05 +00005684 : EmitMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005685 Receiver, CGF.getContext().getObjCIdType(),
5686 false, CallArgs);
Fariborz Jahanian46551122009-02-04 00:22:57 +00005687}
5688
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005689llvm::GlobalVariable *
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005690CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005691 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5692
Daniel Dunbardfff2302009-03-02 05:18:14 +00005693 if (!GV) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005694 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005695 false, llvm::GlobalValue::ExternalLinkage,
5696 0, Name);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005697 }
5698
5699 return GV;
5700}
5701
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005702llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5703 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005704 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005705
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005706 if (!Entry) {
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005707 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005708 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005709 Entry =
5710 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005711 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005712 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005713 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005714 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005715 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005716 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00005717 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005718 CGM.AddUsedGlobal(Entry);
Daniel Dunbar11394522009-04-18 08:51:00 +00005719 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005720
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005721 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar11394522009-04-18 08:51:00 +00005722}
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005723
Daniel Dunbar11394522009-04-18 08:51:00 +00005724llvm::Value *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005725CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00005726 const ObjCInterfaceDecl *ID) {
5727 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005728
Daniel Dunbar11394522009-04-18 08:51:00 +00005729 if (!Entry) {
5730 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5731 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005732 Entry =
5733 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005734 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005735 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005736 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar11394522009-04-18 08:51:00 +00005737 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005738 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005739 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00005740 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005741 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005742 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005743
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005744 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005745}
5746
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005747/// EmitMetaClassRef - Return a Value * of the address of _class_t
5748/// meta-data
5749///
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005750llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5751 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005752 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5753 if (Entry)
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005754 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005755
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005756 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005757 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005758 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00005759 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005760 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005761 MetaClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005762 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005763 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005764 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005765 ObjCTypes.ClassnfABIPtrTy));
5766
Daniel Dunbar33af70f2009-04-15 19:03:14 +00005767 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005768 CGM.AddUsedGlobal(Entry);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005769
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005770 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005771}
5772
Fariborz Jahanian0e81f4b2009-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 Jahanian269f8bc2009-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 Jahanian0e81f4b2009-02-05 20:41:40 +00005783 return EmitClassRef(Builder, ID);
5784}
5785
Fariborz Jahanian7a06aae2009-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 McCallef072fd2010-05-22 01:48:05 +00005791 ReturnValueSlot Return,
Daniel Dunbar6bff2512009-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 Dunbard6c93d72009-09-17 04:01:22 +00005798 const CodeGen::CallArgList &CallArgs,
5799 const ObjCMethodDecl *Method) {
Fariborz Jahanian7a06aae2009-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 Dunbar6bff2512009-08-03 17:06:42 +00005805
Fariborz Jahanian7a06aae2009-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 Dunbar6bff2512009-08-03 17:06:42 +00005810
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005811 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanian7ce77922009-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 Dunbar11394522009-04-18 08:51:00 +00005817 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005818 Target = CGF.Builder.CreateStructGEP(Target, 0);
5819 Target = CGF.Builder.CreateLoad(Target);
Mike Stumpb3589f42009-07-30 22:28:39 +00005820 } else
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005821 Target = EmitMetaClassRef(CGF.Builder, Class);
Mike Stumpb3589f42009-07-30 22:28:39 +00005822 } else
Daniel Dunbar11394522009-04-18 08:51:00 +00005823 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005824
Mike Stumpf5408fe2009-05-16 07:57:57 +00005825 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5826 // ObjCTypes types.
Fariborz Jahanian7a06aae2009-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 Dunbar6bff2512009-08-03 17:06:42 +00005832
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00005833 return (LegacyDispatchedSelector(Sel))
John McCallef072fd2010-05-22 01:48:05 +00005834 ? EmitLegacyMessageSend(CGF, Return, ResultType,
5835 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005836 ObjCSuper, ObjCTypes.SuperPtrCTy,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005837 true, CallArgs, Method, ObjCTypes)
John McCallef072fd2010-05-22 01:48:05 +00005838 : EmitMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005839 ObjCSuper, ObjCTypes.SuperPtrCTy,
5840 true, CallArgs);
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005841}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005842
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005843llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian03b29602010-06-17 19:56:20 +00005844 Selector Sel, bool lval) {
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005845 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005846
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005847 if (!Entry) {
Daniel Dunbar6bff2512009-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 Jahaniand0f8a8d2009-05-11 19:25:47 +00005855 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005856 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005857 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005858
Fariborz Jahanian03b29602010-06-17 19:56:20 +00005859 if (lval)
5860 return Entry;
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005861 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005862}
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005863/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005864/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005865///
5866void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005867 llvm::Value *src,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005868 llvm::Value *dst,
5869 llvm::Value *ivarOffset) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005870 const llvm::Type * SrcTy = src->getType();
5871 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005872 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Jahanian3b8a6522009-03-13 00:42:52 +00005876 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5877 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005878 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5879 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005880 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5881 src, dst, ivarOffset);
Fariborz Jahanian6948aea2009-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 Dunbar6bff2512009-08-03 17:06:42 +00005889 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005890 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005891 const llvm::Type * SrcTy = src->getType();
5892 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005893 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00005896 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005897 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5898 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005899 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5900 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00005901 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005902 src, dst, "weakassign");
5903 return;
5904}
5905
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005906void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005907 CodeGen::CodeGenFunction &CGF,
5908 llvm::Value *DestPtr,
5909 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00005910 llvm::Value *Size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005911 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5912 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005913 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00005914 DestPtr, SrcPtr, Size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005915 return;
5916}
5917
Fariborz Jahanian6948aea2009-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 Dunbar6bff2512009-08-03 17:06:42 +00005922 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005923 llvm::Value *AddrWeakObj) {
Eli Friedman8339b352009-03-07 03:57:15 +00005924 const llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005925 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5926 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00005927 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005928 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00005929 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6948aea2009-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 Stump1eb44332009-09-09 15:08:12 +00005937 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005938 const llvm::Type * SrcTy = src->getType();
5939 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005940 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Jahanian3b8a6522009-03-13 00:42:52 +00005944 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5945 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005946 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5947 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00005948 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian6948aea2009-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 Jahanian021a7a62010-07-20 20:30:03 +00005957 llvm::Value *src, llvm::Value *dst,
5958 bool threadlocal) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005959 const llvm::Type * SrcTy = src->getType();
5960 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005961 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Jahanian3b8a6522009-03-13 00:42:52 +00005965 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5966 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005967 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5968 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-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 Jahanian6948aea2009-02-16 22:52:32 +00005975 return;
5976}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005977
John McCall740e8072010-07-21 00:41:47 +00005978namespace {
John McCall1f0fca52010-07-21 07:22:38 +00005979 struct CallSyncExit : EHScopeStack::Cleanup {
John McCall740e8072010-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 Dunbar6bff2512009-08-03 17:06:42 +00005991void
John McCallf1549f62010-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 Dunbar8ecbaf22009-02-24 07:47:38 +00005996
John McCallf1549f62010-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 McCall1f0fca52010-07-21 07:22:38 +00006003 CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup,
6004 ObjCTypes.getSyncExitFn(),
6005 SyncArg);
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006006
John McCallf1549f62010-07-06 01:34:17 +00006007 // Emit the body of the statement.
6008 CGF.EmitStmt(S.getSynchBody());
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006009
John McCallf1549f62010-07-06 01:34:17 +00006010 // Pop the lock-release cleanup.
6011 CGF.PopCleanupBlock();
6012}
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006013
John McCallf1549f62010-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 McCall8e3f8612010-07-13 22:12:14 +00006021
John McCall1f0fca52010-07-21 07:22:38 +00006022 struct CallObjCEndCatch : EHScopeStack::Cleanup {
John McCall8e3f8612010-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 McCallf1549f62010-07-06 01:34:17 +00006037}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006038
John McCall5a180392010-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 McCallf1549f62010-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 Dunbar4ff36842009-03-02 06:08:11 +00006070
John McCallf1549f62010-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 Dunbar4ff36842009-03-02 06:08:11 +00006077
John McCallf1549f62010-07-06 01:34:17 +00006078 llvm::SmallVector<CatchHandler, 8> Handlers;
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006079
John McCallf1549f62010-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 Gregorc00d8e12010-04-26 16:46:50 +00006084 const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006085
John McCallf1549f62010-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 Gregor8f5e3dd2010-04-23 22:50:49 +00006093 if (!CatchDecl) {
John McCallf1549f62010-07-06 01:34:17 +00006094 Handler.TypeInfo = 0; // catch-all
6095 // Don't consider any other catches.
Douglas Gregor8f5e3dd2010-04-23 22:50:49 +00006096 break;
6097 }
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006098
John McCall5a180392010-07-24 00:37:23 +00006099 Handler.TypeInfo = GetEHType(CatchDecl->getType());
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006100 }
John McCallf1549f62010-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 Dunbar4ff36842009-03-02 06:08:11 +00006105 }
John McCallf1549f62010-07-06 01:34:17 +00006106
6107 // Emit the try body.
6108 CGF.EmitStmt(S.getTryBody());
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006109
John McCallf1549f62010-07-06 01:34:17 +00006110 // Leave the try.
6111 if (S.getNumCatchStmts())
6112 CGF.EHStack.popCatch();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006113
John McCallf1549f62010-07-06 01:34:17 +00006114 // Remember where we were.
6115 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006116
John McCallf1549f62010-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 Dunbar4ff36842009-03-02 06:08:11 +00006120
John McCallf1549f62010-07-06 01:34:17 +00006121 CGF.EmitBlock(Handler.Block);
6122 llvm::Value *RawExn = CGF.Builder.CreateLoad(CGF.getExceptionSlot());
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006123
John McCallf1549f62010-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 Dunbar4ff36842009-03-02 06:08:11 +00006129
John McCallf1549f62010-07-06 01:34:17 +00006130 // Add a cleanup to leave the catch.
John McCall8e3f8612010-07-13 22:12:14 +00006131 bool EndCatchMightThrow = (Handler.Variable == 0);
John McCall1f0fca52010-07-21 07:22:38 +00006132 CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup,
6133 EndCatchMightThrow,
6134 ObjCTypes.getObjCEndCatchFn());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006135
John McCallf1549f62010-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 Dunbar4ff36842009-03-02 06:08:11 +00006140
John McCallf1549f62010-07-06 01:34:17 +00006141 CGF.EmitLocalBlockVarDecl(*CatchParam);
6142 CGF.Builder.CreateStore(CastExn, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006143 }
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006144
John McCallf1549f62010-07-06 01:34:17 +00006145 CGF.ObjCEHValueStack.push_back(Exn);
6146 CGF.EmitStmt(Handler.Body);
6147 CGF.ObjCEHValueStack.pop_back();
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006148
John McCallf1549f62010-07-06 01:34:17 +00006149 // Leave the earlier cleanup.
6150 CGF.PopCleanupBlock();
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006151
John McCallf1549f62010-07-06 01:34:17 +00006152 CGF.EmitBranchThroughCleanup(Cont);
6153 }
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006154
John McCallf1549f62010-07-06 01:34:17 +00006155 // Go back to the try-statement fallthrough.
6156 CGF.Builder.restoreIP(SavedIP);
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006157
John McCallf1549f62010-07-06 01:34:17 +00006158 // Pop out of the normal cleanup on the finally.
6159 if (S.getFinallyStmt())
6160 CGF.ExitFinallyBlock(FinallyInfo);
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006161
John McCallff8e1152010-07-23 21:56:41 +00006162 if (Cont.isValid())
6163 CGF.EmitBlock(Cont.getBlock());
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006164}
6165
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006166/// EmitThrowStmt - Generate code for a throw statement.
6167void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6168 const ObjCAtThrowStmt &S) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006169 llvm::Value *Exception;
Fariborz Jahanian69677ea2010-05-28 17:34:43 +00006170 llvm::Constant *FunctionThrowOrRethrow;
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006171 if (const Expr *ThrowExpr = S.getThrowExpr()) {
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006172 Exception = CGF.EmitScalarExpr(ThrowExpr);
Fariborz Jahanian69677ea2010-05-28 17:34:43 +00006173 FunctionThrowOrRethrow = ObjCTypes.getExceptionThrowFn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006174 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006175 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006176 "Unexpected rethrow outside @catch block.");
6177 Exception = CGF.ObjCEHValueStack.back();
Fariborz Jahanian69677ea2010-05-28 17:34:43 +00006178 FunctionThrowOrRethrow = ObjCTypes.getExceptionRethrowFn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006179 }
6180
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006181 llvm::Value *ExceptionAsObject =
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006182 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
6183 llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
6184 if (InvokeDest) {
Fariborz Jahanian69677ea2010-05-28 17:34:43 +00006185 CGF.Builder.CreateInvoke(FunctionThrowOrRethrow,
John McCallf1549f62010-07-06 01:34:17 +00006186 CGF.getUnreachableBlock(), InvokeDest,
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006187 &ExceptionAsObject, &ExceptionAsObject + 1);
John McCallf1549f62010-07-06 01:34:17 +00006188 } else {
6189 CGF.Builder.CreateCall(FunctionThrowOrRethrow, ExceptionAsObject)
6190 ->setDoesNotReturn();
6191 CGF.Builder.CreateUnreachable();
6192 }
Daniel Dunbar4ff36842009-03-02 06:08:11 +00006193
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006194 // Clear the insertion point to indicate we are in unreachable code.
6195 CGF.Builder.ClearInsertionPoint();
6196}
Daniel Dunbare588b992009-03-01 04:46:24 +00006197
John McCall5a180392010-07-24 00:37:23 +00006198llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006199CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006200 bool ForDefinition) {
Daniel Dunbare588b992009-03-01 04:46:24 +00006201 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbare588b992009-03-01 04:46:24 +00006202
Daniel Dunbar8158a2f2009-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 Dunbar7e075cb2009-04-07 06:43:45 +00006208
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006209 // If this type (or a super class) has the __objc_exception__
6210 // attribute, emit an external reference.
Douglas Gregor68584ed2009-06-18 16:11:24 +00006211 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006212 return Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00006213 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006214 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006215 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006216 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006217 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006218 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006219
Daniel Dunbar8158a2f2009-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 Dunbar6ab187a2009-04-07 05:48:37 +00006223 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbare588b992009-03-01 04:46:24 +00006224 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006225 llvm::GlobalVariable *VTableGV =
Daniel Dunbare588b992009-03-01 04:46:24 +00006226 CGM.getModule().getGlobalVariable(VTableName);
6227 if (!VTableGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006228 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6229 false,
Daniel Dunbare588b992009-03-01 04:46:24 +00006230 llvm::GlobalValue::ExternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00006231 0, VTableName);
Daniel Dunbare588b992009-03-01 04:46:24 +00006232
Chris Lattner77b89b82010-06-27 07:15:29 +00006233 llvm::Value *VTableIdx =
6234 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
Daniel Dunbare588b992009-03-01 04:46:24 +00006235
6236 std::vector<llvm::Constant*> Values(3);
Owen Anderson3c4972d2009-07-29 18:54:39 +00006237 Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
Daniel Dunbare588b992009-03-01 04:46:24 +00006238 Values[1] = GetClassName(ID->getIdentifier());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00006239 Values[2] = GetClassGlobal(ClassName);
Owen Andersona1cf15f2009-07-14 23:10:40 +00006240 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00006241 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbare588b992009-03-01 04:46:24 +00006242
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006243 if (Entry) {
6244 Entry->setInitializer(Init);
6245 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00006246 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006247 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006248 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006249 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006250 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006251 }
6252
Daniel Dunbar04d40782009-04-14 06:00:08 +00006253 if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden)
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006254 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00006255 Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6256 ObjCTypes.EHTypeTy));
Daniel Dunbar8158a2f2009-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 Dunbare588b992009-03-01 04:46:24 +00006264
6265 return Entry;
6266}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006267
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00006268/* *** */
6269
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00006270CodeGen::CGObjCRuntime *
6271CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00006272 return new CGObjCMac(CGM);
6273}
Fariborz Jahanianee0af742009-01-21 22:04:16 +00006274
6275CodeGen::CGObjCRuntime *
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00006276CodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00006277 return new CGObjCNonFragileABIMac(CGM);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00006278}