blob: f4b42bb9b7dc66bcd454e50d24b26a30c444be7b [file] [log] [blame]
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattner57540c52011-04-15 05:22:18 +000010// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbar303e2c22008-08-11 02:45:11 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
John McCallad7c5c12011-02-08 08:22:06 +000015#include "CGBlocks.h"
John McCalled1ae862011-01-28 11:13:47 +000016#include "CGCleanup.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000017#include "CGRecordLayout.h"
18#include "CodeGenFunction.h"
19#include "CodeGenModule.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000020#include "clang/AST/ASTContext.h"
Daniel Dunbar221fa942008-08-11 04:54:23 +000021#include "clang/AST/Decl.h"
Daniel Dunbarb036db82008-08-13 03:21:16 +000022#include "clang/AST/DeclObjC.h"
Anders Carlsson15b73de2009-07-18 19:43:29 +000023#include "clang/AST/RecordLayout.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000024#include "clang/AST/StmtObjC.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000025#include "clang/Basic/LangOptions.h"
Chandler Carruth85098242010-06-15 23:19:56 +000026#include "clang/Frontend/CodeGenOptions.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000027#include "llvm/ADT/DenseSet.h"
28#include "llvm/ADT/SetVector.h"
29#include "llvm/ADT/SmallPtrSet.h"
30#include "llvm/ADT/SmallString.h"
31#include "llvm/DataLayout.h"
John McCall42227ed2010-07-31 23:20:56 +000032#include "llvm/InlineAsm.h"
33#include "llvm/IntrinsicInst.h"
Owen Andersonae86c192009-07-13 04:10:07 +000034#include "llvm/LLVMContext.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000035#include "llvm/Module.h"
John McCall5c08ab92010-07-13 22:12:14 +000036#include "llvm/Support/CallSite.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000037#include "llvm/Support/raw_ostream.h"
Torok Edwindb714922009-08-24 13:25:12 +000038#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000039
40using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000041using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000042
43namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000044
Daniel Dunbar59e476b2009-08-03 17:06:42 +000045// FIXME: We should find a nicer way to make the labels for metadata, string
46// concatenation is lame.
Daniel Dunbarb036db82008-08-13 03:21:16 +000047
Fariborz Jahanian279eda62009-01-21 22:04:16 +000048class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +000049protected:
50 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +000051
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000052private:
John McCall9dc0db22011-05-15 01:53:33 +000053 // The types of these functions don't really matter because we
54 // should always bitcast before calling them.
55
56 /// id objc_msgSend (id, SEL, ...)
57 ///
58 /// The default messenger, used for sends whose ABI is unchanged from
59 /// the all-integer/pointer case.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000060 llvm::Constant *getMessageSendFn() const {
John McCall31168b02011-06-15 23:02:42 +000061 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
62 // be called a lot.
Chris Lattnera5f58b02011-07-09 17:41:47 +000063 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000064 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
65 params, true),
John McCall31168b02011-06-15 23:02:42 +000066 "objc_msgSend",
Bill Wendling311c8322012-10-15 04:47:45 +000067 llvm::Attributes::get(CGM.getLLVMContext(),
Bill Wendling507c3512012-10-16 05:23:44 +000068 llvm::Attributes::NonLazyBind));
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000069 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000070
John McCall9dc0db22011-05-15 01:53:33 +000071 /// void objc_msgSend_stret (id, SEL, ...)
72 ///
73 /// The messenger used when the return value is an aggregate returned
74 /// by indirect reference in the first argument, and therefore the
75 /// self and selector parameters are shifted over by one.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000076 llvm::Constant *getMessageSendStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000077 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +000078 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
79 params, true),
80 "objc_msgSend_stret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000081
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000082 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000083
John McCall9dc0db22011-05-15 01:53:33 +000084 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
85 ///
86 /// The messenger used when the return value is returned on the x87
87 /// floating-point stack; without a special entrypoint, the nil case
88 /// would be unbalanced.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000089 llvm::Constant *getMessageSendFpretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +000090 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Chris Lattnerece04092012-02-07 00:39:47 +000091 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
92 params, true),
John McCall9dc0db22011-05-15 01:53:33 +000093 "objc_msgSend_fpret");
Daniel Dunbar59e476b2009-08-03 17:06:42 +000094
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000095 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000096
Anders Carlsson2f1a6c32011-10-31 16:27:11 +000097 /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
98 ///
99 /// The messenger used when the return value is returned in two values on the
100 /// x87 floating point stack; without a special entrypoint, the nil case
101 /// would be unbalanced. Only used on 64-bit X86.
102 llvm::Constant *getMessageSendFp2retFn() const {
103 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
104 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
105 llvm::Type *resultType =
106 llvm::StructType::get(longDoubleType, longDoubleType, NULL);
107
108 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
109 params, true),
110 "objc_msgSend_fp2ret");
111 }
112
John McCall9dc0db22011-05-15 01:53:33 +0000113 /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
114 ///
115 /// The messenger used for super calls, which have different dispatch
116 /// semantics. The class passed is the superclass of the current
117 /// class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000118 llvm::Constant *getMessageSendSuperFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000119 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000120 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000121 params, true),
122 "objc_msgSendSuper");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000123 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000124
John McCall9dc0db22011-05-15 01:53:33 +0000125 /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
126 ///
127 /// A slightly different messenger used for super calls. The class
128 /// passed is the current class.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000129 llvm::Constant *getMessageSendSuperFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000130 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000131 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000132 params, true),
133 "objc_msgSendSuper2");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000134 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000135
John McCall9dc0db22011-05-15 01:53:33 +0000136 /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
137 /// SEL op, ...)
138 ///
139 /// The messenger used for super calls which return an aggregate indirectly.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000140 llvm::Constant *getMessageSendSuperStretFn() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000141 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000142 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000143 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000144 "objc_msgSendSuper_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000145 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000146
John McCall9dc0db22011-05-15 01:53:33 +0000147 /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
148 /// SEL op, ...)
149 ///
150 /// objc_msgSendSuper_stret with the super2 semantics.
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000151 llvm::Constant *getMessageSendSuperStretFn2() const {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000152 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000153 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000154 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000155 "objc_msgSendSuper2_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000156 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000157
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000158 llvm::Constant *getMessageSendSuperFpretFn() const {
159 // There is no objc_msgSendSuper_fpret? How can that work?
160 return getMessageSendSuperFn();
161 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000162
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000163 llvm::Constant *getMessageSendSuperFpretFn2() const {
164 // There is no objc_msgSendSuper_fpret? How can that work?
165 return getMessageSendSuperFn2();
166 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000167
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000168protected:
169 CodeGen::CodeGenModule &CGM;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000170
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000171public:
Chris Lattnera5f58b02011-07-09 17:41:47 +0000172 llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000173 llvm::Type *Int8PtrTy, *Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000174
Daniel Dunbar5d715592008-08-12 05:28:47 +0000175 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000176 llvm::Type *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000177
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000178 /// PtrObjectPtrTy - LLVM type for id *
Chris Lattnera5f58b02011-07-09 17:41:47 +0000179 llvm::Type *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000180
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000181 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000182 llvm::Type *SelectorPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000183
184private:
Daniel Dunbarb036db82008-08-13 03:21:16 +0000185 /// ProtocolPtrTy - LLVM type for external protocol handles
186 /// (typeof(Protocol))
Chris Lattnera5f58b02011-07-09 17:41:47 +0000187 llvm::Type *ExternalProtocolPtrTy;
Douglas Gregor020de322012-01-17 18:36:30 +0000188
189public:
190 llvm::Type *getExternalProtocolPtrTy() {
191 if (!ExternalProtocolPtrTy) {
192 // FIXME: It would be nice to unify this with the opaque type, so that the
193 // IR comes out a bit cleaner.
194 CodeGen::CodeGenTypes &Types = CGM.getTypes();
195 ASTContext &Ctx = CGM.getContext();
196 llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
197 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
198 }
199
200 return ExternalProtocolPtrTy;
201 }
202
Daniel Dunbarc722b852008-08-30 03:02:31 +0000203 // SuperCTy - clang type for struct objc_super.
204 QualType SuperCTy;
205 // SuperPtrCTy - clang type for struct objc_super *.
206 QualType SuperPtrCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000207
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000208 /// SuperTy - LLVM type for struct objc_super.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000209 llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000210 /// SuperPtrTy - LLVM type for struct objc_super *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000211 llvm::Type *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000212
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000213 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
214 /// in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000215 llvm::StructType *PropertyTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000216
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000217 /// PropertyListTy - LLVM type for struct objc_property_list
218 /// (_prop_list_t in GCC parlance).
Chris Lattnera5f58b02011-07-09 17:41:47 +0000219 llvm::StructType *PropertyListTy;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000220 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000221 llvm::Type *PropertyListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000222
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000223 // MethodTy - LLVM type for struct objc_method.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000224 llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000225
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000226 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000227 llvm::Type *CacheTy;
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000228 /// CachePtrTy - LLVM type for struct objc_cache *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000229 llvm::Type *CachePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000230
Chris Lattnerce8754e2009-04-22 02:44:54 +0000231 llvm::Constant *getGetPropertyFn() {
232 CodeGen::CodeGenTypes &Types = CGM.getTypes();
233 ASTContext &Ctx = CGM.getContext();
234 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000235 SmallVector<CanQualType,4> Params;
John McCall2da83a32010-02-26 00:48:12 +0000236 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
237 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000238 Params.push_back(IdType);
239 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000240 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000241 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000242 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000243 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(IdType, Params,
244 FunctionType::ExtInfo(),
245 RequiredArgs::All));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000246 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
247 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000248
Chris Lattnerce8754e2009-04-22 02:44:54 +0000249 llvm::Constant *getSetPropertyFn() {
250 CodeGen::CodeGenTypes &Types = CGM.getTypes();
251 ASTContext &Ctx = CGM.getContext();
252 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000253 SmallVector<CanQualType,6> Params;
John McCall2da83a32010-02-26 00:48:12 +0000254 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
255 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000256 Params.push_back(IdType);
257 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000258 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000259 Params.push_back(IdType);
260 Params.push_back(Ctx.BoolTy);
261 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000262 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000263 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
264 FunctionType::ExtInfo(),
265 RequiredArgs::All));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000266 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
267 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000268
Ted Kremeneke65b0862012-03-06 20:05:56 +0000269 llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) {
270 CodeGen::CodeGenTypes &Types = CGM.getTypes();
271 ASTContext &Ctx = CGM.getContext();
272 // void objc_setProperty_atomic(id self, SEL _cmd,
273 // id newValue, ptrdiff_t offset);
274 // void objc_setProperty_nonatomic(id self, SEL _cmd,
275 // id newValue, ptrdiff_t offset);
276 // void objc_setProperty_atomic_copy(id self, SEL _cmd,
277 // id newValue, ptrdiff_t offset);
278 // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
279 // id newValue, ptrdiff_t offset);
280
281 SmallVector<CanQualType,4> Params;
282 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
283 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
284 Params.push_back(IdType);
285 Params.push_back(SelType);
286 Params.push_back(IdType);
287 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
288 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000289 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
290 FunctionType::ExtInfo(),
291 RequiredArgs::All));
Ted Kremeneke65b0862012-03-06 20:05:56 +0000292 const char *name;
293 if (atomic && copy)
294 name = "objc_setProperty_atomic_copy";
295 else if (atomic && !copy)
296 name = "objc_setProperty_atomic";
297 else if (!atomic && copy)
298 name = "objc_setProperty_nonatomic_copy";
299 else
300 name = "objc_setProperty_nonatomic";
301
302 return CGM.CreateRuntimeFunction(FTy, name);
303 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000304
305 llvm::Constant *getCopyStructFn() {
306 CodeGen::CodeGenTypes &Types = CGM.getTypes();
307 ASTContext &Ctx = CGM.getContext();
308 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000309 SmallVector<CanQualType,5> Params;
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000310 Params.push_back(Ctx.VoidPtrTy);
311 Params.push_back(Ctx.VoidPtrTy);
312 Params.push_back(Ctx.LongTy);
313 Params.push_back(Ctx.BoolTy);
314 Params.push_back(Ctx.BoolTy);
Chris Lattner2192fe52011-07-18 04:24:23 +0000315 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000316 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
317 FunctionType::ExtInfo(),
318 RequiredArgs::All));
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +0000319 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
320 }
321
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000322 /// This routine declares and returns address of:
323 /// void objc_copyCppObjectAtomic(
324 /// void *dest, const void *src,
325 /// void (*copyHelper) (void *dest, const void *source));
326 llvm::Constant *getCppAtomicObjectFunction() {
327 CodeGen::CodeGenTypes &Types = CGM.getTypes();
328 ASTContext &Ctx = CGM.getContext();
329 /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
330 SmallVector<CanQualType,3> Params;
331 Params.push_back(Ctx.VoidPtrTy);
332 Params.push_back(Ctx.VoidPtrTy);
333 Params.push_back(Ctx.VoidPtrTy);
334 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000335 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
336 FunctionType::ExtInfo(),
337 RequiredArgs::All));
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +0000338 return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
339 }
340
Chris Lattnerce8754e2009-04-22 02:44:54 +0000341 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000342 CodeGen::CodeGenTypes &Types = CGM.getTypes();
343 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000344 // void objc_enumerationMutation (id)
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000345 SmallVector<CanQualType,1> Params;
John McCall2da83a32010-02-26 00:48:12 +0000346 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2192fe52011-07-18 04:24:23 +0000347 llvm::FunctionType *FTy =
John McCall8dda7b22012-07-07 06:41:13 +0000348 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
John McCalla729c622012-02-17 03:33:10 +0000349 FunctionType::ExtInfo(),
350 RequiredArgs::All));
Chris Lattnerce8754e2009-04-22 02:44:54 +0000351 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
352 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000353
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000354 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattnerce8754e2009-04-22 02:44:54 +0000355 llvm::Constant *getGcReadWeakFn() {
356 // id objc_read_weak (id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000357 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000358 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000359 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000360 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000361 }
362
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000363 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000364 llvm::Constant *getGcAssignWeakFn() {
365 // id objc_assign_weak (id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000366 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000367 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000368 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000369 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
370 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000371
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000372 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000373 llvm::Constant *getGcAssignGlobalFn() {
374 // id objc_assign_global(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000375 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000376 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000377 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000378 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
379 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000380
Fariborz Jahanian217af242010-07-20 20:30:03 +0000381 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
382 llvm::Constant *getGcAssignThreadLocalFn() {
383 // id objc_assign_threadlocal(id src, id * dest)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000384 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian217af242010-07-20 20:30:03 +0000385 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000386 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian217af242010-07-20 20:30:03 +0000387 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
388 }
389
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000390 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000391 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000392 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000393 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
394 CGM.PtrDiffTy };
Owen Anderson170229f2009-07-14 23:10:40 +0000395 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000396 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000397 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
398 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000399
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000400 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
401 llvm::Constant *GcMemmoveCollectableFn() {
402 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000403 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall9dc0db22011-05-15 01:53:33 +0000404 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000405 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
406 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000407
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000408 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000409 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000410 // id objc_assign_strongCast(id, id *)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000411 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000412 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000413 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000414 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
415 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000416
417 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000418 llvm::Constant *getExceptionThrowFn() {
419 // void objc_exception_throw(id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000420 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000421 llvm::FunctionType *FTy =
John McCall9dc0db22011-05-15 01:53:33 +0000422 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000423 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
424 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000425
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000426 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
427 llvm::Constant *getExceptionRethrowFn() {
428 // void objc_exception_rethrow(void)
John McCall9dc0db22011-05-15 01:53:33 +0000429 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000430 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
431 }
432
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000433 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerdcceee72009-04-06 16:53:45 +0000434 llvm::Constant *getSyncEnterFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000435 // int objc_sync_enter (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000436 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerdcceee72009-04-06 16:53:45 +0000437 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000438 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000439 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
440 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000441
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000442 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000443 llvm::Constant *getSyncExitFn() {
Aaron Ballman9c004462012-09-06 16:44:16 +0000444 // int objc_sync_exit (id)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000445 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattner0a696a422009-04-22 02:38:11 +0000446 llvm::FunctionType *FTy =
Aaron Ballman9c004462012-09-06 16:44:16 +0000447 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000448 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
449 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000450
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000451 llvm::Constant *getSendFn(bool IsSuper) const {
452 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
453 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000454
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000455 llvm::Constant *getSendFn2(bool IsSuper) const {
456 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
457 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000458
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000459 llvm::Constant *getSendStretFn(bool IsSuper) const {
460 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
461 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000462
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000463 llvm::Constant *getSendStretFn2(bool IsSuper) const {
464 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
465 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000466
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000467 llvm::Constant *getSendFpretFn(bool IsSuper) const {
468 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
469 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000470
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000471 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
472 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
473 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000474
Anders Carlsson2f1a6c32011-10-31 16:27:11 +0000475 llvm::Constant *getSendFp2retFn(bool IsSuper) const {
476 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
477 }
478
479 llvm::Constant *getSendFp2RetFn2(bool IsSuper) const {
480 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
481 }
482
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000483 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
484 ~ObjCCommonTypesHelper(){}
485};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000486
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000487/// ObjCTypesHelper - Helper class that encapsulates lazy
488/// construction of varies types used during ObjC generation.
489class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000490public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000491 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000492 llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000493 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000494 llvm::Type *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000495 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000496 llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000497
Daniel Dunbarb036db82008-08-13 03:21:16 +0000498 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000499 llvm::StructType *ProtocolTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000500 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000501 llvm::Type *ProtocolPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000502 /// ProtocolExtensionTy - LLVM type for struct
503 /// objc_protocol_extension.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000504 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000505 /// ProtocolExtensionTy - LLVM type for struct
506 /// objc_protocol_extension *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000507 llvm::Type *ProtocolExtensionPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000508 /// MethodDescriptionTy - LLVM type for struct
509 /// objc_method_description.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000510 llvm::StructType *MethodDescriptionTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000511 /// MethodDescriptionListTy - LLVM type for struct
512 /// objc_method_description_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000513 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000514 /// MethodDescriptionListPtrTy - LLVM type for struct
515 /// objc_method_description_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000516 llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000517 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000518 llvm::StructType *ProtocolListTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000519 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000520 llvm::Type *ProtocolListPtrTy;
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000521 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000522 llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000523 /// ClassTy - LLVM type for struct objc_class.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000524 llvm::StructType *ClassTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000525 /// ClassPtrTy - LLVM type for struct objc_class *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000526 llvm::Type *ClassPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000527 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000528 llvm::StructType *ClassExtensionTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000529 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000530 llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000531 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000532 llvm::StructType *IvarTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000533 /// IvarListTy - LLVM type for struct objc_ivar_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000534 llvm::Type *IvarListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000535 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000536 llvm::Type *IvarListPtrTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000537 /// MethodListTy - LLVM type for struct objc_method_list.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000538 llvm::Type *MethodListTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000539 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000540 llvm::Type *MethodListPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000541
Anders Carlsson9ff22482008-09-09 10:10:21 +0000542 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000543 llvm::Type *ExceptionDataTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000544
Anders Carlsson9ff22482008-09-09 10:10:21 +0000545 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000546 llvm::Constant *getExceptionTryEnterFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000547 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000548 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000549 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000550 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000551 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000552
553 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000554 llvm::Constant *getExceptionTryExitFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000555 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson170229f2009-07-14 23:10:40 +0000556 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000557 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000558 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000559 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000560
561 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000562 llvm::Constant *getExceptionExtractFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000563 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000564 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000565 params, false),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000566 "objc_exception_extract");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000567 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000568
Anders Carlsson9ff22482008-09-09 10:10:21 +0000569 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000570 llvm::Constant *getExceptionMatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000571 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000572 return CGM.CreateRuntimeFunction(
John McCall9dc0db22011-05-15 01:53:33 +0000573 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000574 "objc_exception_match");
575
Chris Lattnerc6406db2009-04-22 02:26:14 +0000576 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000577
Anders Carlsson9ff22482008-09-09 10:10:21 +0000578 /// SetJmpFn - LLVM _setjmp function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000579 llvm::Constant *getSetJmpFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000580 // This is specifically the prototype for x86.
Chris Lattnera5f58b02011-07-09 17:41:47 +0000581 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
John McCall9dc0db22011-05-15 01:53:33 +0000582 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
583 params, false),
Bill Wendlingbcefeae2011-11-29 00:10:10 +0000584 "_setjmp",
Bill Wendling311c8322012-10-15 04:47:45 +0000585 llvm::Attributes::get(CGM.getLLVMContext(),
Bill Wendling507c3512012-10-16 05:23:44 +0000586 llvm::Attributes::NonLazyBind));
Chris Lattnerc6406db2009-04-22 02:26:14 +0000587 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000588
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000589public:
590 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000591 ~ObjCTypesHelper() {}
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000592};
593
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000594/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000595/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000596class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000597public:
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000598
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000599 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000600 llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000601
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000602 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000603 llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000604
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000605 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000606 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000607
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000608 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000609 llvm::Type *ProtocolnfABIPtrTy;
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000610
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000611 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattnera5f58b02011-07-09 17:41:47 +0000612 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000613
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000614 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000615 llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000616
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000617 // ClassnfABITy - LLVM for struct _class_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000618 llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000619
Fariborz Jahanian71394042009-01-23 23:53:38 +0000620 // ClassnfABIPtrTy - LLVM for struct _class_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000621 llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000622
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000623 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000624 llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000625
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000626 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000627 llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000628
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000629 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000630 llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000631
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000632 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000633 llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000634
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000635 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000636 llvm::Type *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000637
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000638 // CategorynfABITy - LLVM for struct _category_t
Chris Lattnera5f58b02011-07-09 17:41:47 +0000639 llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000640
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000641 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000642
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000643 // MessageRefTy - LLVM for:
644 // struct _message_ref_t {
645 // IMP messenger;
646 // SEL name;
647 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000648 llvm::StructType *MessageRefTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000649 // MessageRefCTy - clang type for struct _message_ref_t
650 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000651
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000652 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000653 llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000654 // MessageRefCPtrTy - clang type for struct _message_ref_t*
655 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000656
Fariborz Jahanian4e87c832009-02-05 01:13:09 +0000657 // MessengerTy - Type of the messenger (shown as IMP above)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000658 llvm::FunctionType *MessengerTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000659
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000660 // SuperMessageRefTy - LLVM for:
661 // struct _super_message_ref_t {
662 // SUPER_IMP messenger;
663 // SEL name;
664 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +0000665 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000666
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000667 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Chris Lattnera5f58b02011-07-09 17:41:47 +0000668 llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000669
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000670 llvm::Constant *getMessageSendFixupFn() {
671 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000672 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000673 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000674 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000675 "objc_msgSend_fixup");
676 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000677
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000678 llvm::Constant *getMessageSendFpretFixupFn() {
679 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000680 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000681 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000682 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000683 "objc_msgSend_fpret_fixup");
684 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000685
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000686 llvm::Constant *getMessageSendStretFixupFn() {
687 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000688 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000689 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000690 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000691 "objc_msgSend_stret_fixup");
692 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000693
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000694 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000695 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000696 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000697 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000698 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000699 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000700 "objc_msgSendSuper2_fixup");
701 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000702
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000703 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000704 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000705 // struct _super_message_ref_t*, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +0000706 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000707 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000708 params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000709 "objc_msgSendSuper2_stret_fixup");
710 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000711
Chris Lattnera7c00b42009-04-22 02:15:23 +0000712 llvm::Constant *getObjCEndCatchFn() {
John McCall9dc0db22011-05-15 01:53:33 +0000713 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000714 "objc_end_catch");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000715
Chris Lattnera7c00b42009-04-22 02:15:23 +0000716 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000717
Chris Lattnera7c00b42009-04-22 02:15:23 +0000718 llvm::Constant *getObjCBeginCatchFn() {
Chris Lattnera5f58b02011-07-09 17:41:47 +0000719 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson9793f0e2009-07-29 22:16:19 +0000720 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall9dc0db22011-05-15 01:53:33 +0000721 params, false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000722 "objc_begin_catch");
723 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000724
Chris Lattnera5f58b02011-07-09 17:41:47 +0000725 llvm::StructType *EHTypeTy;
726 llvm::Type *EHTypePtrTy;
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +0000727
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000728 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
729 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000730};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000731
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000732class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000733public:
734 // FIXME - accessibility
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000735 class GC_IVAR {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +0000736 public:
Eli Friedman8cbca202012-11-06 22:15:52 +0000737 unsigned ivar_bytepos;
738 unsigned ivar_size;
739 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000740 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar22b0ada2009-04-23 01:29:05 +0000741
742 // Allow sorting based on byte pos.
743 bool operator<(const GC_IVAR &b) const {
744 return ivar_bytepos < b.ivar_bytepos;
745 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000746 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000747
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000748 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000749 public:
750 unsigned skip;
751 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000752 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000753 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000754 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000755
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000756 /// opcode for captured block variables layout 'instructions'.
757 /// In the following descriptions, 'I' is the value of the immediate field.
758 /// (field following the opcode).
759 ///
760 enum BLOCK_LAYOUT_OPCODE {
761 /// An operator which affects how the following layout should be
762 /// interpreted.
763 /// I == 0: Halt interpretation and treat everything else as
764 /// a non-pointer. Note that this instruction is equal
765 /// to '\0'.
766 /// I != 0: Currently unused.
767 BLOCK_LAYOUT_OPERATOR = 0,
768
769 /// The next I+1 bytes do not contain a value of object pointer type.
770 /// Note that this can leave the stream unaligned, meaning that
771 /// subsequent word-size instructions do not begin at a multiple of
772 /// the pointer size.
773 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
774
775 /// The next I+1 words do not contain a value of object pointer type.
776 /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
777 /// when the required skip quantity is a multiple of the pointer size.
778 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
779
780 /// The next I+1 words are __strong pointers to Objective-C
781 /// objects or blocks.
782 BLOCK_LAYOUT_STRONG = 3,
783
784 /// The next I+1 words are pointers to __block variables.
785 BLOCK_LAYOUT_BYREF = 4,
786
787 /// The next I+1 words are __weak pointers to Objective-C
788 /// objects or blocks.
789 BLOCK_LAYOUT_WEAK = 5,
790
791 /// The next I+1 words are __unsafe_unretained pointers to
792 /// Objective-C objects or blocks.
793 BLOCK_LAYOUT_UNRETAINED = 6
794
795 /// The next I+1 words are block or object pointers with some
796 /// as-yet-unspecified ownership semantics. If we add more
797 /// flavors of ownership semantics, values will be taken from
798 /// this range.
799 ///
800 /// This is included so that older tools can at least continue
801 /// processing the layout past such things.
802 //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
803
804 /// All other opcodes are reserved. Halt interpretation and
805 /// treat everything else as opaque.
806 };
807
808 class RUN_SKIP {
809 public:
810 enum BLOCK_LAYOUT_OPCODE opcode;
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000811 CharUnits block_var_bytepos;
812 CharUnits block_var_size;
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000813 RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000814 CharUnits BytePos = CharUnits::Zero(),
815 CharUnits Size = CharUnits::Zero())
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +0000816 : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000817
818 // Allow sorting based on byte pos.
819 bool operator<(const RUN_SKIP &b) const {
820 return block_var_bytepos < b.block_var_bytepos;
821 }
822 };
823
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000824protected:
Owen Andersonae86c192009-07-13 04:10:07 +0000825 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000826 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000827 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000828
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000829 // gc ivar layout bitmap calculation helper caches.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000830 SmallVector<GC_IVAR, 16> SkipIvars;
831 SmallVector<GC_IVAR, 16> IvarsInfo;
Fariborz Jahanian196f9382012-10-25 21:15:04 +0000832
833 // arc/mrr layout of captured block literal variables.
834 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000835
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000836 /// LazySymbols - Symbols to generate a lazy reference for. See
837 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000838 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000839
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000840 /// DefinedSymbols - External symbols which are defined by this
841 /// module. The symbols in this list and LazySymbols are used to add
842 /// special linker symbols which ensure that Objective-C modules are
843 /// linked properly.
Daniel Dunbard027a922009-09-07 00:20:42 +0000844 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000845
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000846 /// ClassNames - uniqued class names.
Daniel Dunbarb036db82008-08-13 03:21:16 +0000847 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000848
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000849 /// MethodVarNames - uniqued method variable names.
850 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000851
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000852 /// DefinedCategoryNames - list of category names in form Class_Category.
853 llvm::SetVector<std::string> DefinedCategoryNames;
854
Daniel Dunbarb036db82008-08-13 03:21:16 +0000855 /// MethodVarTypes - uniqued method type signatures. We have to use
856 /// a StringMap here because have no other unique reference.
857 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000858
Daniel Dunbar3c76cb52008-08-26 21:51:14 +0000859 /// MethodDefinitions - map of methods which have been defined in
860 /// this translation unit.
861 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000862
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000863 /// PropertyNames - uniqued method variable names.
864 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000865
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000866 /// ClassReferences - uniqued class references.
867 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000868
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000869 /// SelectorReferences - uniqued selector references.
870 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000871
Daniel Dunbarb036db82008-08-13 03:21:16 +0000872 /// Protocols - Protocols for which an objc_protocol structure has
873 /// been emitted. Forward declarations are handled by creating an
874 /// empty structure whose initializer is filled in when/if defined.
875 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000876
Daniel Dunbarc475d422008-10-29 22:36:39 +0000877 /// DefinedProtocols - Protocols which have actually been
878 /// defined. We should not need this, see FIXME in GenerateProtocol.
879 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000880
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000881 /// DefinedClasses - List of defined classes.
Bill Wendling8392a472012-02-07 09:40:07 +0000882 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000883
884 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Bill Wendling8392a472012-02-07 09:40:07 +0000885 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000886
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000887 /// DefinedCategories - List of defined categories.
Bill Wendling8392a472012-02-07 09:40:07 +0000888 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000889
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000890 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Bill Wendling8392a472012-02-07 09:40:07 +0000891 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000892
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000893 /// GetNameForMethod - Return a name for the given method.
894 /// \param[out] NameOut - The return value.
895 void GetNameForMethod(const ObjCMethodDecl *OMD,
896 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000897 SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000898
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000899 /// GetMethodVarName - Return a unique constant for the given
900 /// selector's name. The return value has type char *.
901 llvm::Constant *GetMethodVarName(Selector Sel);
902 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000903
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000904 /// GetMethodVarType - Return a unique constant for the given
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000905 /// method's type encoding string. The return value has type char *.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000906
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000907 // FIXME: This is a horrible name.
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000908 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
909 bool Extended = false);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000910 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000911
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000912 /// GetPropertyName - Return a unique constant for the given
913 /// name. The return value has type char *.
914 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000915
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000916 // FIXME: This can be dropped once string functions are unified.
917 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
918 const Decl *Container);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000919
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +0000920 /// GetClassName - Return a unique constant for the given selector's
921 /// name. The return value has type char *.
922 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000923
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000924 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
925
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000926 /// BuildIvarLayout - Builds ivar layout bitmap for the class
927 /// implementation for the __strong or __weak case.
928 ///
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000929 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
930 bool ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +0000931
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +0000932 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000933
Daniel Dunbar15bd8882009-05-03 14:10:34 +0000934 void BuildAggrIvarRecordLayout(const RecordType *RT,
Eli Friedman8cbca202012-11-06 22:15:52 +0000935 unsigned int BytePos, bool ForStrongLayout,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000936 bool &HasUnion);
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +0000937 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000938 const llvm::StructLayout *Layout,
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000939 const RecordDecl *RD,
Bill Wendlingf1a3fca2012-02-22 09:30:11 +0000940 ArrayRef<const FieldDecl*> RecFields,
Eli Friedman8cbca202012-11-06 22:15:52 +0000941 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahaniana123b642009-04-24 16:17:09 +0000942 bool &HasUnion);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000943
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000944 Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
Fariborz Jahanian2dd78192012-11-02 22:51:18 +0000945
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000946 void UpdateRunSkipBlockVars(bool IsByref,
947 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +0000948 CharUnits FieldOffset,
949 CharUnits FieldSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000950
951 void BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000952 CharUnits BytePos, bool &HasUnion,
953 bool ByrefLayout=false);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000954
955 void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
956 const RecordDecl *RD,
957 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000958 CharUnits BytePos, bool &HasUnion,
959 bool ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +0000960
Fariborz Jahanian23290b02012-11-01 18:32:55 +0000961 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
962
Fariborz Jahaniana9d44642012-11-14 17:15:51 +0000963 llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
964
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000965
Fariborz Jahanian01dff422009-03-05 19:17:31 +0000966 /// GetIvarLayoutName - Returns a unique constant for the given
967 /// ivar layout bitmap.
968 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
969 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000970
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000971 /// EmitPropertyList - Emit the given property list. The return
972 /// value has type PropertyListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000973 llvm::Constant *EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000974 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000975 const ObjCContainerDecl *OCD,
976 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000977
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000978 /// EmitProtocolMethodTypes - Generate the array of extended method type
979 /// strings. The return value has type Int8PtrPtrTy.
980 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +0000981 ArrayRef<llvm::Constant*> MethodTypes,
Bob Wilson5f4e3a72011-11-30 01:57:58 +0000982 const ObjCCommonTypesHelper &ObjCTypes);
983
Fariborz Jahanian751c1e72009-12-12 21:26:21 +0000984 /// PushProtocolProperties - Push protocol's property on the input stack.
Bill Wendlinga515b582012-02-09 22:16:49 +0000985 void PushProtocolProperties(
986 llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
987 llvm::SmallVectorImpl<llvm::Constant*> &Properties,
988 const Decl *Container,
989 const ObjCProtocolDecl *PROTO,
990 const ObjCCommonTypesHelper &ObjCTypes);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +0000991
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000992 /// GetProtocolRef - Return a reference to the internal protocol
993 /// description, creating an empty one if it has not been
994 /// defined. The return value has type ProtocolPtrTy.
995 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanian67726212009-03-08 20:18:37 +0000996
Daniel Dunbar30c65362009-03-09 20:09:19 +0000997 /// CreateMetadataVar - Create a global variable with internal
998 /// linkage for use by the Objective-C runtime.
999 ///
1000 /// This is a convenience wrapper which not only creates the
1001 /// variable, but also sets the section and alignment and adds the
Chris Lattnerf56501c2009-07-17 23:57:13 +00001002 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001003 ///
1004 /// \param Name - The variable name.
1005 /// \param Init - The variable initializer; this is also used to
1006 /// define the type of the variable.
1007 /// \param Section - The section the variable should go into, or 0.
1008 /// \param Align - The alignment for the variable, or 0.
1009 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbar4527d302009-04-14 17:42:51 +00001010 /// "llvm.used".
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001011 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00001012 llvm::Constant *Init,
1013 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00001014 unsigned Align,
1015 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +00001016
John McCall9e8bb002011-05-14 03:10:52 +00001017 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1018 ReturnValueSlot Return,
1019 QualType ResultType,
1020 llvm::Value *Sel,
1021 llvm::Value *Arg0,
1022 QualType Arg0Ty,
1023 bool IsSuper,
1024 const CallArgList &CallArgs,
1025 const ObjCMethodDecl *OMD,
1026 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbarf5c18462009-04-20 06:54:31 +00001027
Daniel Dunbar5e639272010-04-25 20:39:01 +00001028 /// EmitImageInfo - Emit the image info marker used to encode some module
1029 /// level information.
1030 void EmitImageInfo();
1031
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001032public:
Owen Andersonae86c192009-07-13 04:10:07 +00001033 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCalla729c622012-02-17 03:33:10 +00001034 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001035
David Chisnall481e3a82010-01-23 02:40:42 +00001036 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Ted Kremeneke65b0862012-03-06 20:05:56 +00001037
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001038 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
1039 const ObjCContainerDecl *CD=0);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001040
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001041 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001042
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001043 /// GetOrEmitProtocol - Get the protocol object for the given
1044 /// declaration, emitting it if necessary. The return value has type
1045 /// ProtocolPtrTy.
1046 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001047
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001048 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1049 /// object for the given declaration, emitting it if needed. These
1050 /// forward references will be filled in with empty bodies if no
1051 /// definition is seen. The return value has type ProtocolPtrTy.
1052 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCall351762c2011-02-07 10:33:21 +00001053 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1054 const CGBlockInfo &blockInfo);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00001055 virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1056 const CGBlockInfo &blockInfo);
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001057
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001058 virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1059 QualType T);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001060};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001061
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001062class CGObjCMac : public CGObjCCommonMac {
1063private:
1064 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001065
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001066 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001067 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001068 void EmitModuleInfo();
1069
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001070 /// EmitModuleSymols - Emit module symbols, the list of defined
1071 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00001072 llvm::Constant *EmitModuleSymbols();
1073
Daniel Dunbar3ad53482008-08-11 21:35:06 +00001074 /// FinishModule - Write out global data structures at the end of
1075 /// processing a translation unit.
1076 void FinishModule();
Daniel Dunbarb036db82008-08-13 03:21:16 +00001077
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001078 /// EmitClassExtension - Generate the class extension structure used
1079 /// to store the weak ivar layout and properties. The return value
1080 /// has type ClassExtensionPtrTy.
1081 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
1082
1083 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1084 /// for the given class.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001085 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001086 const ObjCInterfaceDecl *ID);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001087
John McCall31168b02011-06-15 23:02:42 +00001088 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
1089 IdentifierInfo *II);
1090
1091 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
1092
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001093 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1094 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001095
1096 /// EmitIvarList - Emit the ivar list for the given
1097 /// implementation. If ForClass is true the list of class ivars
1098 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1099 /// interface ivars will be emitted. The return value has type
1100 /// IvarListPtrTy.
1101 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00001102 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001103
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001104 /// EmitMetaClass - Emit a forward reference to the class structure
1105 /// for the metaclass of the given interface. The return value has
1106 /// type ClassPtrTy.
1107 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1108
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001109 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001110 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001111 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1112 llvm::Constant *Protocols,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001113 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001114
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001115 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001116
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001117 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001118
1119 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +00001120 /// implementation. The return value has type MethodListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001121 llvm::Constant *EmitMethodList(Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00001122 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001123 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001124
1125 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001126 /// method declarations.
Daniel Dunbarb036db82008-08-13 03:21:16 +00001127 /// - TypeName: The name for the type containing the methods.
Sylvestre Ledru33b5baf2012-09-27 10:16:10 +00001128 /// - IsProtocol: True iff these methods are for a protocol.
1129 /// - ClassMethds: True iff these are class methods.
Daniel Dunbarb036db82008-08-13 03:21:16 +00001130 /// - Required: When true, only "required" methods are
1131 /// listed. Similarly, when false only "optional" methods are
1132 /// listed. For classes this should always be true.
1133 /// - begin, end: The method list to output.
1134 ///
1135 /// The return value has type MethodDescriptionListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001136 llvm::Constant *EmitMethodDescList(Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001137 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001138 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001139
Daniel Dunbarc475d422008-10-29 22:36:39 +00001140 /// GetOrEmitProtocol - Get the protocol object for the given
1141 /// declaration, emitting it if necessary. The return value has type
1142 /// ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001143 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001144
1145 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1146 /// object for the given declaration, emitting it if needed. These
1147 /// forward references will be filled in with empty bodies if no
1148 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001149 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001150
Daniel Dunbarb036db82008-08-13 03:21:16 +00001151 /// EmitProtocolExtension - Generate the protocol extension
1152 /// structure used to store optional instance and class methods, and
1153 /// protocol properties. The return value has type
1154 /// ProtocolExtensionPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001155 llvm::Constant *
1156 EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001157 ArrayRef<llvm::Constant*> OptInstanceMethods,
1158 ArrayRef<llvm::Constant*> OptClassMethods,
1159 ArrayRef<llvm::Constant*> MethodTypesExt);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001160
1161 /// EmitProtocolList - Generate the list of referenced
1162 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001163 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001164 ObjCProtocolDecl::protocol_iterator begin,
1165 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001166
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001167 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1168 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001169 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1170 bool lval=false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001171
1172public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001173 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001174
Fariborz Jahanian71394042009-01-23 23:53:38 +00001175 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001176
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001177 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001178 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001179 QualType ResultType,
1180 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001181 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001182 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001183 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001184 const ObjCMethodDecl *Method);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001185
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001186 virtual CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001187 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001188 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001189 QualType ResultType,
1190 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001191 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001192 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001193 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001194 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001195 const CallArgList &CallArgs,
1196 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001197
Daniel Dunbarcb463852008-11-01 01:53:16 +00001198 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001199 const ObjCInterfaceDecl *ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001200
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001201 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1202 bool lval = false);
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001203
1204 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1205 /// untyped one.
1206 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1207 const ObjCMethodDecl *Method);
1208
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001209 virtual llvm::Constant *GetEHType(QualType T);
John McCall2ca705e2010-07-24 00:37:23 +00001210
Daniel Dunbar92992502008-08-15 22:20:32 +00001211 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001212
Daniel Dunbar92992502008-08-15 22:20:32 +00001213 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001214
Daniel Dunbarf3d3b012012-02-28 15:36:15 +00001215 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}
David Chisnall92d436b2012-01-31 18:59:20 +00001216
Daniel Dunbarcb463852008-11-01 01:53:16 +00001217 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001218 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001219
Chris Lattnerd4808922009-03-22 21:03:39 +00001220 virtual llvm::Constant *GetPropertyGetFunction();
1221 virtual llvm::Constant *GetPropertySetFunction();
Ted Kremeneke65b0862012-03-06 20:05:56 +00001222 virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1223 bool copy);
David Chisnall168b80f2010-12-26 22:13:16 +00001224 virtual llvm::Constant *GetGetStructFunction();
1225 virtual llvm::Constant *GetSetStructFunction();
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001226 virtual llvm::Constant *GetCppAtomicObjectFunction();
Chris Lattnerd4808922009-03-22 21:03:39 +00001227 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001228
John McCallbd309292010-07-06 01:34:17 +00001229 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1230 const ObjCAtTryStmt &S);
1231 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1232 const ObjCAtSynchronizedStmt &S);
1233 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00001234 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1235 const ObjCAtThrowStmt &S);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001236 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001237 llvm::Value *AddrWeakObj);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001238 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001239 llvm::Value *src, llvm::Value *dst);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001240 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001241 llvm::Value *src, llvm::Value *dest,
1242 bool threadlocal = false);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00001243 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001244 llvm::Value *src, llvm::Value *dest,
1245 llvm::Value *ivarOffset);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001246 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1247 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001248 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1249 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001250 llvm::Value *size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001251
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001252 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1253 QualType ObjectTy,
1254 llvm::Value *BaseValue,
1255 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001256 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001257 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001258 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001259 const ObjCIvarDecl *Ivar);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001260
1261 /// GetClassGlobal - Return the global variable for the Objective-C
1262 /// class of the given name.
1263 virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) {
David Blaikie83d382b2011-09-23 05:06:16 +00001264 llvm_unreachable("CGObjCMac::GetClassGlobal");
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001265 }
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001266};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001267
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001268class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001269private:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001270 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001271 llvm::GlobalVariable* ObjCEmptyCacheVar;
1272 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001273
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001274 /// SuperClassReferences - uniqued super class references.
1275 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001276
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001277 /// MetaClassReferences - uniqued meta class references.
1278 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001279
1280 /// EHTypeReferences - uniqued class ehtype references.
1281 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001282
John McCall9e8bb002011-05-14 03:10:52 +00001283 /// VTableDispatchMethods - List of methods for which we generate
1284 /// vtable-based message dispatch.
1285 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001286
Fariborz Jahanian67260552009-11-17 21:37:35 +00001287 /// DefinedMetaClasses - List of defined meta-classes.
1288 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1289
John McCall9e8bb002011-05-14 03:10:52 +00001290 /// isVTableDispatchedSelector - Returns true if SEL is a
1291 /// vtable-based selector.
1292 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001293
Fariborz Jahanian71394042009-01-23 23:53:38 +00001294 /// FinishNonFragileABIModule - Write out global data structures at the end of
1295 /// processing a translation unit.
1296 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001297
Daniel Dunbar19573e72009-05-15 21:48:48 +00001298 /// AddModuleClassList - Add the given list of class pointers to the
1299 /// module with the provided symbol and section names.
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001300 void AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
Daniel Dunbar19573e72009-05-15 21:48:48 +00001301 const char *SymbolName,
1302 const char *SectionName);
1303
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001304 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1305 unsigned InstanceStart,
1306 unsigned InstanceSize,
1307 const ObjCImplementationDecl *ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001308 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001309 llvm::Constant *IsAGV,
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001310 llvm::Constant *SuperClassGV,
Fariborz Jahanian82208252009-01-31 00:59:10 +00001311 llvm::Constant *ClassRoGV,
1312 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001313
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001314 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001315
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00001316 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001317
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001318 /// EmitMethodList - Emit the method list for the given
1319 /// implementation. The return value has type MethodListnfABITy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001320 llvm::Constant *EmitMethodList(Twine Name,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001321 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001322 ArrayRef<llvm::Constant*> Methods);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001323 /// EmitIvarList - Emit the ivar list for the given
1324 /// implementation. If ForClass is true the list of class ivars
1325 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1326 /// interface ivars will be emitted. The return value has type
1327 /// IvarListnfABIPtrTy.
1328 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001329
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001330 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001331 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00001332 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001333
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001334 /// GetOrEmitProtocol - Get the protocol object for the given
1335 /// declaration, emitting it if necessary. The return value has type
1336 /// ProtocolPtrTy.
1337 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001338
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001339 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1340 /// object for the given declaration, emitting it if needed. These
1341 /// forward references will be filled in with empty bodies if no
1342 /// definition is seen. The return value has type ProtocolPtrTy.
1343 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001344
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001345 /// EmitProtocolList - Generate the list of referenced
1346 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001347 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001348 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001349 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001350
John McCall9e8bb002011-05-14 03:10:52 +00001351 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1352 ReturnValueSlot Return,
1353 QualType ResultType,
1354 Selector Sel,
1355 llvm::Value *Receiver,
1356 QualType Arg0Ty,
1357 bool IsSuper,
1358 const CallArgList &CallArgs,
1359 const ObjCMethodDecl *Method);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001360
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001361 /// GetClassGlobal - Return the global variable for the Objective-C
1362 /// class of the given name.
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00001363 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001364
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001365 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001366 /// for the given class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001367 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001368 const ObjCInterfaceDecl *ID);
John McCall31168b02011-06-15 23:02:42 +00001369
1370 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
1371 IdentifierInfo *II);
1372
1373 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001374
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001375 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1376 /// for the given super class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001377 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1378 const ObjCInterfaceDecl *ID);
1379
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001380 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1381 /// meta-data
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001382 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001383 const ObjCInterfaceDecl *ID);
1384
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001385 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1386 /// the given ivar.
1387 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001388 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001389 const ObjCInterfaceDecl *ID,
1390 const ObjCIvarDecl *Ivar);
1391
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001392 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1393 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001394 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1395 bool lval=false);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001396
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001397 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001398 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001399 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001400 bool ForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001401
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001402 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar15894b72009-04-07 05:48:37 +00001403 return "OBJC_METACLASS_$_";
1404 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001405
Daniel Dunbar15894b72009-04-07 05:48:37 +00001406 const char *getClassSymbolPrefix() const {
1407 return "OBJC_CLASS_$_";
1408 }
1409
Daniel Dunbar961202372009-05-03 12:57:56 +00001410 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001411 uint32_t &InstanceStart,
1412 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001413
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001414 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001415 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001416 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1417 return CGM.getContext().Selectors.getSelector(0, &II);
1418 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001419
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001420 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001421 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1422 return CGM.getContext().Selectors.getSelector(1, &II);
1423 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001424
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001425 /// ImplementationIsNonLazy - Check whether the given category or
1426 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001427 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001428
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001429public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001430 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001431 // FIXME. All stubs for now!
1432 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001433
Fariborz Jahanian71394042009-01-23 23:53:38 +00001434 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001435 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001436 QualType ResultType,
1437 Selector Sel,
1438 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001439 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001440 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001441 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001442
1443 virtual CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001444 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001445 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001446 QualType ResultType,
1447 Selector Sel,
1448 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001449 bool isCategoryImpl,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001450 llvm::Value *Receiver,
1451 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001452 const CallArgList &CallArgs,
1453 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001454
Fariborz Jahanian71394042009-01-23 23:53:38 +00001455 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001456 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001457
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001458 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1459 bool lvalue = false)
1460 { return EmitSelector(Builder, Sel, lvalue); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001461
1462 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1463 /// untyped one.
1464 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1465 const ObjCMethodDecl *Method)
1466 { return EmitSelector(Builder, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001467
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00001468 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001469
Fariborz Jahanian71394042009-01-23 23:53:38 +00001470 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
David Chisnall92d436b2012-01-31 18:59:20 +00001471
Daniel Dunbarf3d3b012012-02-28 15:36:15 +00001472 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}
David Chisnall92d436b2012-01-31 18:59:20 +00001473
Fariborz Jahanian71394042009-01-23 23:53:38 +00001474 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian097feda2009-01-30 18:58:59 +00001475 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001476
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001477 virtual llvm::Constant *GetEHType(QualType T);
John McCall2ca705e2010-07-24 00:37:23 +00001478
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001479 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001480 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001481 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001482 virtual llvm::Constant *GetPropertySetFunction() {
1483 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001484 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001485
Ted Kremeneke65b0862012-03-06 20:05:56 +00001486 virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1487 bool copy) {
1488 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1489 }
1490
David Chisnall168b80f2010-12-26 22:13:16 +00001491 virtual llvm::Constant *GetSetStructFunction() {
1492 return ObjCTypes.getCopyStructFn();
1493 }
1494 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001495 return ObjCTypes.getCopyStructFn();
1496 }
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001497 virtual llvm::Constant *GetCppAtomicObjectFunction() {
1498 return ObjCTypes.getCppAtomicObjectFunction();
1499 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001500
Chris Lattnerd4808922009-03-22 21:03:39 +00001501 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001502 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001503 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001504
John McCallbd309292010-07-06 01:34:17 +00001505 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1506 const ObjCAtTryStmt &S);
1507 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1508 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001509 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlsson9ab53d12009-02-16 22:59:18 +00001510 const ObjCAtThrowStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001511 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001512 llvm::Value *AddrWeakObj);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001513 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001514 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001515 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001516 llvm::Value *src, llvm::Value *dest,
1517 bool threadlocal = false);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001518 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001519 llvm::Value *src, llvm::Value *dest,
1520 llvm::Value *ivarOffset);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001521 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001522 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001523 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1524 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001525 llvm::Value *size);
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001526 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1527 QualType ObjectTy,
1528 llvm::Value *BaseValue,
1529 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001530 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001531 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001532 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001533 const ObjCIvarDecl *Ivar);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001534};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001535
1536/// A helper class for performing the null-initialization of a return
1537/// value.
1538struct NullReturnState {
1539 llvm::BasicBlock *NullBB;
1540 llvm::BasicBlock *callBB;
1541 NullReturnState() : NullBB(0), callBB(0) {}
1542
1543 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1544 // Make blocks for the null-init and call edges.
1545 NullBB = CGF.createBasicBlock("msgSend.nullinit");
1546 callBB = CGF.createBasicBlock("msgSend.call");
1547
1548 // Check for a null receiver and, if there is one, jump to the
1549 // null-init test.
1550 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1551 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1552
1553 // Otherwise, start performing the call.
1554 CGF.EmitBlock(callBB);
1555 }
1556
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001557 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1558 const CallArgList &CallArgs,
1559 const ObjCMethodDecl *Method) {
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001560 if (!NullBB) return result;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001561
1562 llvm::Value *NullInitPtr = 0;
1563 if (result.isScalar() && !resultType->isVoidType()) {
1564 NullInitPtr = CGF.CreateTempAlloca(result.getScalarVal()->getType());
1565 CGF.Builder.CreateStore(result.getScalarVal(), NullInitPtr);
1566 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001567
1568 // Finish the call path.
1569 llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
1570 if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
1571
1572 // Emit the null-init block and perform the null-initialization there.
1573 CGF.EmitBlock(NullBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001574
1575 // Release consumed arguments along the null-receiver path.
1576 if (Method) {
1577 CallArgList::const_iterator I = CallArgs.begin();
1578 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1579 e = Method->param_end(); i != e; ++i, ++I) {
1580 const ParmVarDecl *ParamDecl = (*i);
1581 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1582 RValue RV = I->RV;
1583 assert(RV.isScalar() &&
1584 "NullReturnState::complete - arg not on object");
1585 CGF.EmitARCRelease(RV.getScalarVal(), true);
1586 }
1587 }
1588 }
1589
1590 if (result.isScalar()) {
1591 if (NullInitPtr)
1592 CGF.EmitNullInitialization(NullInitPtr, resultType);
1593 // Jump to the continuation block.
1594 CGF.EmitBlock(contBB);
1595 return NullInitPtr ? RValue::get(CGF.Builder.CreateLoad(NullInitPtr))
1596 : result;
1597 }
1598
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001599 if (!resultType->isAnyComplexType()) {
1600 assert(result.isAggregate() && "null init of non-aggregate result?");
1601 CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
1602 // Jump to the continuation block.
1603 CGF.EmitBlock(contBB);
1604 return result;
1605 }
1606
1607 // _Complex type
1608 // FIXME. Now easy to handle any other scalar type whose result is returned
1609 // in memory due to ABI limitations.
1610 CGF.EmitBlock(contBB);
1611 CodeGenFunction::ComplexPairTy CallCV = result.getComplexVal();
1612 llvm::Type *MemberType = CallCV.first->getType();
1613 llvm::Constant *ZeroCV = llvm::Constant::getNullValue(MemberType);
1614 // Create phi instruction for scalar complex value.
1615 llvm::PHINode *PHIReal = CGF.Builder.CreatePHI(MemberType, 2);
1616 PHIReal->addIncoming(ZeroCV, NullBB);
1617 PHIReal->addIncoming(CallCV.first, callBB);
1618 llvm::PHINode *PHIImag = CGF.Builder.CreatePHI(MemberType, 2);
1619 PHIImag->addIncoming(ZeroCV, NullBB);
1620 PHIImag->addIncoming(CallCV.second, callBB);
1621 return RValue::getComplex(PHIReal, PHIImag);
1622 }
1623};
1624
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001625} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001626
1627/* *** Helper Functions *** */
1628
1629/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001630static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001631 llvm::Constant *C,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001632 unsigned idx0,
1633 unsigned idx1) {
1634 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001635 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1636 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001637 };
Jay Foaded8db7d2011-07-21 14:31:17 +00001638 return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001639}
1640
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001641/// hasObjCExceptionAttribute - Return true if this class or any super
1642/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001643static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001644 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001645 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001646 return true;
1647 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001648 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001649 return false;
1650}
1651
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001652/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001653
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001654CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001655 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001656 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001657 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001658}
1659
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001660/// GetClass - Return a reference to the class for the given interface
1661/// decl.
Daniel Dunbarcb463852008-11-01 01:53:16 +00001662llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001663 const ObjCInterfaceDecl *ID) {
1664 return EmitClassRef(Builder, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001665}
1666
1667/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001668llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1669 bool lval) {
1670 return EmitSelector(Builder, Sel, lval);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001671}
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001672llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001673 *Method) {
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001674 return EmitSelector(Builder, Method->getSelector());
1675}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001676
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001677llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001678 if (T->isObjCIdType() ||
1679 T->isObjCQualifiedIdType()) {
1680 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001681 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001682 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001683 if (T->isObjCClassType() ||
1684 T->isObjCQualifiedClassType()) {
1685 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001686 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001687 }
1688 if (T->isObjCObjectPointerType())
1689 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1690
John McCall2ca705e2010-07-24 00:37:23 +00001691 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001692}
1693
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001694/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001695/*
1696 struct __builtin_CFString {
1697 const int *isa; // point to __CFConstantStringClassReference
1698 int flags;
1699 const char *str;
1700 long length;
1701 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001702*/
1703
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001704/// or Generate a constant NSString object.
1705/*
1706 struct __builtin_NSString {
1707 const int *isa; // point to __NSConstantStringClassReference
1708 const char *str;
1709 unsigned int length;
1710 };
1711*/
1712
Fariborz Jahanian71394042009-01-23 23:53:38 +00001713llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall481e3a82010-01-23 02:40:42 +00001714 const StringLiteral *SL) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001715 return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001716 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian50c925f2010-10-19 17:19:29 +00001717 CGM.GetAddrOfConstantString(SL));
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001718}
1719
Ted Kremeneke65b0862012-03-06 20:05:56 +00001720enum {
1721 kCFTaggedObjectID_Integer = (1 << 1) + 1
1722};
1723
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001724/// Generates a message send where the super is the receiver. This is
1725/// a message send to self with special delivery semantics indicating
1726/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001727CodeGen::RValue
1728CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001729 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001730 QualType ResultType,
1731 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001732 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001733 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001734 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001735 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001736 const CodeGen::CallArgList &CallArgs,
1737 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001738 // Create and init a super structure; this is a (receiver, class)
1739 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001740 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00001741 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001742 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001743 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001744 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001745 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001746
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001747 // If this is a class message the metaclass is passed as the target.
1748 llvm::Value *Target;
1749 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001750 if (isCategoryImpl) {
1751 // Message sent to 'super' in a class method defined in a category
1752 // implementation requires an odd treatment.
1753 // If we are in a class method, we must retrieve the
1754 // _metaclass_ for the current class, pointed at by
1755 // the class's "isa" pointer. The following assumes that
1756 // isa" is the first ivar in a class (which it must be).
1757 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1758 Target = CGF.Builder.CreateStructGEP(Target, 0);
1759 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00001760 } else {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001761 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1762 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1763 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1764 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001765 }
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00001766 }
1767 else if (isCategoryImpl)
1768 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1769 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001770 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1771 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1772 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001773 }
Mike Stump18bb9282009-05-16 07:57:57 +00001774 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1775 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00001776 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00001777 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00001778 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001779 CGF.Builder.CreateStore(Target,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001780 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall9e8bb002011-05-14 03:10:52 +00001781 return EmitMessageSend(CGF, Return, ResultType,
1782 EmitSelector(CGF.Builder, Sel),
1783 ObjCSuper, ObjCTypes.SuperPtrCTy,
1784 true, CallArgs, Method, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001785}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001786
1787/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001788CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001789 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001790 QualType ResultType,
1791 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001792 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001793 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001794 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001795 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00001796 return EmitMessageSend(CGF, Return, ResultType,
1797 EmitSelector(CGF.Builder, Sel),
1798 Receiver, CGF.getContext().getObjCIdType(),
1799 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001800}
1801
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001802CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00001803CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1804 ReturnValueSlot Return,
1805 QualType ResultType,
1806 llvm::Value *Sel,
1807 llvm::Value *Arg0,
1808 QualType Arg0Ty,
1809 bool IsSuper,
1810 const CallArgList &CallArgs,
1811 const ObjCMethodDecl *Method,
1812 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00001813 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00001814 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00001815 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00001816 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1817 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCall31168b02011-06-15 23:02:42 +00001818 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001819
John McCalla729c622012-02-17 03:33:10 +00001820 // If we're calling a method, use the formal signature.
1821 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001822
Anders Carlsson280e61f12010-06-21 20:59:55 +00001823 if (Method)
1824 assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1825 CGM.getContext().getCanonicalType(ResultType) &&
1826 "Result type mismatch!");
1827
John McCall5880fb82011-05-14 21:12:11 +00001828 NullReturnState nullReturn;
1829
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001830 llvm::Constant *Fn = NULL;
John McCalla729c622012-02-17 03:33:10 +00001831 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001832 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001833 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001834 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001835 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1836 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1837 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00001838 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
1839 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
1840 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001841 } else {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001842 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001843 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001844 }
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001845
1846 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001847 if (CGM.getLangOpts().ObjCAutoRefCount && Method)
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001848 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1849 e = Method->param_end(); i != e; ++i) {
1850 const ParmVarDecl *ParamDecl = (*i);
1851 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1852 if (!nullReturn.NullBB)
1853 nullReturn.init(CGF, Arg0);
1854 requiresnullCheck = true;
1855 break;
1856 }
1857 }
1858
John McCalla729c622012-02-17 03:33:10 +00001859 Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
1860 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001861 return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
1862 requiresnullCheck ? Method : 0);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001863}
1864
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001865static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1866 if (FQT.isObjCGCStrong())
1867 return Qualifiers::Strong;
1868
John McCall31168b02011-06-15 23:02:42 +00001869 if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001870 return Qualifiers::Weak;
1871
Fariborz Jahanian430b35e2012-02-16 00:15:02 +00001872 // check for __unsafe_unretained
1873 if (FQT.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
1874 return Qualifiers::GCNone;
1875
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001876 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1877 return Qualifiers::Strong;
1878
1879 if (const PointerType *PT = FQT->getAs<PointerType>())
1880 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1881
1882 return Qualifiers::GCNone;
1883}
1884
John McCall351762c2011-02-07 10:33:21 +00001885llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1886 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00001887
Chris Lattnerece04092012-02-07 00:39:47 +00001888 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001889 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
1890 !CGM.getLangOpts().ObjCAutoRefCount)
John McCall351762c2011-02-07 10:33:21 +00001891 return nullPtr;
1892
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001893 bool hasUnion = false;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001894 SkipIvars.clear();
1895 IvarsInfo.clear();
Eli Friedman8cbca202012-11-06 22:15:52 +00001896 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
1897 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001898
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00001899 // __isa is the first field in block descriptor and must assume by runtime's
1900 // convention that it is GC'able.
Eli Friedman8cbca202012-11-06 22:15:52 +00001901 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall351762c2011-02-07 10:33:21 +00001902
1903 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1904
1905 // Calculate the basic layout of the block structure.
1906 const llvm::StructLayout *layout =
Micah Villmowdd31ca12012-10-08 16:25:52 +00001907 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
John McCall351762c2011-02-07 10:33:21 +00001908
1909 // Ignore the optional 'this' capture: C++ objects are not assumed
1910 // to be GC'ed.
1911
1912 // Walk the captured variables.
1913 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1914 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1915 const VarDecl *variable = ci->getVariable();
1916 QualType type = variable->getType();
1917
1918 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1919
1920 // Ignore constant captures.
1921 if (capture.isConstant()) continue;
1922
Eli Friedman8cbca202012-11-06 22:15:52 +00001923 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
John McCall351762c2011-02-07 10:33:21 +00001924
1925 // __block variables are passed by their descriptor address.
1926 if (ci->isByRef()) {
Eli Friedman8cbca202012-11-06 22:15:52 +00001927 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00001928 continue;
John McCall351762c2011-02-07 10:33:21 +00001929 }
1930
1931 assert(!type->isArrayType() && "array variable should not be caught");
1932 if (const RecordType *record = type->getAs<RecordType>()) {
1933 BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00001934 continue;
1935 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001936
John McCall351762c2011-02-07 10:33:21 +00001937 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
Eli Friedman8cbca202012-11-06 22:15:52 +00001938 unsigned fieldSize = CGM.getContext().getTypeSize(type);
John McCall351762c2011-02-07 10:33:21 +00001939
1940 if (GCAttr == Qualifiers::Strong)
Eli Friedman8cbca202012-11-06 22:15:52 +00001941 IvarsInfo.push_back(GC_IVAR(fieldOffset,
1942 fieldSize / WordSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001943 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
Eli Friedman8cbca202012-11-06 22:15:52 +00001944 SkipIvars.push_back(GC_IVAR(fieldOffset,
1945 fieldSize / ByteSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001946 }
1947
1948 if (IvarsInfo.empty())
John McCall351762c2011-02-07 10:33:21 +00001949 return nullPtr;
1950
1951 // Sort on byte position; captures might not be allocated in order,
1952 // and unions can do funny things.
1953 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
1954 llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001955
1956 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00001957 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001958 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001959 printf("\n block variable layout for block: ");
Roman Divackye6377112012-09-06 15:59:27 +00001960 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00001961 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001962 if (!(s[i] & 0xf0))
1963 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1964 else
1965 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
1966 printf("\n");
1967 }
1968
1969 return C;
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001970}
1971
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00001972/// getBlockCaptureLifetime - This routine returns life time of the captured
1973/// block variable for the purpose of block layout meta-data generation. FQT is
1974/// the type of the variable captured in the block.
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001975Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
1976 bool ByrefLayout) {
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00001977 if (CGM.getLangOpts().ObjCAutoRefCount)
1978 return FQT.getObjCLifetime();
1979
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00001980 // MRR.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00001981 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001982 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00001983
1984 return Qualifiers::OCL_None;
1985}
1986
Fariborz Jahanian39319c42012-10-30 20:05:29 +00001987void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
1988 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00001989 CharUnits FieldOffset,
1990 CharUnits FieldSize) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00001991 // __block variables are passed by their descriptor address.
1992 if (IsByref)
1993 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00001994 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00001995 else if (LifeTime == Qualifiers::OCL_Strong)
1996 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00001997 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00001998 else if (LifeTime == Qualifiers::OCL_Weak)
1999 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002000 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002001 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2002 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002003 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002004 else
2005 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2006 FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002007 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002008}
2009
2010void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2011 const RecordDecl *RD,
2012 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002013 CharUnits BytePos, bool &HasUnion,
2014 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002015 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002016 CharUnits MaxUnionSize = CharUnits::Zero();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002017 const FieldDecl *MaxField = 0;
2018 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002019 CharUnits MaxFieldOffset = CharUnits::Zero();
2020 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002021
2022 if (RecFields.empty())
2023 return;
2024 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
2025
2026 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2027 const FieldDecl *Field = RecFields[i];
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002028 // Note that 'i' here is actually the field index inside RD of Field,
2029 // although this dependency is hidden.
2030 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002031 CharUnits FieldOffset =
2032 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002033
2034 // Skip over unnamed or bitfields
2035 if (!Field->getIdentifier() || Field->isBitField()) {
2036 LastFieldBitfieldOrUnnamed = Field;
2037 LastBitfieldOrUnnamedOffset = FieldOffset;
2038 continue;
2039 }
2040
2041 LastFieldBitfieldOrUnnamed = 0;
2042 QualType FQT = Field->getType();
2043 if (FQT->isRecordType() || FQT->isUnionType()) {
2044 if (FQT->isUnionType())
2045 HasUnion = true;
2046
2047 BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2048 BytePos + FieldOffset, HasUnion);
2049 continue;
2050 }
2051
2052 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2053 const ConstantArrayType *CArray =
2054 dyn_cast_or_null<ConstantArrayType>(Array);
2055 uint64_t ElCount = CArray->getSize().getZExtValue();
2056 assert(CArray && "only array with known element size is supported");
2057 FQT = CArray->getElementType();
2058 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2059 const ConstantArrayType *CArray =
2060 dyn_cast_or_null<ConstantArrayType>(Array);
2061 ElCount *= CArray->getSize().getZExtValue();
2062 FQT = CArray->getElementType();
2063 }
2064
2065 assert(!FQT->isUnionType() &&
2066 "layout for array of unions not supported");
2067 if (FQT->isRecordType() && ElCount) {
2068 int OldIndex = RunSkipBlockVars.size() - 1;
2069 const RecordType *RT = FQT->getAs<RecordType>();
2070 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2071 HasUnion);
2072
2073 // Replicate layout information for each array element. Note that
2074 // one element is already done.
2075 uint64_t ElIx = 1;
2076 for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002077 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002078 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2079 RunSkipBlockVars.push_back(
2080 RUN_SKIP(RunSkipBlockVars[i].opcode,
2081 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2082 RunSkipBlockVars[i].block_var_size));
2083 }
2084 continue;
2085 }
2086 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002087 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002088 if (IsUnion) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002089 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002090 if (UnionIvarSize > MaxUnionSize) {
2091 MaxUnionSize = UnionIvarSize;
2092 MaxField = Field;
2093 MaxFieldOffset = FieldOffset;
2094 }
2095 } else {
2096 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002097 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002098 BytePos + FieldOffset,
2099 FieldSize);
2100 }
2101 }
2102
2103 if (LastFieldBitfieldOrUnnamed) {
2104 if (LastFieldBitfieldOrUnnamed->isBitField()) {
2105 // Last field was a bitfield. Must update the info.
2106 uint64_t BitFieldSize
2107 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002108 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedman8cbca202012-11-06 22:15:52 +00002109 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002110 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002111 Size += LastBitfieldOrUnnamedOffset;
2112 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002113 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2114 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002115 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002116 Size);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002117 } else {
2118 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2119 // Last field was unnamed. Must update skip info.
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002120 CharUnits FieldSize
2121 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002122 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002123 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2124 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002125 BytePos + LastBitfieldOrUnnamedOffset,
2126 FieldSize);
2127 }
2128 }
2129
2130 if (MaxField)
2131 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002132 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002133 BytePos + MaxFieldOffset,
2134 MaxUnionSize);
2135}
2136
2137void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002138 CharUnits BytePos,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002139 bool &HasUnion,
2140 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002141 const RecordDecl *RD = RT->getDecl();
2142 SmallVector<const FieldDecl*, 16> Fields;
2143 for (RecordDecl::field_iterator i = RD->field_begin(),
2144 e = RD->field_end(); i != e; ++i)
2145 Fields.push_back(*i);
2146 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2147 const llvm::StructLayout *RecLayout =
2148 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2149
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002150 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002151}
2152
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002153/// InlineLayoutInstruction - This routine produce an inline instruction for the
2154/// block variable layout if it can. If not, it returns 0. Rules are as follow:
2155/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2156/// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2157/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2158/// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2159/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2160/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2161/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
2162uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2163 SmallVectorImpl<unsigned char> &Layout) {
2164 uint64_t Result = 0;
2165 if (Layout.size() <= 3) {
2166 unsigned size = Layout.size();
2167 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2168 unsigned char inst;
2169 enum BLOCK_LAYOUT_OPCODE opcode ;
2170 switch (size) {
2171 case 3:
2172 inst = Layout[0];
2173 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2174 if (opcode == BLOCK_LAYOUT_STRONG)
2175 strong_word_count = (inst & 0xF)+1;
2176 else
2177 return 0;
2178 inst = Layout[1];
2179 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2180 if (opcode == BLOCK_LAYOUT_BYREF)
2181 byref_word_count = (inst & 0xF)+1;
2182 else
2183 return 0;
2184 inst = Layout[2];
2185 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2186 if (opcode == BLOCK_LAYOUT_WEAK)
2187 weak_word_count = (inst & 0xF)+1;
2188 else
2189 return 0;
2190 break;
2191
2192 case 2:
2193 inst = Layout[0];
2194 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2195 if (opcode == BLOCK_LAYOUT_STRONG) {
2196 strong_word_count = (inst & 0xF)+1;
2197 inst = Layout[1];
2198 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2199 if (opcode == BLOCK_LAYOUT_BYREF)
2200 byref_word_count = (inst & 0xF)+1;
2201 else if (opcode == BLOCK_LAYOUT_WEAK)
2202 weak_word_count = (inst & 0xF)+1;
2203 else
2204 return 0;
2205 }
2206 else if (opcode == BLOCK_LAYOUT_BYREF) {
2207 byref_word_count = (inst & 0xF)+1;
2208 inst = Layout[1];
2209 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2210 if (opcode == BLOCK_LAYOUT_WEAK)
2211 weak_word_count = (inst & 0xF)+1;
2212 else
2213 return 0;
2214 }
2215 else
2216 return 0;
2217 break;
2218
2219 case 1:
2220 inst = Layout[0];
2221 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2222 if (opcode == BLOCK_LAYOUT_STRONG)
2223 strong_word_count = (inst & 0xF)+1;
2224 else if (opcode == BLOCK_LAYOUT_BYREF)
2225 byref_word_count = (inst & 0xF)+1;
2226 else if (opcode == BLOCK_LAYOUT_WEAK)
2227 weak_word_count = (inst & 0xF)+1;
2228 else
2229 return 0;
2230 break;
2231
2232 default:
2233 return 0;
2234 }
2235
2236 // Cannot inline when any of the word counts is 15. Because this is one less
2237 // than the actual work count (so 15 means 16 actual word counts),
2238 // and we can only display 0 thru 15 word counts.
2239 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2240 return 0;
2241
2242 unsigned count =
2243 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2244
2245 if (size == count) {
2246 if (strong_word_count)
2247 Result = strong_word_count;
2248 Result <<= 4;
2249 if (byref_word_count)
2250 Result += byref_word_count;
2251 Result <<= 4;
2252 if (weak_word_count)
2253 Result += weak_word_count;
2254 }
2255 }
2256 return Result;
2257}
2258
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002259llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2260 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2261 if (RunSkipBlockVars.empty())
2262 return nullPtr;
2263 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
2264 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
2265 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2266
2267 // Sort on byte position; captures might not be allocated in order,
2268 // and unions can do funny things.
2269 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2270 SmallVector<unsigned char, 16> Layout;
2271
2272 unsigned size = RunSkipBlockVars.size();
2273 for (unsigned i = 0; i < size; i++) {
2274 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2275 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2276 CharUnits end_byte_pos = start_byte_pos;
2277 unsigned j = i+1;
2278 while (j < size) {
2279 if (opcode == RunSkipBlockVars[j].opcode) {
2280 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2281 i++;
2282 }
2283 else
2284 break;
2285 }
2286 CharUnits size_in_bytes =
2287 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2288 if (j < size) {
2289 CharUnits gap =
2290 RunSkipBlockVars[j].block_var_bytepos -
2291 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2292 size_in_bytes += gap;
2293 }
2294 CharUnits residue_in_bytes = CharUnits::Zero();
2295 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2296 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2297 size_in_bytes -= residue_in_bytes;
2298 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2299 }
2300
2301 unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2302 while (size_in_words >= 16) {
2303 // Note that value in imm. is one less that the actual
2304 // value. So, 0xf means 16 words follow!
2305 unsigned char inst = (opcode << 4) | 0xf;
2306 Layout.push_back(inst);
2307 size_in_words -= 16;
2308 }
2309 if (size_in_words > 0) {
2310 // Note that value in imm. is one less that the actual
2311 // value. So, we subtract 1 away!
2312 unsigned char inst = (opcode << 4) | (size_in_words-1);
2313 Layout.push_back(inst);
2314 }
2315 if (residue_in_bytes > CharUnits::Zero()) {
2316 unsigned char inst =
2317 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2318 Layout.push_back(inst);
2319 }
2320 }
2321
2322 int e = Layout.size()-1;
2323 while (e >= 0) {
2324 unsigned char inst = Layout[e--];
2325 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2326 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2327 Layout.pop_back();
2328 else
2329 break;
2330 }
2331
2332 uint64_t Result = InlineLayoutInstruction(Layout);
2333 if (Result != 0) {
2334 // Block variable layout instruction has been inlined.
2335 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2336 if (ComputeByrefLayout)
2337 printf("\n Inline instruction for BYREF variable layout: ");
2338 else
2339 printf("\n Inline instruction for block variable layout: ");
2340 printf("0x0%llx\n", (unsigned long long)Result);
2341 }
2342 if (WordSizeInBytes == 8) {
2343 const llvm::APInt Instruction(64, Result);
2344 return llvm::Constant::getIntegerValue(CGM.Int64Ty, Instruction);
2345 }
2346 else {
2347 const llvm::APInt Instruction(32, Result);
2348 return llvm::Constant::getIntegerValue(CGM.Int32Ty, Instruction);
2349 }
2350 }
2351
2352 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2353 Layout.push_back(inst);
2354 std::string BitMap;
2355 for (unsigned i = 0, e = Layout.size(); i != e; i++)
2356 BitMap += Layout[i];
2357
2358 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2359 if (ComputeByrefLayout)
2360 printf("\n BYREF variable layout: ");
2361 else
2362 printf("\n block variable layout: ");
2363 for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2364 unsigned char inst = BitMap[i];
2365 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2366 unsigned delta = 1;
2367 switch (opcode) {
2368 case BLOCK_LAYOUT_OPERATOR:
2369 printf("BL_OPERATOR:");
2370 delta = 0;
2371 break;
2372 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2373 printf("BL_NON_OBJECT_BYTES:");
2374 break;
2375 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2376 printf("BL_NON_OBJECT_WORD:");
2377 break;
2378 case BLOCK_LAYOUT_STRONG:
2379 printf("BL_STRONG:");
2380 break;
2381 case BLOCK_LAYOUT_BYREF:
2382 printf("BL_BYREF:");
2383 break;
2384 case BLOCK_LAYOUT_WEAK:
2385 printf("BL_WEAK:");
2386 break;
2387 case BLOCK_LAYOUT_UNRETAINED:
2388 printf("BL_UNRETAINED:");
2389 break;
2390 }
2391 // Actual value of word count is one more that what is in the imm.
2392 // field of the instruction
2393 printf("%d", (inst & 0xf) + delta);
2394 if (i < e-1)
2395 printf(", ");
2396 else
2397 printf("\n");
2398 }
2399 }
2400
2401 llvm::GlobalVariable * Entry =
2402 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
2403 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
2404 "__TEXT,__objc_classname,cstring_literals", 1, true);
2405 return getConstantGEP(VMContext, Entry, 0, 0);
2406}
2407
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002408llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2409 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002410 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2411
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002412 RunSkipBlockVars.clear();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002413 bool hasUnion = false;
2414
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002415 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
2416 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
2417 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2418
2419 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2420
2421 // Calculate the basic layout of the block structure.
2422 const llvm::StructLayout *layout =
2423 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
2424
2425 // Ignore the optional 'this' capture: C++ objects are not assumed
2426 // to be GC'ed.
2427
2428 // Walk the captured variables.
2429 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
2430 ce = blockDecl->capture_end(); ci != ce; ++ci) {
2431 const VarDecl *variable = ci->getVariable();
2432 QualType type = variable->getType();
2433
2434 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2435
2436 // Ignore constant captures.
2437 if (capture.isConstant()) continue;
2438
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002439 CharUnits fieldOffset =
2440 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002441
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002442 assert(!type->isArrayType() && "array variable should not be caught");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002443 if (!ci->isByRef())
2444 if (const RecordType *record = type->getAs<RecordType>()) {
2445 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2446 continue;
2447 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002448 CharUnits fieldSize;
2449 if (ci->isByRef())
2450 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2451 else
2452 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002453 UpdateRunSkipBlockVars(ci->isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002454 fieldOffset, fieldSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002455 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002456 return getBitmapBlockLayout(false);
2457}
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002458
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002459
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002460llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2461 QualType T) {
2462 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2463 assert(!T->isArrayType() && "__block array variable should not be caught");
2464 CharUnits fieldOffset;
2465 RunSkipBlockVars.clear();
2466 bool hasUnion = false;
2467 if (const RecordType *record = T->getAs<RecordType>()) {
2468 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
2469 llvm::Constant *Result = getBitmapBlockLayout(true);
2470 return Result;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002471 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002472 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2473 return nullPtr;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002474}
2475
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002476llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00002477 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00002478 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002479 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00002480 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2481
Owen Andersonade90fd2009-07-29 18:54:39 +00002482 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00002483 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002484}
2485
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002486void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00002487 // FIXME: We shouldn't need this, the protocol decl should contain enough
2488 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00002489 DefinedProtocols.insert(PD->getIdentifier());
2490
2491 // If we have generated a forward reference to this protocol, emit
2492 // it now. Otherwise do nothing, the protocol objects are lazily
2493 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002494 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00002495 GetOrEmitProtocol(PD);
2496}
2497
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002498llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002499 if (DefinedProtocols.count(PD->getIdentifier()))
2500 return GetOrEmitProtocol(PD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002501
Daniel Dunbarc475d422008-10-29 22:36:39 +00002502 return GetOrEmitProtocolRef(PD);
2503}
2504
Daniel Dunbarb036db82008-08-13 03:21:16 +00002505/*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002506// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
2507struct _objc_protocol {
2508struct _objc_protocol_extension *isa;
2509char *protocol_name;
2510struct _objc_protocol_list *protocol_list;
2511struct _objc__method_prototype_list *instance_methods;
2512struct _objc__method_prototype_list *class_methods
2513};
Daniel Dunbarb036db82008-08-13 03:21:16 +00002514
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002515See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00002516*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00002517llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00002518 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00002519
2520 // Early exit if a defining object has already been generated.
2521 if (Entry && Entry->hasInitializer())
2522 return Entry;
2523
Douglas Gregora715bff2012-01-01 19:51:50 +00002524 // Use the protocol definition, if there is one.
2525 if (const ObjCProtocolDecl *Def = PD->getDefinition())
2526 PD = Def;
2527
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002528 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002529 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002530 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2531
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002532 // Construct method lists.
2533 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2534 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002535 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002536 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002537 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002538 ObjCMethodDecl *MD = *i;
2539 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002540 if (!C)
2541 return GetOrEmitProtocolRef(PD);
2542
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002543 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2544 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002545 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002546 } else {
2547 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002548 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002549 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002550 }
2551
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002552 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002553 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002554 ObjCMethodDecl *MD = *i;
2555 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002556 if (!C)
2557 return GetOrEmitProtocolRef(PD);
2558
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002559 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2560 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002561 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002562 } else {
2563 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002564 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002565 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002566 }
2567
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002568 MethodTypesExt.insert(MethodTypesExt.end(),
2569 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
2570
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002571 llvm::Constant *Values[] = {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002572 EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
2573 MethodTypesExt),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002574 GetClassName(PD->getIdentifier()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002575 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00002576 PD->protocol_begin(),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002577 PD->protocol_end()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002578 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002579 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002580 InstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002581 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002582 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002583 ClassMethods)
2584 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002585 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002586 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002587
Daniel Dunbarb036db82008-08-13 03:21:16 +00002588 if (Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002589 // Already created, fix the linkage and update the initializer.
2590 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002591 Entry->setInitializer(Init);
2592 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002593 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002594 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002595 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002596 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002597 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002598 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002599 // FIXME: Is this necessary? Why only for protocol?
2600 Entry->setAlignment(4);
John McCallf9582a72012-03-30 21:29:05 +00002601
2602 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002603 }
Chris Lattnerf56501c2009-07-17 23:57:13 +00002604 CGM.AddUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00002605
2606 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002607}
2608
Daniel Dunbarc475d422008-10-29 22:36:39 +00002609llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002610 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2611
2612 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002613 // We use the initializer as a marker of whether this is a forward
2614 // reference or not. At module finalization we add the empty
2615 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002616 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002617 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarc475d422008-10-29 22:36:39 +00002618 llvm::GlobalValue::ExternalLinkage,
2619 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002620 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002621 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002622 // FIXME: Is this necessary? Why only for protocol?
2623 Entry->setAlignment(4);
2624 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002625
Daniel Dunbarb036db82008-08-13 03:21:16 +00002626 return Entry;
2627}
2628
2629/*
2630 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002631 uint32_t size;
2632 struct objc_method_description_list *optional_instance_methods;
2633 struct objc_method_description_list *optional_class_methods;
2634 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002635 const char ** extendedMethodTypes;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002636 };
2637*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002638llvm::Constant *
2639CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002640 ArrayRef<llvm::Constant*> OptInstanceMethods,
2641 ArrayRef<llvm::Constant*> OptClassMethods,
2642 ArrayRef<llvm::Constant*> MethodTypesExt) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002643 uint64_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002644 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002645 llvm::Constant *Values[] = {
2646 llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002647 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002648 + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002649 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002650 OptInstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002651 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002652 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002653 OptClassMethods),
2654 EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002655 ObjCTypes),
2656 EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
2657 MethodTypesExt, ObjCTypes)
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002658 };
Daniel Dunbarb036db82008-08-13 03:21:16 +00002659
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002660 // Return null if no extension bits are used.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002661 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002662 Values[3]->isNullValue() && Values[4]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002663 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002664
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002665 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002666 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002667
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002668 // No special section, but goes in llvm.used
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002669 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002670 Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002671 0, 0, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002672}
2673
2674/*
2675 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002676 struct objc_protocol_list *next;
2677 long count;
2678 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002679 };
2680*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00002681llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002682CGObjCMac::EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00002683 ObjCProtocolDecl::protocol_iterator begin,
2684 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendlinga515b582012-02-09 22:16:49 +00002685 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002686
Daniel Dunbardec75f82008-08-21 21:57:41 +00002687 for (; begin != end; ++begin)
2688 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002689
2690 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002691 if (ProtocolRefs.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002692 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002693
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002694 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00002695 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002696
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002697 llvm::Constant *Values[3];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002698 // This field is only used by the runtime.
Owen Anderson0b75f232009-07-31 20:28:54 +00002699 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002700 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002701 ProtocolRefs.size() - 1);
2702 Values[2] =
2703 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
2704 ProtocolRefs.size()),
Daniel Dunbarb036db82008-08-13 03:21:16 +00002705 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002706
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002707 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002708 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002709 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002710 4, false);
Owen Andersonade90fd2009-07-29 18:54:39 +00002711 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002712}
2713
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002714void CGObjCCommonMac::
2715PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
Bill Wendlinga515b582012-02-09 22:16:49 +00002716 llvm::SmallVectorImpl<llvm::Constant*> &Properties,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002717 const Decl *Container,
2718 const ObjCProtocolDecl *PROTO,
2719 const ObjCCommonTypesHelper &ObjCTypes) {
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002720 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
2721 E = PROTO->protocol_end(); P != E; ++P)
2722 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
2723 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
2724 E = PROTO->prop_end(); I != E; ++I) {
David Blaikie40ed2972012-06-06 20:45:41 +00002725 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002726 if (!PropertySet.insert(PD->getIdentifier()))
2727 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002728 llvm::Constant *Prop[] = {
2729 GetPropertyName(PD->getIdentifier()),
2730 GetPropertyTypeString(PD, Container)
2731 };
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002732 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
2733 }
2734}
2735
Daniel Dunbarb036db82008-08-13 03:21:16 +00002736/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002737 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00002738 const char * const name;
2739 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002740 };
2741
2742 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002743 uint32_t entsize; // sizeof (struct _objc_property)
2744 uint32_t prop_count;
2745 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002746 };
2747*/
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002748llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002749 const Decl *Container,
2750 const ObjCContainerDecl *OCD,
2751 const ObjCCommonTypesHelper &ObjCTypes) {
Bill Wendlinga515b582012-02-09 22:16:49 +00002752 llvm::SmallVector<llvm::Constant*, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002753 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002754 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2755 E = OCD->prop_end(); I != E; ++I) {
David Blaikie40ed2972012-06-06 20:45:41 +00002756 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002757 PropertySet.insert(PD->getIdentifier());
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002758 llvm::Constant *Prop[] = {
2759 GetPropertyName(PD->getIdentifier()),
2760 GetPropertyTypeString(PD, Container)
2761 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002762 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002763 Prop));
2764 }
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002765 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002766 for (ObjCInterfaceDecl::all_protocol_iterator
2767 P = OID->all_referenced_protocol_begin(),
2768 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002769 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2770 ObjCTypes);
2771 }
2772 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2773 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
2774 E = CD->protocol_end(); P != E; ++P)
2775 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2776 ObjCTypes);
2777 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002778
2779 // Return null for empty list.
2780 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002781 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002782
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002783 unsigned PropertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002784 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002785 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002786 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2787 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002788 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002789 Properties.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002790 Values[2] = llvm::ConstantArray::get(AT, Properties);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002791 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002792
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002793 llvm::GlobalVariable *GV =
2794 CreateMetadataVar(Name, Init,
2795 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002796 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002797 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002798 true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002799 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002800}
2801
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002802llvm::Constant *
2803CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
2804 ArrayRef<llvm::Constant*> MethodTypes,
2805 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002806 // Return null for empty list.
2807 if (MethodTypes.empty())
2808 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
2809
2810 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
2811 MethodTypes.size());
2812 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
2813
2814 llvm::GlobalVariable *GV =
2815 CreateMetadataVar(Name, Init,
2816 (ObjCABI == 2) ? "__DATA, __objc_const" : 0,
2817 (ObjCABI == 2) ? 8 : 4,
2818 true);
2819 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
2820}
2821
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002822/*
Daniel Dunbarb036db82008-08-13 03:21:16 +00002823 struct objc_method_description_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002824 int count;
2825 struct objc_method_description list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002826 };
2827*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002828llvm::Constant *
2829CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002830 llvm::Constant *Desc[] = {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002831 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002832 ObjCTypes.SelectorPtrTy),
2833 GetMethodVarType(MD)
2834 };
Douglas Gregora9d84932011-05-27 01:19:52 +00002835 if (!Desc[1])
2836 return 0;
2837
Owen Anderson0e0189d2009-07-27 22:29:56 +00002838 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002839 Desc);
2840}
Daniel Dunbarb036db82008-08-13 03:21:16 +00002841
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002842llvm::Constant *
2843CGObjCMac::EmitMethodDescList(Twine Name, const char *Section,
2844 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002845 // Return null for empty list.
2846 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002847 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002848
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002849 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002850 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002851 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002852 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002853 Values[1] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002854 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002855
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002856 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002857 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002858 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002859}
2860
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002861/*
2862 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002863 char *category_name;
2864 char *class_name;
2865 struct _objc_method_list *instance_methods;
2866 struct _objc_method_list *class_methods;
2867 struct _objc_protocol_list *protocols;
2868 uint32_t size; // <rdar://4585769>
2869 struct _objc_property_list *instance_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002870 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002871*/
Daniel Dunbar92992502008-08-15 22:20:32 +00002872void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00002873 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002874
Mike Stump18bb9282009-05-16 07:57:57 +00002875 // FIXME: This is poor design, the OCD should have a pointer to the category
2876 // decl. Additionally, note that Category can be null for the @implementation
2877 // w/o an @interface case. Sema should just create one for us as it does for
2878 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002879 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002880 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002881 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002882
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002883 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002884 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2885 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002886
Bill Wendlinga515b582012-02-09 22:16:49 +00002887 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002888 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002889 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002890 // Instance methods should always be defined.
2891 InstanceMethods.push_back(GetMethodConstant(*i));
2892 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002893 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002894 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002895 // Class methods should always be defined.
2896 ClassMethods.push_back(GetMethodConstant(*i));
2897 }
2898
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002899 llvm::Constant *Values[7];
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002900 Values[0] = GetClassName(OCD->getIdentifier());
2901 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00002902 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002903 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002904 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002905 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002906 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002907 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002908 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002909 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002910 ClassMethods);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002911 if (Category) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002912 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002913 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002914 Category->protocol_begin(),
2915 Category->protocol_end());
2916 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002917 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002918 }
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002919 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002920
2921 // If there is no category @interface then there can be no properties.
2922 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002923 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002924 OCD, Category, ObjCTypes);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002925 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002926 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002927 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002928
Owen Anderson0e0189d2009-07-27 22:29:56 +00002929 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002930 Values);
2931
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002932 llvm::GlobalVariable *GV =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002933 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002934 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002935 4, true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002936 DefinedCategories.push_back(GV);
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00002937 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002938 // method definition entries must be clear for next implementation.
2939 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002940}
2941
John McCallef19dbb2012-10-17 04:53:23 +00002942enum FragileClassFlags {
2943 FragileABI_Class_Factory = 0x00001,
2944 FragileABI_Class_Meta = 0x00002,
2945 FragileABI_Class_HasCXXStructors = 0x02000,
2946 FragileABI_Class_Hidden = 0x20000
2947};
2948
2949enum NonFragileClassFlags {
2950 /// Is a meta-class.
2951 NonFragileABI_Class_Meta = 0x00001,
2952
2953 /// Is a root class.
2954 NonFragileABI_Class_Root = 0x00002,
2955
2956 /// Has a C++ constructor and destructor.
2957 NonFragileABI_Class_HasCXXStructors = 0x00004,
2958
2959 /// Has hidden visibility.
2960 NonFragileABI_Class_Hidden = 0x00010,
2961
2962 /// Has the exception attribute.
2963 NonFragileABI_Class_Exception = 0x00020,
2964
2965 /// (Obsolete) ARC-specific: this class has a .release_ivars method
2966 NonFragileABI_Class_HasIvarReleaser = 0x00040,
2967
2968 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00002969 NonFragileABI_Class_CompiledByARC = 0x00080,
2970
2971 /// Class has non-trivial destructors, but zero-initialization is okay.
2972 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002973};
2974
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002975/*
2976 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002977 Class isa;
2978 Class super_class;
2979 const char *name;
2980 long version;
2981 long info;
2982 long instance_size;
2983 struct _objc_ivar_list *ivars;
2984 struct _objc_method_list *methods;
2985 struct _objc_cache *cache;
2986 struct _objc_protocol_list *protocols;
2987 // Objective-C 1.0 extensions (<rdr://4585769>)
2988 const char *ivar_layout;
2989 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002990 };
2991
2992 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002993*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002994void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002995 DefinedSymbols.insert(ID->getIdentifier());
2996
Chris Lattner86d7d912008-11-24 03:54:41 +00002997 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002998 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002999 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003000 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003001 llvm::Constant *Protocols =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003002 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003003 Interface->all_referenced_protocol_begin(),
3004 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00003005 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00003006 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00003007 Flags |= FragileABI_Class_HasCXXStructors;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003008 unsigned Size =
Ken Dyckc8ae5502011-02-09 01:59:34 +00003009 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003010
3011 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00003012 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003013 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003014
Bill Wendlinga515b582012-02-09 22:16:49 +00003015 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003016 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003017 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003018 // Instance methods should always be defined.
3019 InstanceMethods.push_back(GetMethodConstant(*i));
3020 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003021 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003022 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003023 // Class methods should always be defined.
3024 ClassMethods.push_back(GetMethodConstant(*i));
3025 }
3026
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003027 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003028 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie40ed2972012-06-06 20:45:41 +00003029 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003030
3031 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3032 ObjCPropertyDecl *PD = PID->getPropertyDecl();
3033
3034 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
3035 if (llvm::Constant *C = GetMethodConstant(MD))
3036 InstanceMethods.push_back(C);
3037 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
3038 if (llvm::Constant *C = GetMethodConstant(MD))
3039 InstanceMethods.push_back(C);
3040 }
3041 }
3042
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003043 llvm::Constant *Values[12];
Daniel Dunbarccf61832009-05-03 08:56:52 +00003044 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003045 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003046 // Record a reference to the super class.
3047 LazySymbols.insert(Super->getIdentifier());
3048
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003049 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003050 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003051 ObjCTypes.ClassPtrTy);
3052 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00003053 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003054 }
3055 Values[ 2] = GetClassName(ID->getIdentifier());
3056 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003057 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3058 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3059 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003060 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003061 Values[ 7] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003062 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003063 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003064 InstanceMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003065 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003066 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003067 Values[ 9] = Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003068 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003069 Values[11] = EmitClassExtension(ID);
Owen Anderson0e0189d2009-07-27 22:29:56 +00003070 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003071 Values);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003072 std::string Name("\01L_OBJC_CLASS_");
3073 Name += ClassName;
3074 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3075 // Check for a forward reference.
3076 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
3077 if (GV) {
3078 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3079 "Forward metaclass reference has incorrect type.");
3080 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
3081 GV->setInitializer(Init);
3082 GV->setSection(Section);
3083 GV->setAlignment(4);
3084 CGM.AddUsedGlobal(GV);
3085 }
3086 else
3087 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003088 DefinedClasses.push_back(GV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003089 // method definition entries must be clear for next implementation.
3090 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003091}
3092
3093llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3094 llvm::Constant *Protocols,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003095 ArrayRef<llvm::Constant*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00003096 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00003097 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003098
John McCall457a04e2010-10-22 21:05:15 +00003099 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003100 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003101
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003102 llvm::Constant *Values[12];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003103 // The isa for the metaclass is the root of the hierarchy.
3104 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3105 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3106 Root = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003107 Values[ 0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003108 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003109 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003110 // The super class for the metaclass is emitted as the name of the
3111 // super class. The runtime fixes this up to point to the
3112 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003113 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003114 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003115 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003116 ObjCTypes.ClassPtrTy);
3117 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00003118 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003119 }
3120 Values[ 2] = GetClassName(ID->getIdentifier());
3121 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003122 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3123 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3124 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003125 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003126 Values[ 7] =
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00003127 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003128 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003129 Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003130 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003131 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003132 Values[ 9] = Protocols;
3133 // ivar_layout for metaclass is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003134 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003135 // The class extension is always unused for metaclasses.
Owen Anderson0b75f232009-07-31 20:28:54 +00003136 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00003137 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003138 Values);
3139
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003140 std::string Name("\01L_OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00003141 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003142
3143 // Check for a forward reference.
3144 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
3145 if (GV) {
3146 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3147 "Forward metaclass reference has incorrect type.");
3148 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
3149 GV->setInitializer(Init);
3150 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00003151 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003152 llvm::GlobalValue::InternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00003153 Init, Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003154 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003155 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbarae333842009-03-09 22:18:41 +00003156 GV->setAlignment(4);
Chris Lattnerf56501c2009-07-17 23:57:13 +00003157 CGM.AddUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003158
3159 return GV;
3160}
3161
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003162llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00003163 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003164
Mike Stump18bb9282009-05-16 07:57:57 +00003165 // FIXME: Should we look these up somewhere other than the module. Its a bit
3166 // silly since we only generate these while processing an implementation, so
3167 // exactly one pointer would work if know when we entered/exitted an
3168 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003169
3170 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00003171 // Previously, metaclass with internal linkage may have been defined.
3172 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003173 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
3174 true)) {
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003175 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3176 "Forward metaclass reference has incorrect type.");
3177 return GV;
3178 } else {
3179 // Generate as an external reference to keep a consistent
3180 // module. This will be patched up when we emit the metaclass.
Owen Andersonc10c8d32009-07-08 19:05:04 +00003181 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003182 llvm::GlobalValue::ExternalLinkage,
3183 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00003184 Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003185 }
3186}
3187
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003188llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
3189 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
3190
3191 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
3192 true)) {
3193 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3194 "Forward class metadata reference has incorrect type.");
3195 return GV;
3196 } else {
3197 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
3198 llvm::GlobalValue::ExternalLinkage,
3199 0,
3200 Name);
3201 }
3202}
3203
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003204/*
3205 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003206 uint32_t size;
3207 const char *weak_ivar_layout;
3208 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003209 };
3210*/
3211llvm::Constant *
3212CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003213 uint64_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00003214 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003215
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003216 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003217 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian6df69862009-04-22 23:00:43 +00003218 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003219 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00003220 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003221
3222 // Return null if no extension bits are used.
3223 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00003224 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003225
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003226 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00003227 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003228 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003229 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003230 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003231}
3232
3233/*
3234 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003235 char *ivar_name;
3236 char *ivar_type;
3237 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003238 };
3239
3240 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003241 int ivar_count;
3242 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003243 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003244*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003245llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003246 bool ForClass) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003247 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003248
3249 // When emitting the root class GCC emits ivar entries for the
3250 // actual class structure. It is not clear if we need to follow this
3251 // behavior; for now lets try and get away with not doing it. If so,
3252 // the cleanest solution would be to make up an ObjCInterfaceDecl
3253 // for the class.
3254 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00003255 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003256
Jordy Rosea91768e2011-07-22 02:08:32 +00003257 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003258
Jordy Rosea91768e2011-07-22 02:08:32 +00003259 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00003260 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00003261 // Ignore unnamed bit-fields.
3262 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003263 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003264 llvm::Constant *Ivar[] = {
3265 GetMethodVarName(IVD->getIdentifier()),
3266 GetMethodVarType(IVD),
3267 llvm::ConstantInt::get(ObjCTypes.IntTy,
Eli Friedman8cbca202012-11-06 22:15:52 +00003268 ComputeIvarBaseOffset(CGM, OID, IVD))
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003269 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00003270 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003271 }
3272
3273 // Return null for empty list.
3274 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003275 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003276
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003277 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003278 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00003279 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003280 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00003281 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003282 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003283
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003284 llvm::GlobalVariable *GV;
3285 if (ForClass)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003286 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003287 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003288 4, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003289 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003290 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003291 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003292 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003293 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003294}
3295
3296/*
3297 struct objc_method {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003298 SEL method_name;
3299 char *method_types;
3300 void *method;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003301 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003302
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003303 struct objc_method_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003304 struct objc_method_list *obsolete;
3305 int count;
3306 struct objc_method methods_list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003307 };
3308*/
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003309
3310/// GetMethodConstant - Return a struct objc_method constant for the
3311/// given method if it has been defined. The result is null if the
3312/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003313llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00003314 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003315 if (!Fn)
3316 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003317
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003318 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00003319 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003320 ObjCTypes.SelectorPtrTy),
3321 GetMethodVarType(MD),
3322 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
3323 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00003324 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003325}
3326
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003327llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003328 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003329 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003330 // Return null for empty list.
3331 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003332 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003333
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003334 llvm::Constant *Values[3];
Owen Anderson0b75f232009-07-31 20:28:54 +00003335 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003336 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00003337 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003338 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00003339 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003340 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003341
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003342 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003343 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003344}
3345
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00003346llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003347 const ObjCContainerDecl *CD) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003348 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00003349 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003350
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00003351 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00003352 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00003353 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003354 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00003355 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003356 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00003357 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003358 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003359 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003360
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003361 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003362}
3363
Daniel Dunbar30c65362009-03-09 20:09:19 +00003364llvm::GlobalVariable *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003365CGObjCCommonMac::CreateMetadataVar(Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00003366 llvm::Constant *Init,
3367 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003368 unsigned Align,
3369 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003370 llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003371 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00003372 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerf56501c2009-07-17 23:57:13 +00003373 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003374 if (Section)
3375 GV->setSection(Section);
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003376 if (Align)
3377 GV->setAlignment(Align);
3378 if (AddToUsed)
Chris Lattnerf56501c2009-07-17 23:57:13 +00003379 CGM.AddUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003380 return GV;
3381}
3382
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003383llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003384 // Abuse this interface function as a place to finalize.
3385 FinishModule();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003386 return NULL;
3387}
3388
Chris Lattnerd4808922009-03-22 21:03:39 +00003389llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003390 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003391}
3392
Chris Lattnerd4808922009-03-22 21:03:39 +00003393llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003394 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003395}
3396
Ted Kremeneke65b0862012-03-06 20:05:56 +00003397llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3398 bool copy) {
3399 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3400}
3401
David Chisnall168b80f2010-12-26 22:13:16 +00003402llvm::Constant *CGObjCMac::GetGetStructFunction() {
3403 return ObjCTypes.getCopyStructFn();
3404}
3405llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00003406 return ObjCTypes.getCopyStructFn();
3407}
3408
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00003409llvm::Constant *CGObjCMac::GetCppAtomicObjectFunction() {
3410 return ObjCTypes.getCppAtomicObjectFunction();
3411}
3412
Chris Lattnerd4808922009-03-22 21:03:39 +00003413llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003414 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00003415}
3416
John McCallbd309292010-07-06 01:34:17 +00003417void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
3418 return EmitTryOrSynchronizedStmt(CGF, S);
3419}
3420
3421void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
3422 const ObjCAtSynchronizedStmt &S) {
3423 return EmitTryOrSynchronizedStmt(CGF, S);
3424}
3425
John McCall65bea082010-07-21 06:59:36 +00003426namespace {
John McCallcda666c2010-07-21 07:22:38 +00003427 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00003428 const Stmt &S;
John McCall2dd7d442010-08-04 05:59:32 +00003429 llvm::Value *SyncArgSlot;
John McCall65bea082010-07-21 06:59:36 +00003430 llvm::Value *CallTryExitVar;
3431 llvm::Value *ExceptionData;
3432 ObjCTypesHelper &ObjCTypes;
3433 PerformFragileFinally(const Stmt *S,
John McCall2dd7d442010-08-04 05:59:32 +00003434 llvm::Value *SyncArgSlot,
John McCall65bea082010-07-21 06:59:36 +00003435 llvm::Value *CallTryExitVar,
3436 llvm::Value *ExceptionData,
3437 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00003438 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00003439 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
3440
John McCall30317fd2011-07-12 20:27:29 +00003441 void Emit(CodeGenFunction &CGF, Flags flags) {
John McCall65bea082010-07-21 06:59:36 +00003442 // Check whether we need to call objc_exception_try_exit.
3443 // In optimized code, this branch will always be folded.
3444 llvm::BasicBlock *FinallyCallExit =
3445 CGF.createBasicBlock("finally.call_exit");
3446 llvm::BasicBlock *FinallyNoCallExit =
3447 CGF.createBasicBlock("finally.no_call_exit");
3448 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
3449 FinallyCallExit, FinallyNoCallExit);
3450
3451 CGF.EmitBlock(FinallyCallExit);
3452 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
3453 ->setDoesNotThrow();
3454
3455 CGF.EmitBlock(FinallyNoCallExit);
3456
3457 if (isa<ObjCAtTryStmt>(S)) {
3458 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00003459 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
3460 // Save the current cleanup destination in case there's
3461 // control flow inside the finally statement.
3462 llvm::Value *CurCleanupDest =
3463 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
3464
John McCall65bea082010-07-21 06:59:36 +00003465 CGF.EmitStmt(FinallyStmt->getFinallyBody());
3466
John McCallcebe0ca2010-08-11 00:16:14 +00003467 if (CGF.HaveInsertPoint()) {
3468 CGF.Builder.CreateStore(CurCleanupDest,
3469 CGF.getNormalCleanupDestSlot());
3470 } else {
3471 // Currently, the end of the cleanup must always exist.
3472 CGF.EnsureInsertPoint();
3473 }
3474 }
John McCall65bea082010-07-21 06:59:36 +00003475 } else {
3476 // Emit objc_sync_exit(expr); as finally's sole statement for
3477 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00003478 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall65bea082010-07-21 06:59:36 +00003479 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
3480 ->setDoesNotThrow();
3481 }
3482 }
3483 };
John McCall42227ed2010-07-31 23:20:56 +00003484
3485 class FragileHazards {
3486 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003487 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00003488 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
3489
3490 llvm::InlineAsm *ReadHazard;
3491 llvm::InlineAsm *WriteHazard;
3492
3493 llvm::FunctionType *GetAsmFnType();
3494
3495 void collectLocals();
3496 void emitReadHazard(CGBuilderTy &Builder);
3497
3498 public:
3499 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00003500
John McCall42227ed2010-07-31 23:20:56 +00003501 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00003502 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003503 };
3504}
3505
3506/// Create the fragile-ABI read and write hazards based on the current
3507/// state of the function, which is presumed to be immediately prior
3508/// to a @try block. These hazards are used to maintain correct
3509/// semantics in the face of optimization and the fragile ABI's
3510/// cavalier use of setjmp/longjmp.
3511FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
3512 collectLocals();
3513
3514 if (Locals.empty()) return;
3515
3516 // Collect all the blocks in the function.
3517 for (llvm::Function::iterator
3518 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
3519 BlocksBeforeTry.insert(&*I);
3520
3521 llvm::FunctionType *AsmFnTy = GetAsmFnType();
3522
3523 // Create a read hazard for the allocas. This inhibits dead-store
3524 // optimizations and forces the values to memory. This hazard is
3525 // inserted before any 'throwing' calls in the protected scope to
3526 // reflect the possibility that the variables might be read from the
3527 // catch block if the call throws.
3528 {
3529 std::string Constraint;
3530 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3531 if (I) Constraint += ',';
3532 Constraint += "*m";
3533 }
3534
3535 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3536 }
3537
3538 // Create a write hazard for the allocas. This inhibits folding
3539 // loads across the hazard. This hazard is inserted at the
3540 // beginning of the catch path to reflect the possibility that the
3541 // variables might have been written within the protected scope.
3542 {
3543 std::string Constraint;
3544 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3545 if (I) Constraint += ',';
3546 Constraint += "=*m";
3547 }
3548
3549 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3550 }
3551}
3552
3553/// Emit a write hazard at the current location.
3554void FragileHazards::emitWriteHazard() {
3555 if (Locals.empty()) return;
3556
Jay Foad5bd375a2011-07-15 08:37:34 +00003557 CGF.Builder.CreateCall(WriteHazard, Locals)->setDoesNotThrow();
John McCall42227ed2010-07-31 23:20:56 +00003558}
3559
John McCall42227ed2010-07-31 23:20:56 +00003560void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
3561 assert(!Locals.empty());
Jay Foad5bd375a2011-07-15 08:37:34 +00003562 Builder.CreateCall(ReadHazard, Locals)->setDoesNotThrow();
John McCall42227ed2010-07-31 23:20:56 +00003563}
3564
3565/// Emit read hazards in all the protected blocks, i.e. all the blocks
3566/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00003567void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00003568 if (Locals.empty()) return;
3569
3570 CGBuilderTy Builder(CGF.getLLVMContext());
3571
3572 // Iterate through all blocks, skipping those prior to the try.
3573 for (llvm::Function::iterator
3574 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
3575 llvm::BasicBlock &BB = *FI;
3576 if (BlocksBeforeTry.count(&BB)) continue;
3577
3578 // Walk through all the calls in the block.
3579 for (llvm::BasicBlock::iterator
3580 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
3581 llvm::Instruction &I = *BI;
3582
3583 // Ignore instructions that aren't non-intrinsic calls.
3584 // These are the only calls that can possibly call longjmp.
3585 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
3586 if (isa<llvm::IntrinsicInst>(I))
3587 continue;
3588
3589 // Ignore call sites marked nounwind. This may be questionable,
3590 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
3591 llvm::CallSite CS(&I);
3592 if (CS.doesNotThrow()) continue;
3593
John McCall2dd7d442010-08-04 05:59:32 +00003594 // Insert a read hazard before the call. This will ensure that
3595 // any writes to the locals are performed before making the
3596 // call. If the call throws, then this is sufficient to
3597 // guarantee correctness as long as it doesn't also write to any
3598 // locals.
John McCall42227ed2010-07-31 23:20:56 +00003599 Builder.SetInsertPoint(&BB, BI);
3600 emitReadHazard(Builder);
3601 }
3602 }
3603}
3604
3605static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
3606 if (V) S.insert(V);
3607}
3608
3609void FragileHazards::collectLocals() {
3610 // Compute a set of allocas to ignore.
3611 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
3612 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
3613 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00003614
3615 // Collect all the allocas currently in the function. This is
3616 // probably way too aggressive.
3617 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
3618 for (llvm::BasicBlock::iterator
3619 I = Entry.begin(), E = Entry.end(); I != E; ++I)
3620 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
3621 Locals.push_back(&*I);
3622}
3623
3624llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003625 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00003626 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
3627 tys[i] = Locals[i]->getType();
3628 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00003629}
3630
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003631/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003632
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003633 Objective-C setjmp-longjmp (sjlj) Exception Handling
3634 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003635
John McCallbd309292010-07-06 01:34:17 +00003636 A catch buffer is a setjmp buffer plus:
3637 - a pointer to the exception that was caught
3638 - a pointer to the previous exception data buffer
3639 - two pointers of reserved storage
3640 Therefore catch buffers form a stack, with a pointer to the top
3641 of the stack kept in thread-local storage.
3642
3643 objc_exception_try_enter pushes a catch buffer onto the EH stack.
3644 objc_exception_try_exit pops the given catch buffer, which is
3645 required to be the top of the EH stack.
3646 objc_exception_throw pops the top of the EH stack, writes the
3647 thrown exception into the appropriate field, and longjmps
3648 to the setjmp buffer. It crashes the process (with a printf
3649 and an abort()) if there are no catch buffers on the stack.
3650 objc_exception_extract just reads the exception pointer out of the
3651 catch buffer.
3652
3653 There's no reason an implementation couldn't use a light-weight
3654 setjmp here --- something like __builtin_setjmp, but API-compatible
3655 with the heavyweight setjmp. This will be more important if we ever
3656 want to implement correct ObjC/C++ exception interactions for the
3657 fragile ABI.
3658
3659 Note that for this use of setjmp/longjmp to be correct, we may need
3660 to mark some local variables volatile: if a non-volatile local
3661 variable is modified between the setjmp and the longjmp, it has
3662 indeterminate value. For the purposes of LLVM IR, it may be
3663 sufficient to make loads and stores within the @try (to variables
3664 declared outside the @try) volatile. This is necessary for
3665 optimized correctness, but is not currently being done; this is
3666 being tracked as rdar://problem/8160285
3667
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003668 The basic framework for a @try-catch-finally is as follows:
3669 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003670 objc_exception_data d;
3671 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00003672 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003673
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003674 objc_exception_try_enter(&d);
3675 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003676 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003677 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003678 // exception path
3679 id _caught = objc_exception_extract(&d);
3680
3681 // enter new try scope for handlers
3682 if (!setjmp(d.jmp_buf)) {
3683 ... match exception and execute catch blocks ...
3684
3685 // fell off end, rethrow.
3686 _rethrow = _caught;
3687 ... jump-through-finally to finally_rethrow ...
3688 } else {
3689 // exception in catch block
3690 _rethrow = objc_exception_extract(&d);
3691 _call_try_exit = false;
3692 ... jump-through-finally to finally_rethrow ...
3693 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003694 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003695 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003696
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003697 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00003698 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003699 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00003700
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003701 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003702 ... dispatch to finally destination ...
3703
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003704 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003705 objc_exception_throw(_rethrow);
3706
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003707 finally_end:
3708 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003709
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003710 This framework differs slightly from the one gcc uses, in that gcc
3711 uses _rethrow to determine if objc_exception_try_exit should be called
3712 and if the object should be rethrown. This breaks in the face of
3713 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003714
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003715 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003716
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003717 - If there are no catch blocks, then we avoid emitting the second
3718 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003719
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003720 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
3721 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003722
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003723 - FIXME: If there is no @finally block we can do a few more
3724 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003725
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003726 Rethrows and Jumps-Through-Finally
3727 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003728
John McCallbd309292010-07-06 01:34:17 +00003729 '@throw;' is supported by pushing the currently-caught exception
3730 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003731
John McCallbd309292010-07-06 01:34:17 +00003732 Branches through the @finally block are handled with an ordinary
3733 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
3734 exceptions are not compatible with C++ exceptions, and this is
3735 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003736
John McCallbd309292010-07-06 01:34:17 +00003737 @synchronized(expr) { stmt; } is emitted as if it were:
3738 id synch_value = expr;
3739 objc_sync_enter(synch_value);
3740 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003741*/
3742
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00003743void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
3744 const Stmt &S) {
3745 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00003746
3747 // A destination for the fall-through edges of the catch handlers to
3748 // jump to.
3749 CodeGenFunction::JumpDest FinallyEnd =
3750 CGF.getJumpDestInCurrentScope("finally.end");
3751
3752 // A destination for the rethrow edge of the catch handlers to jump
3753 // to.
3754 CodeGenFunction::JumpDest FinallyRethrow =
3755 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003756
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003757 // For @synchronized, call objc_sync_enter(sync.expr). The
3758 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00003759 // @synchronized. We can't avoid a temp here because we need the
3760 // value to be preserved. If the backend ever does liveness
3761 // correctly after setjmp, this will be unnecessary.
3762 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003763 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00003764 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003765 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
3766 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallbd309292010-07-06 01:34:17 +00003767 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
3768 ->setDoesNotThrow();
John McCall2dd7d442010-08-04 05:59:32 +00003769
3770 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
3771 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003772 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003773
John McCall2dd7d442010-08-04 05:59:32 +00003774 // Allocate memory for the setjmp buffer. This needs to be kept
3775 // live throughout the try and catch blocks.
3776 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
3777 "exceptiondata.ptr");
3778
John McCall42227ed2010-07-31 23:20:56 +00003779 // Create the fragile hazards. Note that this will not capture any
3780 // of the allocas required for exception processing, but will
3781 // capture the current basic block (which extends all the way to the
3782 // setjmp call) as "before the @try".
3783 FragileHazards Hazards(CGF);
3784
John McCallbd309292010-07-06 01:34:17 +00003785 // Create a flag indicating whether the cleanup needs to call
3786 // objc_exception_try_exit. This is true except when
3787 // - no catches match and we're branching through the cleanup
3788 // just to rethrow the exception, or
3789 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00003790 // The setjmp-safety rule here is that we should always store to this
3791 // variable in a place that dominates the branch through the cleanup
3792 // without passing through any setjmps.
John McCallbd309292010-07-06 01:34:17 +00003793 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlssonda0e4562009-02-07 21:26:04 +00003794 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003795
John McCall9916e3f2010-10-04 23:42:51 +00003796 // A slot containing the exception to rethrow. Only needed when we
3797 // have both a @catch and a @finally.
3798 llvm::Value *PropagatingExnVar = 0;
3799
John McCallbd309292010-07-06 01:34:17 +00003800 // Push a normal cleanup to leave the try scope.
John McCallcda666c2010-07-21 07:22:38 +00003801 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00003802 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00003803 CallTryExitVar,
3804 ExceptionData,
3805 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00003806
3807 // Enter a try block:
3808 // - Call objc_exception_try_enter to push ExceptionData on top of
3809 // the EH stack.
3810 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3811 ->setDoesNotThrow();
3812
3813 // - Call setjmp on the exception data buffer.
3814 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3815 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3816 llvm::Value *SetJmpBuffer =
Jay Foad040dd822011-07-22 08:16:57 +00003817 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
John McCallbd309292010-07-06 01:34:17 +00003818 llvm::CallInst *SetJmpResult =
3819 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3820 SetJmpResult->setDoesNotThrow();
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003821 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00003822
3823 // If setjmp returned 0, enter the protected block; otherwise,
3824 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00003825 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3826 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00003827 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00003828 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3829 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003830
John McCallbd309292010-07-06 01:34:17 +00003831 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003832 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00003833 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003834 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00003835 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00003836
3837 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003838
John McCallbd309292010-07-06 01:34:17 +00003839 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00003840 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003841
John McCall42227ed2010-07-31 23:20:56 +00003842 // Don't optimize loads of the in-scope locals across this point.
3843 Hazards.emitWriteHazard();
3844
John McCallbd309292010-07-06 01:34:17 +00003845 // For a @synchronized (or a @try with no catches), just branch
3846 // through the cleanup to the rethrow block.
3847 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3848 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00003849 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003850 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00003851
3852 // Otherwise, we have to match against the caught exceptions.
3853 } else {
John McCall2dd7d442010-08-04 05:59:32 +00003854 // Retrieve the exception object. We may emit multiple blocks but
3855 // nothing can cross this so the value is already in SSA form.
3856 llvm::CallInst *Caught =
3857 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3858 ExceptionData, "caught");
3859 Caught->setDoesNotThrow();
3860
John McCallbd309292010-07-06 01:34:17 +00003861 // Push the exception to rethrow onto the EH value stack for the
3862 // benefit of any @throws in the handlers.
3863 CGF.ObjCEHValueStack.push_back(Caught);
3864
Douglas Gregor96c79492010-04-23 22:50:49 +00003865 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003866
John McCall2dd7d442010-08-04 05:59:32 +00003867 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallbd309292010-07-06 01:34:17 +00003868
John McCall2dd7d442010-08-04 05:59:32 +00003869 llvm::BasicBlock *CatchBlock = 0;
3870 llvm::BasicBlock *CatchHandler = 0;
3871 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00003872 // Save the currently-propagating exception before
3873 // objc_exception_try_enter clears the exception slot.
3874 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3875 "propagating_exception");
3876 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3877
John McCall2dd7d442010-08-04 05:59:32 +00003878 // Enter a new exception try block (in case a @catch block
3879 // throws an exception).
3880 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3881 ->setDoesNotThrow();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003882
John McCall2dd7d442010-08-04 05:59:32 +00003883 llvm::CallInst *SetJmpResult =
3884 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3885 "setjmp.result");
3886 SetJmpResult->setDoesNotThrow();
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003887 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003888
John McCall2dd7d442010-08-04 05:59:32 +00003889 llvm::Value *Threw =
3890 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3891
3892 CatchBlock = CGF.createBasicBlock("catch");
3893 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3894 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3895
3896 CGF.EmitBlock(CatchBlock);
3897 }
3898
3899 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003900
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003901 // Handle catch list. As a special case we check if everything is
3902 // matched and avoid generating code for falling off the end if
3903 // so.
3904 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00003905 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3906 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003907
Douglas Gregor46a572b2010-04-26 16:46:50 +00003908 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff7cae42b2009-07-10 23:34:53 +00003909 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar523208f2008-09-27 07:36:24 +00003910
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003911 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003912 if (!CatchParam) {
3913 AllMatched = true;
3914 } else {
John McCall9dd450b2009-09-21 23:43:11 +00003915 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003916
John McCallbd309292010-07-06 01:34:17 +00003917 // catch(id e) always matches under this ABI, since only
3918 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00003919 // FIXME: For the time being we also match id<X>; this should
3920 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00003921 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003922 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003923 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003924
John McCallbd309292010-07-06 01:34:17 +00003925 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003926 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00003927 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3928
Anders Carlsson9396a892008-09-11 09:15:33 +00003929 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00003930 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003931 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00003932
3933 // These types work out because ConvertType(id) == i8*.
Steve Naroff371b8fb2009-03-03 19:52:17 +00003934 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson9396a892008-09-11 09:15:33 +00003935 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003936
Anders Carlsson9396a892008-09-11 09:15:33 +00003937 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003938
3939 // The scope of the catch variable ends right here.
3940 CatchVarCleanups.ForceCleanup();
3941
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003942 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003943 break;
3944 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003945
Steve Naroff7cae42b2009-07-10 23:34:53 +00003946 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00003947 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00003948
3949 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00003950 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3951 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003952
3953 // Check if the @catch block matches the exception object.
John McCall96fa4842010-05-17 21:00:27 +00003954 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003955
John McCallbd309292010-07-06 01:34:17 +00003956 llvm::CallInst *Match =
Chris Lattnerc6406db2009-04-22 02:26:14 +00003957 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3958 Class, Caught, "match");
John McCallbd309292010-07-06 01:34:17 +00003959 Match->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003960
John McCallbd309292010-07-06 01:34:17 +00003961 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3962 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003963
3964 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00003965 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003966
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003967 // Emit the @catch block.
3968 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00003969
3970 // Collect any cleanups for the catch variable. The scope lasts until
3971 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00003972 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00003973
John McCall1c9c3fd2010-10-15 04:57:14 +00003974 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003975 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003976
John McCallbd309292010-07-06 01:34:17 +00003977 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003978 llvm::Value *Tmp =
3979 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00003980 CGF.ConvertType(CatchParam->getType()));
Steve Naroff371b8fb2009-03-03 19:52:17 +00003981 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003982
Anders Carlsson9396a892008-09-11 09:15:33 +00003983 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003984
3985 // We're done with the catch variable.
3986 CatchVarCleanups.ForceCleanup();
3987
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003988 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003989
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003990 CGF.EmitBlock(NextCatchBlock);
3991 }
3992
John McCallbd309292010-07-06 01:34:17 +00003993 CGF.ObjCEHValueStack.pop_back();
3994
John McCall2dd7d442010-08-04 05:59:32 +00003995 // If nothing wanted anything to do with the caught exception,
3996 // kill the extract call.
3997 if (Caught->use_empty())
3998 Caught->eraseFromParent();
3999
4000 if (!AllMatched)
4001 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4002
4003 if (HasFinally) {
4004 // Emit the exception handler for the @catch blocks.
4005 CGF.EmitBlock(CatchHandler);
4006
4007 // In theory we might now need a write hazard, but actually it's
4008 // unnecessary because there's no local-accessing code between
4009 // the try's write hazard and here.
4010 //Hazards.emitWriteHazard();
4011
John McCall9916e3f2010-10-04 23:42:51 +00004012 // Extract the new exception and save it to the
4013 // propagating-exception slot.
4014 assert(PropagatingExnVar);
4015 llvm::CallInst *NewCaught =
4016 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
4017 ExceptionData, "caught");
4018 NewCaught->setDoesNotThrow();
4019 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4020
John McCall2dd7d442010-08-04 05:59:32 +00004021 // Don't pop the catch handler; the throw already did.
4022 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004023 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004024 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004025 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004026
John McCall42227ed2010-07-31 23:20:56 +00004027 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00004028 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004029
John McCallbd309292010-07-06 01:34:17 +00004030 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00004031 CGF.Builder.restoreIP(TryFallthroughIP);
4032 if (CGF.HaveInsertPoint())
4033 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00004034 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00004035 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004036
John McCallbd309292010-07-06 01:34:17 +00004037 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00004038 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00004039 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00004040 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00004041 // If we have a propagating-exception variable, check it.
4042 llvm::Value *PropagatingExn;
4043 if (PropagatingExnVar) {
4044 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00004045
John McCall9916e3f2010-10-04 23:42:51 +00004046 // Otherwise, just look in the buffer for the exception to throw.
4047 } else {
4048 llvm::CallInst *Caught =
4049 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
4050 ExceptionData);
4051 Caught->setDoesNotThrow();
4052 PropagatingExn = Caught;
4053 }
4054
4055 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallbd309292010-07-06 01:34:17 +00004056 ->setDoesNotThrow();
4057 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00004058 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004059
John McCall42227ed2010-07-31 23:20:56 +00004060 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004061}
4062
4063void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004064 const ObjCAtThrowStmt &S) {
Anders Carlssone005aa12008-09-09 16:16:55 +00004065 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004066
Anders Carlssone005aa12008-09-09 16:16:55 +00004067 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00004068 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004069 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004070 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00004071 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004072 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004073 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00004074 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00004075 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004076
John McCallbd309292010-07-06 01:34:17 +00004077 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4078 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004079 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004080
4081 // Clear the insertion point to indicate we are in unreachable code.
4082 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004083}
4084
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004085/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004086/// object: objc_read_weak (id *src)
4087///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004088llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004089 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004090 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004091 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
4092 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4093 ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00004094 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004095 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00004096 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004097 return read_weak;
4098}
4099
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004100/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4101/// objc_assign_weak (id src, id *dst)
4102///
4103void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004104 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004105 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004106 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004107 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004108 assert(Size <= 8 && "does not support size > 8");
4109 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004110 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004111 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4112 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004113 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4114 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00004115 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004116 src, dst, "weakassign");
4117 return;
4118}
4119
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004120/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4121/// objc_assign_global (id src, id *dst)
4122///
4123void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00004124 llvm::Value *src, llvm::Value *dst,
4125 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004126 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004127 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004128 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004129 assert(Size <= 8 && "does not support size > 8");
4130 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004131 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004132 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4133 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004134 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4135 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00004136 if (!threadlocal)
4137 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
4138 src, dst, "globalassign");
4139 else
4140 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
4141 src, dst, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004142 return;
4143}
4144
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004145/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004146/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004147///
4148void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004149 llvm::Value *src, llvm::Value *dst,
4150 llvm::Value *ivarOffset) {
4151 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00004152 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004153 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004154 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004155 assert(Size <= 8 && "does not support size > 8");
4156 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004157 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004158 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4159 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004160 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4161 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004162 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
4163 src, dst, ivarOffset);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004164 return;
4165}
4166
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004167/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4168/// objc_assign_strongCast (id src, id *dst)
4169///
4170void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004171 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004172 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004173 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004174 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004175 assert(Size <= 8 && "does not support size > 8");
4176 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004177 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004178 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4179 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004180 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4181 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00004182 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004183 src, dst, "weakassign");
4184 return;
4185}
4186
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004187void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004188 llvm::Value *DestPtr,
4189 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004190 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004191 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4192 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004193 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004194 DestPtr, SrcPtr, size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004195 return;
4196}
4197
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004198/// EmitObjCValueForIvar - Code Gen for ivar reference.
4199///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004200LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4201 QualType ObjectTy,
4202 llvm::Value *BaseValue,
4203 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004204 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00004205 const ObjCInterfaceDecl *ID =
4206 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00004207 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4208 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004209}
4210
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004211llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00004212 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004213 const ObjCIvarDecl *Ivar) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004214 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4215 return llvm::ConstantInt::get(
4216 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
4217 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004218}
4219
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004220/* *** Private Interface *** */
4221
4222/// EmitImageInfo - Emit the image info marker used to encode some module
4223/// level information.
4224///
4225/// See: <rdr://4810609&4810587&4810587>
4226/// struct IMAGE_INFO {
4227/// unsigned version;
4228/// unsigned flags;
4229/// };
4230enum ImageInfoFlags {
Daniel Dunbar5e639272010-04-25 20:39:01 +00004231 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004232 eImageInfo_GarbageCollected = (1 << 1),
4233 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbar75e909f2009-04-20 07:11:47 +00004234 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
4235
Daniel Dunbar5e639272010-04-25 20:39:01 +00004236 // A flag indicating that the module has no instances of a @synthesize of a
4237 // superclass variable. <rdar://problem/6803242>
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004238 eImageInfo_CorrectedSynthesize = (1 << 4),
4239 eImageInfo_ImageIsSimulated = (1 << 5)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004240};
4241
Daniel Dunbar5e639272010-04-25 20:39:01 +00004242void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004243 unsigned version = 0; // Version is unused?
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004244 const char *Section = (ObjCABI == 1) ?
4245 "__OBJC, __image_info,regular" :
4246 "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004247
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004248 // Generate module-level named metadata to convey this information to the
4249 // linker and code-gen.
4250 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004251
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004252 // Add the ObjC ABI version to the module flags.
4253 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
4254 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
4255 version);
4256 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
4257 llvm::MDString::get(VMContext,Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004258
David Blaikiebbafb8a2012-03-11 07:00:24 +00004259 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004260 // Non-GC overrides those files which specify GC.
4261 Mod.addModuleFlag(llvm::Module::Override,
4262 "Objective-C Garbage Collection", (uint32_t)0);
4263 } else {
4264 // Add the ObjC garbage collection value.
4265 Mod.addModuleFlag(llvm::Module::Error,
4266 "Objective-C Garbage Collection",
4267 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004268
David Blaikiebbafb8a2012-03-11 07:00:24 +00004269 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004270 // Add the ObjC GC Only value.
4271 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
4272 eImageInfo_GCOnly);
4273
4274 // Require that GC be specified and set to eImageInfo_GarbageCollected.
4275 llvm::Value *Ops[2] = {
4276 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
4277 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
4278 eImageInfo_GarbageCollected)
4279 };
4280 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
4281 llvm::MDNode::get(VMContext, Ops));
4282 }
4283 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004284
4285 // Indicate whether we're compiling this to run on a simulator.
4286 const llvm::Triple &Triple = CGM.getTarget().getTriple();
4287 if (Triple.getOS() == llvm::Triple::IOS &&
4288 (Triple.getArch() == llvm::Triple::x86 ||
4289 Triple.getArch() == llvm::Triple::x86_64))
4290 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
4291 eImageInfo_ImageIsSimulated);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004292}
4293
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004294// struct objc_module {
4295// unsigned long version;
4296// unsigned long size;
4297// const char *name;
4298// Symtab symtab;
4299// };
4300
4301// FIXME: Get from somewhere
4302static const int ModuleVersion = 7;
4303
4304void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004305 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004306
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004307 llvm::Constant *Values[] = {
4308 llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion),
4309 llvm::ConstantInt::get(ObjCTypes.LongTy, Size),
4310 // This used to be the filename, now it is unused. <rdr://4327263>
4311 GetClassName(&CGM.getContext().Idents.get("")),
4312 EmitModuleSymbols()
4313 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004314 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson0e0189d2009-07-27 22:29:56 +00004315 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004316 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00004317 4, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004318}
4319
4320llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004321 unsigned NumClasses = DefinedClasses.size();
4322 unsigned NumCategories = DefinedCategories.size();
4323
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004324 // Return null if no symbols were defined.
4325 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00004326 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004327
Chris Lattnere64d7ba2011-06-20 04:01:35 +00004328 llvm::Constant *Values[5];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004329 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Anderson0b75f232009-07-31 20:28:54 +00004330 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004331 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
4332 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004333
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004334 // The runtime expects exactly the list of defined classes followed
4335 // by the list of defined categories, in a single array.
Chris Lattner3def9ae2012-02-06 22:16:34 +00004336 SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004337 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00004338 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004339 ObjCTypes.Int8PtrTy);
4340 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004341 Symbols[NumClasses + i] =
Owen Andersonade90fd2009-07-29 18:54:39 +00004342 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004343 ObjCTypes.Int8PtrTy);
4344
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004345 Values[4] =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004346 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00004347 Symbols.size()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004348 Symbols);
4349
Chris Lattnere64d7ba2011-06-20 04:01:35 +00004350 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004351
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004352 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004353 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
4354 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00004355 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00004356 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004357}
4358
John McCall31168b02011-06-15 23:02:42 +00004359llvm::Value *CGObjCMac::EmitClassRefFromId(CGBuilderTy &Builder,
4360 IdentifierInfo *II) {
4361 LazySymbols.insert(II);
4362
4363 llvm::GlobalVariable *&Entry = ClassReferences[II];
4364
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004365 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004366 llvm::Constant *Casted =
John McCall31168b02011-06-15 23:02:42 +00004367 llvm::ConstantExpr::getBitCast(GetClassName(II),
4368 ObjCTypes.ClassPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004369 Entry =
John McCall31168b02011-06-15 23:02:42 +00004370 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
4371 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
4372 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004373 }
John McCall31168b02011-06-15 23:02:42 +00004374
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004375 return Builder.CreateLoad(Entry);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004376}
4377
John McCall31168b02011-06-15 23:02:42 +00004378llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
4379 const ObjCInterfaceDecl *ID) {
4380 return EmitClassRefFromId(Builder, ID->getIdentifier());
4381}
4382
4383llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder) {
4384 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
4385 return EmitClassRefFromId(Builder, II);
4386}
4387
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00004388llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
4389 bool lvalue) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004390 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004391
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004392 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004393 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00004394 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004395 ObjCTypes.SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004396 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004397 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
4398 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00004399 4, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004400 }
4401
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00004402 if (lvalue)
4403 return Entry;
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004404 return Builder.CreateLoad(Entry);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004405}
4406
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004407llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00004408 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004409
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004410 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004411 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004412 llvm::ConstantDataArray::getString(VMContext,
4413 Ident->getNameStart()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004414 ((ObjCABI == 2) ?
4415 "__TEXT,__objc_classname,cstring_literals" :
4416 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004417 1, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004418
Owen Anderson170229f2009-07-14 23:10:40 +00004419 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004420}
4421
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004422llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
4423 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
4424 I = MethodDefinitions.find(MD);
4425 if (I != MethodDefinitions.end())
4426 return I->second;
4427
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004428 return NULL;
4429}
4430
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004431/// GetIvarLayoutName - Returns a unique constant for the given
4432/// ivar layout bitmap.
4433llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004434 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00004435 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004436}
4437
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004438void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Eli Friedman8cbca202012-11-06 22:15:52 +00004439 unsigned int BytePos,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004440 bool ForStrongLayout,
4441 bool &HasUnion) {
4442 const RecordDecl *RD = RT->getDecl();
4443 // FIXME - Use iterator.
David Blaikie2d7c57e2012-04-30 02:36:29 +00004444 SmallVector<const FieldDecl*, 16> Fields;
4445 for (RecordDecl::field_iterator i = RD->field_begin(),
4446 e = RD->field_end(); i != e; ++i)
David Blaikie40ed2972012-06-06 20:45:41 +00004447 Fields.push_back(*i);
Chris Lattner2192fe52011-07-18 04:24:23 +00004448 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004449 const llvm::StructLayout *RecLayout =
Micah Villmowdd31ca12012-10-08 16:25:52 +00004450 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004451
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004452 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
4453 ForStrongLayout, HasUnion);
4454}
4455
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +00004456void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004457 const llvm::StructLayout *Layout,
4458 const RecordDecl *RD,
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00004459 ArrayRef<const FieldDecl*> RecFields,
Eli Friedman8cbca202012-11-06 22:15:52 +00004460 unsigned int BytePos, bool ForStrongLayout,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004461 bool &HasUnion) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004462 bool IsUnion = (RD && RD->isUnion());
Eli Friedman8cbca202012-11-06 22:15:52 +00004463 uint64_t MaxUnionIvarSize = 0;
4464 uint64_t MaxSkippedUnionIvarSize = 0;
Jordy Rosea91768e2011-07-22 02:08:32 +00004465 const FieldDecl *MaxField = 0;
4466 const FieldDecl *MaxSkippedField = 0;
4467 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Eli Friedman8cbca202012-11-06 22:15:52 +00004468 uint64_t MaxFieldOffset = 0;
4469 uint64_t MaxSkippedFieldOffset = 0;
4470 uint64_t LastBitfieldOrUnnamedOffset = 0;
4471 uint64_t FirstFieldDelta = 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004472
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004473 if (RecFields.empty())
4474 return;
Eli Friedman8cbca202012-11-06 22:15:52 +00004475 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
Douglas Gregore8bbc122011-09-02 00:18:52 +00004476 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
David Blaikiebbafb8a2012-03-11 07:00:24 +00004477 if (!RD && CGM.getLangOpts().ObjCAutoRefCount) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004478 const FieldDecl *FirstField = RecFields[0];
4479 FirstFieldDelta =
4480 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
John McCall31168b02011-06-15 23:02:42 +00004481 }
4482
Chris Lattner5b36ddb2009-03-31 08:48:01 +00004483 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004484 const FieldDecl *Field = RecFields[i];
Eli Friedman8cbca202012-11-06 22:15:52 +00004485 uint64_t FieldOffset;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00004486 if (RD) {
Daniel Dunbard51c1a62010-04-14 17:02:21 +00004487 // Note that 'i' here is actually the field index inside RD of Field,
4488 // although this dependency is hidden.
4489 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Eli Friedman8cbca202012-11-06 22:15:52 +00004490 FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00004491 } else
John McCall31168b02011-06-15 23:02:42 +00004492 FieldOffset =
4493 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004494
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004495 // Skip over unnamed or bitfields
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004496 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004497 LastFieldBitfieldOrUnnamed = Field;
4498 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004499 continue;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004500 }
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004501
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004502 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004503 QualType FQT = Field->getType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004504 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004505 if (FQT->isUnionType())
4506 HasUnion = true;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004507
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004508 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004509 BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004510 ForStrongLayout, HasUnion);
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004511 continue;
4512 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004513
Chris Lattner5b36ddb2009-03-31 08:48:01 +00004514 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004515 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004516 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004517 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004518 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004519 FQT = CArray->getElementType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004520 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
4521 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004522 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004523 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004524 FQT = CArray->getElementType();
4525 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004526
4527 assert(!FQT->isUnionType() &&
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004528 "layout for array of unions not supported");
Fariborz Jahanian9a7d57d2011-01-03 19:23:18 +00004529 if (FQT->isRecordType() && ElCount) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004530 int OldIndex = IvarsInfo.size() - 1;
4531 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004532
Ted Kremenekc23c7e62009-07-29 21:53:49 +00004533 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004534 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004535 ForStrongLayout, HasUnion);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004536
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004537 // Replicate layout information for each array element. Note that
4538 // one element is already done.
4539 uint64_t ElIx = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004540 for (int FirstIndex = IvarsInfo.size() - 1,
4541 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004542 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004543 for (int i = OldIndex+1; i <= FirstIndex; ++i)
4544 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
4545 IvarsInfo[i].ivar_size));
4546 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
4547 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
4548 SkipIvars[i].ivar_size));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004549 }
4550 continue;
4551 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004552 }
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004553 // At this point, we are done with Record/Union and array there of.
4554 // For other arrays we are down to its element type.
John McCall8ccfcb52009-09-24 19:53:00 +00004555 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004556
Eli Friedman8cbca202012-11-06 22:15:52 +00004557 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall8ccfcb52009-09-24 19:53:00 +00004558 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
4559 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00004560 if (IsUnion) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004561 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00004562 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004563 MaxUnionIvarSize = UnionIvarSize;
4564 MaxField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004565 MaxFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004566 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00004567 } else {
Eli Friedman8cbca202012-11-06 22:15:52 +00004568 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
4569 FieldSize / WordSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004570 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004571 } else if ((ForStrongLayout &&
John McCall8ccfcb52009-09-24 19:53:00 +00004572 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
4573 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00004574 if (IsUnion) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004575 // FIXME: Why the asymmetry? We divide by word size in bits on other
4576 // side.
4577 uint64_t UnionIvarSize = FieldSize / ByteSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00004578 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004579 MaxSkippedUnionIvarSize = UnionIvarSize;
4580 MaxSkippedField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004581 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004582 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00004583 } else {
Eli Friedman8cbca202012-11-06 22:15:52 +00004584 // FIXME: Why the asymmetry, we divide by byte size in bits here?
4585 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
4586 FieldSize / ByteSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004587 }
4588 }
4589 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004590
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004591 if (LastFieldBitfieldOrUnnamed) {
4592 if (LastFieldBitfieldOrUnnamed->isBitField()) {
4593 // Last field was a bitfield. Must update skip info.
Richard Smithcaf33902011-10-10 18:28:20 +00004594 uint64_t BitFieldSize
4595 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004596 GC_IVAR skivar;
4597 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
Eli Friedman8cbca202012-11-06 22:15:52 +00004598 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
4599 + ((BitFieldSize % ByteSizeInBits) != 0);
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004600 SkipIvars.push_back(skivar);
4601 } else {
4602 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
4603 // Last field was unnamed. Must update skip info.
Eli Friedman8cbca202012-11-06 22:15:52 +00004604 unsigned FieldSize
4605 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004606 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
Eli Friedman8cbca202012-11-06 22:15:52 +00004607 FieldSize / ByteSizeInBits));
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004608 }
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004609 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004610
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004611 if (MaxField)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004612 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004613 MaxUnionIvarSize));
4614 if (MaxSkippedField)
Daniel Dunbar5b743912009-05-03 23:31:46 +00004615 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004616 MaxSkippedUnionIvarSize));
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004617}
4618
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004619/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
4620/// the computations and returning the layout bitmap (for ivar or blocks) in
4621/// the given argument BitMap string container. Routine reads
4622/// two containers, IvarsInfo and SkipIvars which are assumed to be
4623/// filled already by the caller.
Chris Lattner9c818332012-02-05 02:30:40 +00004624llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004625 unsigned int WordsToScan, WordsToSkip;
Chris Lattnerece04092012-02-07 00:39:47 +00004626 llvm::Type *PtrTy = CGM.Int8PtrTy;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004627
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004628 // Build the string of skip/scan nibbles
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004629 SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Eli Friedman8cbca202012-11-06 22:15:52 +00004630 unsigned int WordSize =
4631 CGM.getTypes().getDataLayout().getTypeAllocSize(PtrTy);
4632 if (IvarsInfo[0].ivar_bytepos == 0) {
4633 WordsToSkip = 0;
4634 WordsToScan = IvarsInfo[0].ivar_size;
4635 } else {
4636 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
4637 WordsToScan = IvarsInfo[0].ivar_size;
4638 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004639 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004640 unsigned int TailPrevGCObjC =
4641 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004642 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004643 // consecutive 'scanned' object pointers.
Eli Friedman8cbca202012-11-06 22:15:52 +00004644 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004645 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004646 // Skip over 'gc'able object pointer which lay over each other.
4647 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
4648 continue;
4649 // Must skip over 1 or more words. We save current skip/scan values
4650 // and start a new pair.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004651 SKIP_SCAN SkScan;
4652 SkScan.skip = WordsToSkip;
4653 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004654 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004655
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004656 // Skip the hole.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004657 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
4658 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004659 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004660 WordsToSkip = 0;
Eli Friedman8cbca202012-11-06 22:15:52 +00004661 WordsToScan = IvarsInfo[i].ivar_size;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004662 }
4663 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004664 if (WordsToScan > 0) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004665 SKIP_SCAN SkScan;
4666 SkScan.skip = WordsToSkip;
4667 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004668 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004669 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004670
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004671 if (!SkipIvars.empty()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004672 unsigned int LastIndex = SkipIvars.size()-1;
Eli Friedman8cbca202012-11-06 22:15:52 +00004673 int LastByteSkipped =
4674 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004675 LastIndex = IvarsInfo.size()-1;
Eli Friedman8cbca202012-11-06 22:15:52 +00004676 int LastByteScanned =
4677 IvarsInfo[LastIndex].ivar_bytepos +
4678 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004679 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramerd20ef752009-12-25 15:43:36 +00004680 if (LastByteSkipped > LastByteScanned) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004681 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004682 SKIP_SCAN SkScan;
Eli Friedman8cbca202012-11-06 22:15:52 +00004683 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004684 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004685 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004686 }
4687 }
4688 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
4689 // as 0xMN.
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004690 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004691 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004692 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
4693 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
4694 // 0xM0 followed by 0x0N detected.
4695 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
4696 for (int j = i+1; j < SkipScan; j++)
4697 SkipScanIvars[j] = SkipScanIvars[j+1];
4698 --SkipScan;
4699 }
4700 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004701
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004702 // Generate the string.
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004703 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004704 unsigned char byte;
4705 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
4706 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
4707 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
4708 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004709
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004710 // first skip big.
4711 for (unsigned int ix = 0; ix < skip_big; ix++)
4712 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004713
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004714 // next (skip small, scan)
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004715 if (skip_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004716 byte = skip_small << 4;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004717 if (scan_big > 0) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004718 byte |= 0xf;
4719 --scan_big;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004720 } else if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004721 byte |= scan_small;
4722 scan_small = 0;
4723 }
4724 BitMap += byte;
4725 }
4726 // next scan big
4727 for (unsigned int ix = 0; ix < scan_big; ix++)
4728 BitMap += (unsigned char)(0x0f);
4729 // last scan small
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004730 if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004731 byte = scan_small;
4732 BitMap += byte;
4733 }
4734 }
4735 // null terminate string.
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004736 unsigned char zero = 0;
4737 BitMap += zero;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004738
4739 llvm::GlobalVariable * Entry =
4740 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004741 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004742 ((ObjCABI == 2) ?
4743 "__TEXT,__objc_classname,cstring_literals" :
4744 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004745 1, true);
4746 return getConstantGEP(VMContext, Entry, 0, 0);
4747}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004748
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004749/// BuildIvarLayout - Builds ivar layout bitmap for the class
4750/// implementation for the __strong or __weak case.
4751/// The layout map displays which words in ivar list must be skipped
4752/// and which must be scanned by GC (see below). String is built of bytes.
4753/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
4754/// of words to skip and right nibble is count of words to scan. So, each
4755/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
4756/// represented by a 0x00 byte which also ends the string.
4757/// 1. when ForStrongLayout is true, following ivars are scanned:
4758/// - id, Class
4759/// - object *
4760/// - __strong anything
4761///
4762/// 2. When ForStrongLayout is false, following ivars are scanned:
4763/// - __weak anything
4764///
4765llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
4766 const ObjCImplementationDecl *OMD,
4767 bool ForStrongLayout) {
4768 bool hasUnion = false;
4769
Chris Lattnerece04092012-02-07 00:39:47 +00004770 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00004771 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
4772 !CGM.getLangOpts().ObjCAutoRefCount)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004773 return llvm::Constant::getNullValue(PtrTy);
4774
Jordy Rosea91768e2011-07-22 02:08:32 +00004775 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
4776 SmallVector<const FieldDecl*, 32> RecFields;
David Blaikiebbafb8a2012-03-11 07:00:24 +00004777 if (CGM.getLangOpts().ObjCAutoRefCount) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004778 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004779 IVD; IVD = IVD->getNextIvar())
4780 RecFields.push_back(cast<FieldDecl>(IVD));
4781 }
4782 else {
Jordy Rosea91768e2011-07-22 02:08:32 +00004783 SmallVector<const ObjCIvarDecl*, 32> Ivars;
John McCall31168b02011-06-15 23:02:42 +00004784 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004785
Jordy Rosea91768e2011-07-22 02:08:32 +00004786 // FIXME: This is not ideal; we shouldn't have to do this copy.
4787 RecFields.append(Ivars.begin(), Ivars.end());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004788 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004789
4790 if (RecFields.empty())
4791 return llvm::Constant::getNullValue(PtrTy);
4792
4793 SkipIvars.clear();
4794 IvarsInfo.clear();
4795
Eli Friedman8cbca202012-11-06 22:15:52 +00004796 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004797 if (IvarsInfo.empty())
4798 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004799 // Sort on byte position in case we encounterred a union nested in
4800 // the ivar list.
4801 if (hasUnion && !IvarsInfo.empty())
4802 std::sort(IvarsInfo.begin(), IvarsInfo.end());
4803 if (hasUnion && !SkipIvars.empty())
4804 std::sort(SkipIvars.begin(), SkipIvars.end());
4805
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004806 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004807 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004808
David Blaikiebbafb8a2012-03-11 07:00:24 +00004809 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004810 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004811 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar56df9772010-08-17 22:39:59 +00004812 OMD->getClassInterface()->getName().data());
Roman Divackye6377112012-09-06 15:59:27 +00004813 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00004814 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004815 if (!(s[i] & 0xf0))
4816 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
4817 else
4818 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
4819 printf("\n");
4820 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004821 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004822}
4823
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004824llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004825 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
4826
Chris Lattner3def9ae2012-02-06 22:16:34 +00004827 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004828 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004829 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004830 llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004831 ((ObjCABI == 2) ?
4832 "__TEXT,__objc_methname,cstring_literals" :
4833 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004834 1, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004835
Owen Anderson170229f2009-07-14 23:10:40 +00004836 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004837}
4838
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004839// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004840llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004841 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4842}
4843
Daniel Dunbarf5c18462009-04-20 06:54:31 +00004844llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004845 std::string TypeStr;
4846 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
4847
4848 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarb036db82008-08-13 03:21:16 +00004849
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004850 if (!Entry)
4851 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004852 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004853 ((ObjCABI == 2) ?
4854 "__TEXT,__objc_methtype,cstring_literals" :
4855 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004856 1, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004857
Owen Anderson170229f2009-07-14 23:10:40 +00004858 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004859}
4860
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004861llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
4862 bool Extended) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004863 std::string TypeStr;
Bill Wendlinge22bef72012-02-09 22:45:21 +00004864 if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
Douglas Gregora9d84932011-05-27 01:19:52 +00004865 return 0;
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004866
4867 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4868
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004869 if (!Entry)
4870 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004871 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004872 ((ObjCABI == 2) ?
4873 "__TEXT,__objc_methtype,cstring_literals" :
4874 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004875 1, true);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004876
Owen Anderson170229f2009-07-14 23:10:40 +00004877 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004878}
4879
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004880// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004881llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004882 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004883
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004884 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004885 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Chris Lattner9c818332012-02-05 02:30:40 +00004886 llvm::ConstantDataArray::getString(VMContext,
4887 Ident->getNameStart()),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004888 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004889 1, true);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004890
Owen Anderson170229f2009-07-14 23:10:40 +00004891 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004892}
4893
4894// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00004895// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004896llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004897CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4898 const Decl *Container) {
Daniel Dunbar4932b362008-08-28 04:38:10 +00004899 std::string TypeStr;
4900 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004901 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4902}
4903
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004904void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004905 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004906 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00004907 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00004908 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00004909 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4910 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004911 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00004912 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00004913 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00004914 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004915}
4916
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004917void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004918 EmitModuleInfo();
4919
Daniel Dunbarc475d422008-10-29 22:36:39 +00004920 // Emit the dummy bodies for any protocols which were referenced but
4921 // never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004922 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerf56501c2009-07-17 23:57:13 +00004923 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4924 if (I->second->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00004925 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004926
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004927 llvm::Constant *Values[5];
Owen Anderson0b75f232009-07-31 20:28:54 +00004928 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004929 Values[1] = GetClassName(I->first);
Owen Anderson0b75f232009-07-31 20:28:54 +00004930 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004931 Values[3] = Values[4] =
Owen Anderson0b75f232009-07-31 20:28:54 +00004932 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004933 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004934 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarc475d422008-10-29 22:36:39 +00004935 Values));
Chris Lattnerf56501c2009-07-17 23:57:13 +00004936 CGM.AddUsedGlobal(I->second);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004937 }
4938
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004939 // Add assembler directives to add lazy undefined symbol references
4940 // for classes which are referenced but not defined. This is
4941 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00004942 //
4943 // FIXME: It would be nice if we had an LLVM construct for this.
4944 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00004945 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00004946 Asm += CGM.getModule().getModuleInlineAsm();
4947 if (!Asm.empty() && Asm.back() != '\n')
4948 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004949
Daniel Dunbard027a922009-09-07 00:20:42 +00004950 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbard027a922009-09-07 00:20:42 +00004951 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4952 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar07d07852009-10-18 21:17:35 +00004953 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4954 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnera299f2c2010-04-17 18:26:20 +00004955 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004956 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnera299f2c2010-04-17 18:26:20 +00004957 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004958 }
4959
Bill Wendling53136852012-02-07 09:06:01 +00004960 for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) {
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004961 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4962 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4963 }
Chris Lattnera299f2c2010-04-17 18:26:20 +00004964
Daniel Dunbard027a922009-09-07 00:20:42 +00004965 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004966 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004967}
4968
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004969CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004970 : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00004971 ObjCTypes(cgm) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004972 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004973 ObjCABI = 2;
4974}
4975
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004976/* *** */
4977
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004978ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00004979 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(0)
4980{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004981 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4982 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004983
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004984 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004985 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004986 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004987 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Chris Lattnerece04092012-02-07 00:39:47 +00004988 Int8PtrTy = CGM.Int8PtrTy;
4989 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004990
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004991 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004992 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004993 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004994
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004995 // I'm not sure I like this. The implicit coordination is a bit
4996 // gross. We should solve this in a reasonable fashion because this
4997 // is a pretty common task (match some runtime data structure with
4998 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004999
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005000 // FIXME: This is leaked.
5001 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005002
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005003 // struct _objc_super {
5004 // id self;
5005 // Class cls;
5006 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00005007 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005008 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005009 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005010 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005011 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005012 Ctx.getObjCIdType(), 0, 0, false, ICIS_NoInit));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005013 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005014 Ctx.getObjCClassType(), 0, 0, false,
5015 ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005016 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005017
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005018 SuperCTy = Ctx.getTagDeclType(RD);
5019 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005020
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005021 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005022 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5023
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005024 // struct _prop_t {
5025 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005026 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005027 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005028 PropertyTy = llvm::StructType::create("struct._prop_t",
5029 Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005030
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005031 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005032 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005033 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005034 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005035 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005036 PropertyListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005037 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
5038 llvm::ArrayType::get(PropertyTy, 0), NULL);
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005039 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005040 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005041
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005042 // struct _objc_method {
5043 // SEL _cmd;
5044 // char *method_type;
5045 // char *_imp;
5046 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005047 MethodTy = llvm::StructType::create("struct._objc_method",
5048 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
5049 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005050
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005051 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00005052 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005053 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005054
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005055}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005056
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005057ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005058 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005059 // struct _objc_method_description {
5060 // SEL name;
5061 // char *types;
5062 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005063 MethodDescriptionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005064 llvm::StructType::create("struct._objc_method_description",
5065 SelectorPtrTy, Int8PtrTy, NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005066
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005067 // struct _objc_method_description_list {
5068 // int count;
5069 // struct _objc_method_description[1];
5070 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005071 MethodDescriptionListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005072 llvm::StructType::create("struct._objc_method_description_list",
5073 IntTy,
5074 llvm::ArrayType::get(MethodDescriptionTy, 0),NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005075
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005076 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005077 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005078 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005079
Daniel Dunbarb036db82008-08-13 03:21:16 +00005080 // Protocol description structures
5081
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005082 // struct _objc_protocol_extension {
5083 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5084 // struct _objc_method_description_list *optional_instance_methods;
5085 // struct _objc_method_description_list *optional_class_methods;
5086 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005087 // const char ** extendedMethodTypes;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005088 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005089 ProtocolExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005090 llvm::StructType::create("struct._objc_protocol_extension",
5091 IntTy, MethodDescriptionListPtrTy,
5092 MethodDescriptionListPtrTy, PropertyListPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005093 Int8PtrPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005094
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005095 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005096 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005097
Daniel Dunbarc475d422008-10-29 22:36:39 +00005098 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00005099
Chris Lattnera5f58b02011-07-09 17:41:47 +00005100 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005101 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00005102
Chris Lattnera5f58b02011-07-09 17:41:47 +00005103 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005104 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005105 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005106 LongTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00005107 llvm::ArrayType::get(ProtocolTy, 0),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005108 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005109
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005110 // struct _objc_protocol {
5111 // struct _objc_protocol_extension *isa;
5112 // char *protocol_name;
5113 // struct _objc_protocol **_objc_protocol_list;
5114 // struct _objc_method_description_list *instance_methods;
5115 // struct _objc_method_description_list *class_methods;
5116 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005117 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5118 llvm::PointerType::getUnqual(ProtocolListTy),
5119 MethodDescriptionListPtrTy,
5120 MethodDescriptionListPtrTy,
5121 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005122
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005123 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005124 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005125
Owen Anderson9793f0e2009-07-29 22:16:19 +00005126 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005127
5128 // Class description structures
5129
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005130 // struct _objc_ivar {
5131 // char *ivar_name;
5132 // char *ivar_type;
5133 // int ivar_offset;
5134 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005135 IvarTy = llvm::StructType::create("struct._objc_ivar",
5136 Int8PtrTy, Int8PtrTy, IntTy, NULL);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005137
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005138 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005139 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005140 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005141 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005142
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005143 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005144 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005145 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005146 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005147
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005148 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005149 ClassExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005150 llvm::StructType::create("struct._objc_class_extension",
5151 IntTy, Int8PtrTy, PropertyListPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005152 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005153
Chris Lattner5ec04a52011-08-12 17:43:31 +00005154 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005155
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005156 // struct _objc_class {
5157 // Class isa;
5158 // Class super_class;
5159 // char *name;
5160 // long version;
5161 // long info;
5162 // long instance_size;
5163 // struct _objc_ivar_list *ivars;
5164 // struct _objc_method_list *methods;
5165 // struct _objc_cache *cache;
5166 // struct _objc_protocol_list *protocols;
5167 // char *ivar_layout;
5168 // struct _objc_class_ext *ext;
5169 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005170 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5171 llvm::PointerType::getUnqual(ClassTy),
5172 Int8PtrTy,
5173 LongTy,
5174 LongTy,
5175 LongTy,
5176 IvarListPtrTy,
5177 MethodListPtrTy,
5178 CachePtrTy,
5179 ProtocolListPtrTy,
5180 Int8PtrTy,
5181 ClassExtensionPtrTy,
5182 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005183
Owen Anderson9793f0e2009-07-29 22:16:19 +00005184 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005185
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005186 // struct _objc_category {
5187 // char *category_name;
5188 // char *class_name;
5189 // struct _objc_method_list *instance_method;
5190 // struct _objc_method_list *class_method;
5191 // uint32_t size; // sizeof(struct _objc_category)
5192 // struct _objc_property_list *instance_properties;// category's @property
5193 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005194 CategoryTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005195 llvm::StructType::create("struct._objc_category",
5196 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5197 MethodListPtrTy, ProtocolListPtrTy,
5198 IntTy, PropertyListPtrTy, NULL);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005199
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005200 // Global metadata structures
5201
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005202 // struct _objc_symtab {
5203 // long sel_ref_cnt;
5204 // SEL *refs;
5205 // short cls_def_cnt;
5206 // short cat_def_cnt;
5207 // char *defs[cls_def_cnt + cat_def_cnt];
5208 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005209 SymtabTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005210 llvm::StructType::create("struct._objc_symtab",
5211 LongTy, SelectorPtrTy, ShortTy, ShortTy,
5212 llvm::ArrayType::get(Int8PtrTy, 0), NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005213 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005214
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00005215 // struct _objc_module {
5216 // long version;
5217 // long size; // sizeof(struct _objc_module)
5218 // char *name;
5219 // struct _objc_symtab* symtab;
5220 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005221 ModuleTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005222 llvm::StructType::create("struct._objc_module",
5223 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00005224
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005225
Mike Stump18bb9282009-05-16 07:57:57 +00005226 // FIXME: This is the size of the setjmp buffer and should be target
5227 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00005228 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005229
Anders Carlsson9ff22482008-09-09 10:10:21 +00005230 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00005231 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005232
5233 ExceptionDataTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005234 llvm::StructType::create("struct._objc_exception_data",
Chris Lattnerece04092012-02-07 00:39:47 +00005235 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
5236 StackPtrTy, NULL);
Anders Carlsson9ff22482008-09-09 10:10:21 +00005237
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005238}
5239
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005240ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005241 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005242 // struct _method_list_t {
5243 // uint32_t entsize; // sizeof(struct _objc_method)
5244 // uint32_t method_count;
5245 // struct _objc_method method_list[method_count];
5246 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005247 MethodListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005248 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
5249 llvm::ArrayType::get(MethodTy, 0), NULL);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005250 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005251 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005252
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005253 // struct _protocol_t {
5254 // id isa; // NULL
5255 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005256 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005257 // const struct method_list_t * const instance_methods;
5258 // const struct method_list_t * const class_methods;
5259 // const struct method_list_t *optionalInstanceMethods;
5260 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005261 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005262 // const uint32_t size; // sizeof(struct _protocol_t)
5263 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005264 // const char ** extendedMethodTypes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005265 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005266
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005267 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005268 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005269 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005270
Chris Lattnera5f58b02011-07-09 17:41:47 +00005271 ProtocolnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005272 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
5273 llvm::PointerType::getUnqual(ProtocolListnfABITy),
5274 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5275 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005276 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
5277 NULL);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005278
5279 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005280 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005281
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005282 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005283 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005284 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005285 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005286 ProtocolListnfABITy->setBody(LongTy,
5287 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
5288 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005289
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005290 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005291 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005292
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005293 // struct _ivar_t {
5294 // unsigned long int *offset; // pointer to ivar offset location
5295 // char *name;
5296 // char *type;
5297 // uint32_t alignment;
5298 // uint32_t size;
5299 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005300 IvarnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005301 llvm::StructType::create("struct._ivar_t",
5302 llvm::PointerType::getUnqual(LongTy),
5303 Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005304
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005305 // struct _ivar_list_t {
5306 // uint32 entsize; // sizeof(struct _ivar_t)
5307 // uint32 count;
5308 // struct _iver_t list[count];
5309 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005310 IvarListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005311 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
5312 llvm::ArrayType::get(IvarnfABITy, 0), NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005313
Owen Anderson9793f0e2009-07-29 22:16:19 +00005314 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005315
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005316 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005317 // uint32_t const flags;
5318 // uint32_t const instanceStart;
5319 // uint32_t const instanceSize;
5320 // uint32_t const reserved; // only when building for 64bit targets
5321 // const uint8_t * const ivarLayout;
5322 // const char *const name;
5323 // const struct _method_list_t * const baseMethods;
5324 // const struct _objc_protocol_list *const baseProtocols;
5325 // const struct _ivar_list_t *const ivars;
5326 // const uint8_t * const weakIvarLayout;
5327 // const struct _prop_list_t * const properties;
5328 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005329
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005330 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattner5ec04a52011-08-12 17:43:31 +00005331 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
5332 IntTy, IntTy, IntTy, Int8PtrTy,
5333 Int8PtrTy, MethodListnfABIPtrTy,
5334 ProtocolListnfABIPtrTy,
5335 IvarListnfABIPtrTy,
5336 Int8PtrTy, PropertyListPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005337
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005338 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00005339 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00005340 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5341 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005342
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005343 // struct _class_t {
5344 // struct _class_t *isa;
5345 // struct _class_t * const superclass;
5346 // void *cache;
5347 // IMP *vtable;
5348 // struct class_ro_t *ro;
5349 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005350
Chris Lattner5ec04a52011-08-12 17:43:31 +00005351 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005352 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
5353 llvm::PointerType::getUnqual(ClassnfABITy),
5354 CachePtrTy,
5355 llvm::PointerType::getUnqual(ImpnfABITy),
5356 llvm::PointerType::getUnqual(ClassRonfABITy),
5357 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005358
Fariborz Jahanian71394042009-01-23 23:53:38 +00005359 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005360 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005361
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005362 // struct _category_t {
5363 // const char * const name;
5364 // struct _class_t *const cls;
5365 // const struct _method_list_t * const instance_methods;
5366 // const struct _method_list_t * const class_methods;
5367 // const struct _protocol_list_t * const protocols;
5368 // const struct _prop_list_t * const properties;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00005369 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005370 CategorynfABITy = llvm::StructType::create("struct._category_t",
5371 Int8PtrTy, ClassnfABIPtrTy,
5372 MethodListnfABIPtrTy,
5373 MethodListnfABIPtrTy,
5374 ProtocolListnfABIPtrTy,
5375 PropertyListPtrTy,
5376 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005377
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005378 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005379 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5380 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005381
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005382 // MessageRefTy - LLVM for:
5383 // struct _message_ref_t {
5384 // IMP messenger;
5385 // SEL name;
5386 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005387
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005388 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00005389 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005390 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005391 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005392 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005393 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005394 Ctx.VoidPtrTy, 0, 0, false, ICIS_NoInit));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005395 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005396 Ctx.getObjCSelType(), 0, 0, false,
5397 ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005398 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005399
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005400 MessageRefCTy = Ctx.getTagDeclType(RD);
5401 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5402 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005403
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005404 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005405 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005406
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005407 // SuperMessageRefTy - LLVM for:
5408 // struct _super_message_ref_t {
5409 // SUPER_IMP messenger;
5410 // SEL name;
5411 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005412 SuperMessageRefTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005413 llvm::StructType::create("struct._super_message_ref_t",
5414 ImpnfABITy, SelectorPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005415
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005416 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005417 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005418
Daniel Dunbarb1559a42009-03-01 04:46:24 +00005419
5420 // struct objc_typeinfo {
5421 // const void** vtable; // objc_ehtype_vtable + 2
5422 // const char* name; // c++ typeinfo string
5423 // Class cls;
5424 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005425 EHTypeTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005426 llvm::StructType::create("struct._objc_typeinfo",
5427 llvm::PointerType::getUnqual(Int8PtrTy),
5428 Int8PtrTy, ClassnfABIPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005429 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005430}
5431
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005432llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00005433 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005434
Fariborz Jahanian71394042009-01-23 23:53:38 +00005435 return NULL;
5436}
5437
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00005438void CGObjCNonFragileABIMac::
5439AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
5440 const char *SymbolName,
5441 const char *SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00005442 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005443
Daniel Dunbar19573e72009-05-15 21:48:48 +00005444 if (!NumClasses)
5445 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005446
Chris Lattner3def9ae2012-02-06 22:16:34 +00005447 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005448 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00005449 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00005450 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00005451 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005452 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00005453 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00005454 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005455
Daniel Dunbar19573e72009-05-15 21:48:48 +00005456 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005457 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005458 llvm::GlobalValue::InternalLinkage,
5459 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005460 SymbolName);
Micah Villmowdd31ca12012-10-08 16:25:52 +00005461 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00005462 GV->setSection(SectionName);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005463 CGM.AddUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005464}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005465
Fariborz Jahanian71394042009-01-23 23:53:38 +00005466void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5467 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005468
Daniel Dunbar19573e72009-05-15 21:48:48 +00005469 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005470 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005471 AddModuleClassList(DefinedClasses,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005472 "\01L_OBJC_LABEL_CLASS_$",
5473 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahanian67260552009-11-17 21:37:35 +00005474
Bill Wendling53136852012-02-07 09:06:01 +00005475 for (unsigned i = 0, e = DefinedClasses.size(); i < e; i++) {
Fariborz Jahanian67260552009-11-17 21:37:35 +00005476 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
5477 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
5478 continue;
5479 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahanian67260552009-11-17 21:37:35 +00005480 }
5481
Bill Wendling53136852012-02-07 09:06:01 +00005482 for (unsigned i = 0, e = DefinedMetaClasses.size(); i < e; i++) {
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005483 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
5484 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
5485 continue;
5486 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
5487 }
Fariborz Jahanian67260552009-11-17 21:37:35 +00005488
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005489 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005490 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
5491 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005492
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005493 // Build list of all implemented category addresses in array
5494 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005495 AddModuleClassList(DefinedCategories,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005496 "\01L_OBJC_LABEL_CATEGORY_$",
5497 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005498 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005499 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
5500 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005501
Daniel Dunbar5e639272010-04-25 20:39:01 +00005502 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005503}
5504
John McCall9e8bb002011-05-14 03:10:52 +00005505/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
5506/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005507/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005508/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00005509bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
5510 // At various points we've experimented with using vtable-based
5511 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005512 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005513 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00005514 return false;
John McCall9e8bb002011-05-14 03:10:52 +00005515 case CodeGenOptions::NonLegacy:
5516 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005517 case CodeGenOptions::Mixed:
5518 break;
5519 }
5520
5521 // If so, see whether this selector is in the white-list of things which must
5522 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00005523 if (VTableDispatchMethods.empty()) {
5524 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
5525 VTableDispatchMethods.insert(GetNullarySelector("class"));
5526 VTableDispatchMethods.insert(GetNullarySelector("self"));
5527 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
5528 VTableDispatchMethods.insert(GetNullarySelector("length"));
5529 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005530
John McCall9e8bb002011-05-14 03:10:52 +00005531 // These are vtable-based if GC is disabled.
5532 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005533 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00005534 VTableDispatchMethods.insert(GetNullarySelector("retain"));
5535 VTableDispatchMethods.insert(GetNullarySelector("release"));
5536 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
5537 }
5538
5539 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
5540 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
5541 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
5542 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
5543 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
5544 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
5545 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
5546
5547 // These are vtable-based if GC is enabled.
5548 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005549 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00005550 VTableDispatchMethods.insert(GetNullarySelector("hash"));
5551 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
5552
5553 // "countByEnumeratingWithState:objects:count"
5554 IdentifierInfo *KeyIdents[] = {
5555 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
5556 &CGM.getContext().Idents.get("objects"),
5557 &CGM.getContext().Idents.get("count")
5558 };
5559 VTableDispatchMethods.insert(
5560 CGM.getContext().Selectors.getSelector(3, KeyIdents));
5561 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005562 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005563
John McCall9e8bb002011-05-14 03:10:52 +00005564 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005565}
5566
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005567/// BuildClassRoTInitializer - generate meta-data for:
5568/// struct _class_ro_t {
5569/// uint32_t const flags;
5570/// uint32_t const instanceStart;
5571/// uint32_t const instanceSize;
5572/// uint32_t const reserved; // only when building for 64bit targets
5573/// const uint8_t * const ivarLayout;
5574/// const char *const name;
5575/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005576/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005577/// const struct _ivar_list_t *const ivars;
5578/// const uint8_t * const weakIvarLayout;
5579/// const struct _prop_list_t * const properties;
5580/// }
5581///
5582llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005583 unsigned flags,
5584 unsigned InstanceStart,
5585 unsigned InstanceSize,
5586 const ObjCImplementationDecl *ID) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005587 std::string ClassName = ID->getNameAsString();
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005588 llvm::Constant *Values[10]; // 11 for 64bit targets!
John McCall31168b02011-06-15 23:02:42 +00005589
David Blaikiebbafb8a2012-03-11 07:00:24 +00005590 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00005591 flags |= NonFragileABI_Class_CompiledByARC;
John McCall31168b02011-06-15 23:02:42 +00005592
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005593 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
5594 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
5595 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005596 // FIXME. For 64bit targets add 0 here.
John McCallef19dbb2012-10-17 04:53:23 +00005597 Values[ 3] = (flags & NonFragileABI_Class_Meta)
5598 ? GetIvarLayoutName(0, ObjCTypes)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005599 : BuildIvarLayout(ID, true);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005600 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005601 // const struct _method_list_t * const baseMethods;
5602 std::vector<llvm::Constant*> Methods;
5603 std::string MethodListName("\01l_OBJC_$_");
John McCallef19dbb2012-10-17 04:53:23 +00005604 if (flags & NonFragileABI_Class_Meta) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005605 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005606 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005607 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005608 // Class methods should always be defined.
5609 Methods.push_back(GetMethodConstant(*i));
5610 }
5611 } else {
5612 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005613 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005614 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005615 // Instance methods should always be defined.
5616 Methods.push_back(GetMethodConstant(*i));
5617 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005618 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005619 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie40ed2972012-06-06 20:45:41 +00005620 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005621
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005622 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
5623 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005624
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005625 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
5626 if (llvm::Constant *C = GetMethodConstant(MD))
5627 Methods.push_back(C);
5628 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
5629 if (llvm::Constant *C = GetMethodConstant(MD))
5630 Methods.push_back(C);
5631 }
5632 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005633 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005634 Values[ 5] = EmitMethodList(MethodListName,
5635 "__DATA, __objc_const", Methods);
5636
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005637 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5638 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005639 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005640 + OID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00005641 OID->all_referenced_protocol_begin(),
5642 OID->all_referenced_protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005643
John McCallef19dbb2012-10-17 04:53:23 +00005644 if (flags & NonFragileABI_Class_Meta) {
Owen Anderson0b75f232009-07-31 20:28:54 +00005645 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCallef19dbb2012-10-17 04:53:23 +00005646 Values[ 8] = GetIvarLayoutName(0, ObjCTypes);
Owen Anderson0b75f232009-07-31 20:28:54 +00005647 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
John McCallef19dbb2012-10-17 04:53:23 +00005648 } else {
5649 Values[ 7] = EmitIvarList(ID);
5650 Values[ 8] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005651 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
5652 ID, ID->getClassInterface(), ObjCTypes);
John McCallef19dbb2012-10-17 04:53:23 +00005653 }
Owen Anderson0e0189d2009-07-27 22:29:56 +00005654 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005655 Values);
5656 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005657 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
5658 llvm::GlobalValue::InternalLinkage,
5659 Init,
John McCallef19dbb2012-10-17 04:53:23 +00005660 (flags & NonFragileABI_Class_Meta) ?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005661 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
5662 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005663 CLASS_RO_GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005664 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005665 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005666 return CLASS_RO_GV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005667
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005668}
5669
5670/// BuildClassMetaData - This routine defines that to-level meta-data
5671/// for the given ClassName for:
5672/// struct _class_t {
5673/// struct _class_t *isa;
5674/// struct _class_t * const superclass;
5675/// void *cache;
5676/// IMP *vtable;
5677/// struct class_ro_t *ro;
5678/// }
5679///
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005680llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005681 std::string &ClassName,
5682 llvm::Constant *IsAGV,
5683 llvm::Constant *SuperClassGV,
5684 llvm::Constant *ClassRoGV,
5685 bool HiddenVisibility) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005686 llvm::Constant *Values[] = {
5687 IsAGV,
5688 SuperClassGV,
5689 ObjCEmptyCacheVar, // &ObjCEmptyCacheVar
5690 ObjCEmptyVtableVar, // &ObjCEmptyVtableVar
5691 ClassRoGV // &CLASS_RO_GV
5692 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005693 if (!Values[1])
5694 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005695 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005696 Values);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005697 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
5698 GV->setInitializer(Init);
Fariborz Jahanian04087232009-01-31 01:07:39 +00005699 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005700 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005701 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian82208252009-01-31 00:59:10 +00005702 if (HiddenVisibility)
5703 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005704 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005705}
5706
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005707bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00005708CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005709 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005710}
5711
Daniel Dunbar961202372009-05-03 12:57:56 +00005712void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00005713 uint32_t &InstanceStart,
5714 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005715 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00005716 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005717
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005718 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00005719 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005720
5721 // If there are no fields, the start is the same as the end.
5722 if (!RL.getFieldCount())
5723 InstanceStart = InstanceSize;
5724 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00005725 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00005726}
5727
Fariborz Jahanian71394042009-01-23 23:53:38 +00005728void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
5729 std::string ClassName = ID->getNameAsString();
5730 if (!ObjCEmptyCacheVar) {
5731 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005732 CGM.getModule(),
5733 ObjCTypes.CacheTy,
5734 false,
5735 llvm::GlobalValue::ExternalLinkage,
5736 0,
5737 "_objc_empty_cache");
5738
Fariborz Jahanian71394042009-01-23 23:53:38 +00005739 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005740 CGM.getModule(),
5741 ObjCTypes.ImpnfABITy,
5742 false,
5743 llvm::GlobalValue::ExternalLinkage,
5744 0,
5745 "_objc_empty_vtable");
Fariborz Jahanian71394042009-01-23 23:53:38 +00005746 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005747 assert(ID->getClassInterface() &&
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005748 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00005749 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005750 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00005751 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005752 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00005753 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar15894b72009-04-07 05:48:37 +00005754 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
5755 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005756
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005757 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005758
John McCall0d54a172012-10-17 04:53:31 +00005759 // Build the flags for the metaclass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005760 bool classIsHidden =
John McCall457a04e2010-10-22 21:05:15 +00005761 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005762 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00005763 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00005764
5765 // FIXME: why is this flag set on the metaclass?
5766 // ObjC metaclasses have no fields and don't really get constructed.
5767 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00005768 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00005769 if (!ID->hasNonZeroConstructors())
5770 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5771 }
5772
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005773 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005774 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00005775 flags |= NonFragileABI_Class_Root;
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005776 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005777 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005778 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005779 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005780 const ObjCInterfaceDecl *Root = ID->getClassInterface();
5781 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
5782 Root = Super;
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005783 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005784 if (Root->isWeakImported())
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005785 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005786 // work on super class metadata symbol.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005787 std::string SuperClassName =
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005788 ObjCMetaClassName +
5789 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005790 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005791 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005792 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005793 }
5794 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
5795 InstanceStart,
5796 InstanceSize,ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005797 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005798 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005799 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
5800 classIsHidden);
Fariborz Jahanian67260552009-11-17 21:37:35 +00005801 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00005802
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005803 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00005804 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005805 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00005806 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00005807
5808 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00005809 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005810
John McCall0d54a172012-10-17 04:53:31 +00005811 // Set a flag to enable a runtime optimization when a class has
5812 // fields that require destruction but which don't require
5813 // anything except zero-initialization during construction. This
5814 // is most notably true of __strong and __weak types, but you can
5815 // also imagine there being C++ types with non-trivial default
5816 // constructors that merely set all fields to null.
5817 if (!ID->hasNonZeroConstructors())
5818 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5819 }
5820
Douglas Gregor78bd61f2009-06-18 16:11:24 +00005821 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
John McCallef19dbb2012-10-17 04:53:23 +00005822 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005823
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005824 if (!ID->getClassInterface()->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00005825 flags |= NonFragileABI_Class_Root;
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005826 SuperClassGV = 0;
Chris Lattnerb433b272009-04-19 06:02:28 +00005827 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005828 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005829 std::string RootClassName =
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005830 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005831 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005832 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005833 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005834 }
Daniel Dunbar961202372009-05-03 12:57:56 +00005835 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005836 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005837 InstanceStart,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005838 InstanceSize,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005839 ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005840
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005841 TClassName = ObjCClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005842 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005843 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5844 classIsHidden);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005845 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005846
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005847 // Determine if this class is also "non-lazy".
5848 if (ImplementationIsNonLazy(ID))
5849 DefinedNonLazyClasses.push_back(ClassMD);
5850
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005851 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00005852 if (flags & NonFragileABI_Class_Exception)
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005853 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005854 // Make sure method definition entries are all clear for next implementation.
5855 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005856}
5857
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005858/// GenerateProtocolRef - This routine is called to generate code for
5859/// a protocol reference expression; as in:
5860/// @code
5861/// @protocol(Proto1);
5862/// @endcode
5863/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5864/// which will hold address of the protocol meta-data.
5865///
5866llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005867 const ObjCProtocolDecl *PD) {
5868
Fariborz Jahanian464423d2009-04-10 18:47:34 +00005869 // This routine is called for @protocol only. So, we must build definition
5870 // of protocol's meta-data (not a reference to it!)
5871 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005872 llvm::Constant *Init =
5873 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00005874 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005875
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005876 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar56df9772010-08-17 22:39:59 +00005877 ProtocolName += PD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005878
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005879 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5880 if (PTGV)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005881 return Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005882 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005883 CGM.getModule(),
5884 Init->getType(), false,
5885 llvm::GlobalValue::WeakAnyLinkage,
5886 Init,
5887 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005888 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5889 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005890 CGM.AddUsedGlobal(PTGV);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005891 return Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005892}
5893
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005894/// GenerateCategory - Build metadata for a category implementation.
5895/// struct _category_t {
5896/// const char * const name;
5897/// struct _class_t *const cls;
5898/// const struct _method_list_t * const instance_methods;
5899/// const struct _method_list_t * const class_methods;
5900/// const struct _protocol_list_t * const protocols;
5901/// const struct _prop_list_t * const properties;
5902/// }
5903///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005904void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005905 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005906 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005907 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5908 "_$_" + OCD->getNameAsString());
5909 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar15894b72009-04-07 05:48:37 +00005910 Interface->getNameAsString());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005911
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005912 llvm::Constant *Values[6];
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005913 Values[0] = GetClassName(OCD->getIdentifier());
5914 // meta-class entry symbol
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005915 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005916 if (Interface->isWeakImported())
Fariborz Jahanian3ad8dcf2009-11-17 22:02:21 +00005917 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5918
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005919 Values[1] = ClassGV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005920 std::vector<llvm::Constant*> Methods;
5921 std::string MethodListName(Prefix);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005922 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005923 "_$_" + OCD->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005924
5925 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005926 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005927 // Instance methods should always be defined.
5928 Methods.push_back(GetMethodConstant(*i));
5929 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005930
5931 Values[2] = EmitMethodList(MethodListName,
5932 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005933 Methods);
5934
5935 MethodListName = Prefix;
5936 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5937 OCD->getNameAsString();
5938 Methods.clear();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005939 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005940 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005941 // Class methods should always be defined.
5942 Methods.push_back(GetMethodConstant(*i));
5943 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005944
5945 Values[3] = EmitMethodList(MethodListName,
5946 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005947 Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005948 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00005949 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005950 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005951 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005952 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5953 << OCD->getName();
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005954 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005955 + Interface->getName() + "_$_"
5956 + Category->getName(),
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005957 Category->protocol_begin(),
5958 Category->protocol_end());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005959 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5960 OCD, Category, ObjCTypes);
Mike Stump658fe022009-07-30 22:28:39 +00005961 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00005962 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5963 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005964 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005965
5966 llvm::Constant *Init =
5967 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005968 Values);
5969 llvm::GlobalVariable *GCATV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005970 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005971 false,
5972 llvm::GlobalValue::InternalLinkage,
5973 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005974 ExtCatName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005975 GCATV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005976 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005977 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005978 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005979 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005980
5981 // Determine if this category is also "non-lazy".
5982 if (ImplementationIsNonLazy(OCD))
5983 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005984 // method definition entries must be clear for next implementation.
5985 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005986}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005987
5988/// GetMethodConstant - Return a struct objc_method constant for the
5989/// given method if it has been defined. The result is null if the
5990/// method has not been defined. The return value has type MethodPtrTy.
5991llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005992 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005993 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005994 if (!Fn)
5995 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005996
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005997 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00005998 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005999 ObjCTypes.SelectorPtrTy),
6000 GetMethodVarType(MD),
6001 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
6002 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00006003 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006004}
6005
6006/// EmitMethodList - Build meta-data for method declarations
6007/// struct _method_list_t {
6008/// uint32_t entsize; // sizeof(struct _objc_method)
6009/// uint32_t method_count;
6010/// struct _objc_method method_list[method_count];
6011/// }
6012///
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00006013llvm::Constant *
6014CGObjCNonFragileABIMac::EmitMethodList(Twine Name,
6015 const char *Section,
6016 ArrayRef<llvm::Constant*> Methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006017 // Return null for empty list.
6018 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006019 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006020
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006021 llvm::Constant *Values[3];
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006022 // sizeof(struct _objc_method)
Micah Villmowdd31ca12012-10-08 16:25:52 +00006023 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006024 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006025 // method_count
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006026 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00006027 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006028 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00006029 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006030 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006031
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006032 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006033 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006034 llvm::GlobalValue::InternalLinkage, Init, Name);
Micah Villmowdd31ca12012-10-08 16:25:52 +00006035 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006036 GV->setSection(Section);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006037 CGM.AddUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006038 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006039}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006040
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006041/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6042/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006043llvm::GlobalVariable *
6044CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6045 const ObjCIvarDecl *Ivar) {
6046 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar3f86b9c2009-05-05 00:36:57 +00006047 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregorbcced4e2009-04-09 21:40:53 +00006048 '.' + Ivar->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006049 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006050 CGM.getModule().getGlobalVariable(Name);
6051 if (!IvarOffsetGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006052 IvarOffsetGV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006053 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006054 false,
6055 llvm::GlobalValue::ExternalLinkage,
6056 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006057 Name);
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006058 return IvarOffsetGV;
6059}
6060
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006061llvm::Constant *
6062CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6063 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00006064 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006065 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006066 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Eli Friedman8cbca202012-11-06 22:15:52 +00006067 Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006068 IvarOffsetGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006069 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006070
Mike Stump18bb9282009-05-16 07:57:57 +00006071 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
6072 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006073 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6074 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall457a04e2010-10-22 21:05:15 +00006075 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00006076 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00006077 else
Fariborz Jahanianbc3c77b2009-04-06 18:30:00 +00006078 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendlingf7d45982011-05-04 21:37:25 +00006079 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006080 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006081}
6082
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006083/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006084/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006085/// IvarListnfABIPtrTy.
6086/// struct _ivar_t {
6087/// unsigned long int *offset; // pointer to ivar offset location
6088/// char *name;
6089/// char *type;
6090/// uint32_t alignment;
6091/// uint32_t size;
6092/// }
6093/// struct _ivar_list_t {
6094/// uint32 entsize; // sizeof(struct _ivar_t)
6095/// uint32 count;
6096/// struct _iver_t list[count];
6097/// }
6098///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00006099
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006100llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006101 const ObjCImplementationDecl *ID) {
6102
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006103 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006104
Jordy Rosea91768e2011-07-22 02:08:32 +00006105 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006106 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006107
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006108 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006109
Jordy Rosea91768e2011-07-22 02:08:32 +00006110 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00006111 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00006112 // Ignore unnamed bit-fields.
6113 if (!IVD->getDeclName())
6114 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006115 llvm::Constant *Ivar[5];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006116 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar961202372009-05-03 12:57:56 +00006117 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006118 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
6119 Ivar[2] = GetMethodVarType(IVD);
Chris Lattner2192fe52011-07-18 04:24:23 +00006120 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006121 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00006122 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006123 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006124 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006125 Align = llvm::Log2_32(Align);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006126 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00006127 // NOTE. Size of a bitfield does not match gcc's, because of the
6128 // way bitfields are treated special in each. But I am told that
6129 // 'size' for bitfield ivars is ignored by the runtime so it does
6130 // not matter. If it matters, there is enough info to get the
6131 // bitfield right!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006132 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006133 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006134 }
6135 // Return null for empty list.
6136 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006137 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006138
6139 llvm::Constant *Values[3];
Micah Villmowdd31ca12012-10-08 16:25:52 +00006140 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006141 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
6142 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00006143 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006144 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00006145 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006146 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006147 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
6148 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006149 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006150 llvm::GlobalValue::InternalLinkage,
6151 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006152 Prefix + OID->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006153 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006154 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006155 GV->setSection("__DATA, __objc_const");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006156
Chris Lattnerf56501c2009-07-17 23:57:13 +00006157 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00006158 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006159}
6160
6161llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006162 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006163 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006164
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006165 if (!Entry) {
6166 // We use the initializer as a marker of whether this is a forward
6167 // reference or not. At module finalization we add the empty
6168 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006169 Entry =
6170 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
6171 llvm::GlobalValue::ExternalLinkage,
6172 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006173 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006174 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006175 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006176
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006177 return Entry;
6178}
6179
6180/// GetOrEmitProtocol - Generate the protocol meta-data:
6181/// @code
6182/// struct _protocol_t {
6183/// id isa; // NULL
6184/// const char * const protocol_name;
6185/// const struct _protocol_list_t * protocol_list; // super protocols
6186/// const struct method_list_t * const instance_methods;
6187/// const struct method_list_t * const class_methods;
6188/// const struct method_list_t *optionalInstanceMethods;
6189/// const struct method_list_t *optionalClassMethods;
6190/// const struct _prop_list_t * properties;
6191/// const uint32_t size; // sizeof(struct _protocol_t)
6192/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006193/// const char ** extendedMethodTypes;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006194/// }
6195/// @endcode
6196///
6197
6198llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006199 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00006200 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006201
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006202 // Early exit if a defining object has already been generated.
6203 if (Entry && Entry->hasInitializer())
6204 return Entry;
6205
Douglas Gregora715bff2012-01-01 19:51:50 +00006206 // Use the protocol definition, if there is one.
6207 if (const ObjCProtocolDecl *Def = PD->getDefinition())
6208 PD = Def;
6209
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006210 // Construct method lists.
6211 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
6212 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006213 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006214 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00006215 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006216 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006217 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006218 if (!C)
6219 return GetOrEmitProtocolRef(PD);
6220
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006221 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6222 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006223 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006224 } else {
6225 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006226 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006227 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006228 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006229
6230 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00006231 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006232 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006233 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006234 if (!C)
6235 return GetOrEmitProtocolRef(PD);
6236
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006237 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6238 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006239 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006240 } else {
6241 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006242 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006243 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006244 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006245
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006246 MethodTypesExt.insert(MethodTypesExt.end(),
6247 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
6248
6249 llvm::Constant *Values[11];
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006250 // isa is NULL
Owen Anderson0b75f232009-07-31 20:28:54 +00006251 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006252 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006253 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
6254 PD->protocol_begin(),
6255 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006256
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006257 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006258 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006259 "__DATA, __objc_const",
6260 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006261 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006262 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006263 "__DATA, __objc_const",
6264 ClassMethods);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006265 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006266 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006267 "__DATA, __objc_const",
6268 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006269 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006270 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006271 "__DATA, __objc_const",
6272 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006273 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006274 0, PD, ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006275 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006276 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006277 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0b75f232009-07-31 20:28:54 +00006278 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006279 Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
6280 + PD->getName(),
6281 MethodTypesExt, ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006282 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006283 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006284
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006285 if (Entry) {
6286 // Already created, fix the linkage and update the initializer.
Mike Stumpa6ca3342009-03-07 16:33:28 +00006287 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006288 Entry->setInitializer(Init);
6289 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006290 Entry =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006291 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6292 false, llvm::GlobalValue::WeakAnyLinkage, Init,
6293 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006294 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006295 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006296 Entry->setSection("__DATA,__datacoal_nt,coalesced");
John McCallf9582a72012-03-30 21:29:05 +00006297
6298 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006299 }
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006300 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006301 CGM.AddUsedGlobal(Entry);
6302
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006303 // Use this protocol meta-data to build protocol list table in section
6304 // __DATA, __objc_protolist
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006305 llvm::GlobalVariable *PTGV =
6306 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
6307 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
6308 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006309 PTGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006310 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbarb25452a2009-04-15 02:56:18 +00006311 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006312 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006313 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006314 return Entry;
6315}
6316
6317/// EmitProtocolList - Generate protocol list meta-data:
6318/// @code
6319/// struct _protocol_list_t {
6320/// long protocol_count; // Note, this is 32/64 bit
6321/// struct _protocol_t[protocol_count];
6322/// }
6323/// @endcode
6324///
6325llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006326CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006327 ObjCProtocolDecl::protocol_iterator begin,
6328 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendlinga515b582012-02-09 22:16:49 +00006329 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006330
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006331 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006332 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00006333 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006334
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006335 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006336 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006337 Name.toVector(TmpName);
6338 llvm::GlobalVariable *GV =
6339 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006340 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006341 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006342
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006343 for (; begin != end; ++begin)
6344 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
6345
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006346 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00006347 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006348 ObjCTypes.ProtocolnfABIPtrTy));
6349
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006350 llvm::Constant *Values[2];
Owen Anderson170229f2009-07-14 23:10:40 +00006351 Values[0] =
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006352 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006353 Values[1] =
Bill Wendlinga515b582012-02-09 22:16:49 +00006354 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
6355 ProtocolRefs.size()),
6356 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006357
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006358 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Owen Andersonc10c8d32009-07-08 19:05:04 +00006359 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006360 llvm::GlobalValue::InternalLinkage,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006361 Init, Name);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006362 GV->setSection("__DATA, __objc_const");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006363 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006364 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Chris Lattnerf56501c2009-07-17 23:57:13 +00006365 CGM.AddUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006366 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006367 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006368}
6369
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006370/// GetMethodDescriptionConstant - This routine build following meta-data:
6371/// struct _objc_method {
6372/// SEL _cmd;
6373/// char *method_type;
6374/// char *_imp;
6375/// }
6376
6377llvm::Constant *
6378CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006379 llvm::Constant *Desc[3];
Owen Anderson170229f2009-07-14 23:10:40 +00006380 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006381 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
6382 ObjCTypes.SelectorPtrTy);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006383 Desc[1] = GetMethodVarType(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006384 if (!Desc[1])
6385 return 0;
6386
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006387 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00006388 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006389 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006390}
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006391
6392/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
6393/// This code gen. amounts to generating code for:
6394/// @code
6395/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
6396/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006397///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00006398LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00006399 CodeGen::CodeGenFunction &CGF,
6400 QualType ObjectTy,
6401 llvm::Value *BaseValue,
6402 const ObjCIvarDecl *Ivar,
6403 unsigned CVRQualifiers) {
6404 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006405 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
6406 if (llvm::LoadInst *LI = dyn_cast<llvm::LoadInst>(Offset))
6407 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6408 llvm::MDNode::get(VMContext,
6409 ArrayRef<llvm::Value*>()));
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00006410 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006411 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006412}
6413
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006414llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006415 CodeGen::CodeGenFunction &CGF,
6416 const ObjCInterfaceDecl *Interface,
6417 const ObjCIvarDecl *Ivar) {
Daniel Dunbarc76493a2009-11-29 21:23:36 +00006418 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006419}
6420
John McCall234eac82011-05-13 23:16:18 +00006421static void appendSelectorForMessageRefTable(std::string &buffer,
6422 Selector selector) {
6423 if (selector.isUnarySelector()) {
6424 buffer += selector.getNameForSlot(0);
6425 return;
6426 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006427
John McCall234eac82011-05-13 23:16:18 +00006428 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
6429 buffer += selector.getNameForSlot(i);
6430 buffer += '_';
6431 }
6432}
6433
John McCall9e8bb002011-05-14 03:10:52 +00006434/// Emit a "v-table" message send. We emit a weak hidden-visibility
6435/// struct, initially containing the selector pointer and a pointer to
6436/// a "fixup" variant of the appropriate objc_msgSend. To call, we
6437/// load and call the function pointer, passing the address of the
6438/// struct as the second parameter. The runtime determines whether
6439/// the selector is currently emitted using vtable dispatch; if so, it
6440/// substitutes a stub function which simply tail-calls through the
6441/// appropriate vtable slot, and if not, it substitues a stub function
6442/// which tail-calls objc_msgSend. Both stubs adjust the selector
6443/// argument to correctly point to the selector.
6444RValue
6445CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
6446 ReturnValueSlot returnSlot,
6447 QualType resultType,
6448 Selector selector,
6449 llvm::Value *arg0,
6450 QualType arg0Type,
6451 bool isSuper,
6452 const CallArgList &formalArgs,
6453 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00006454 // Compute the actual arguments.
6455 CallArgList args;
6456
John McCall9e8bb002011-05-14 03:10:52 +00006457 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00006458 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00006459 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
6460 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00006461
John McCall9e8bb002011-05-14 03:10:52 +00006462 // Second argument: a pointer to the message ref structure. Leave
6463 // the actual argument value blank for now.
John McCall234eac82011-05-13 23:16:18 +00006464 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
6465
6466 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
6467
John McCalla729c622012-02-17 03:33:10 +00006468 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00006469
John McCall5880fb82011-05-14 21:12:11 +00006470 NullReturnState nullReturn;
6471
John McCall9e8bb002011-05-14 03:10:52 +00006472 // Find the function to call and the mangled name for the message
6473 // ref structure. Using a different mangled name wouldn't actually
6474 // be a problem; it would just be a waste.
6475 //
6476 // The runtime currently never uses vtable dispatch for anything
6477 // except normal, non-super message-sends.
6478 // FIXME: don't use this for that.
John McCall234eac82011-05-13 23:16:18 +00006479 llvm::Constant *fn = 0;
6480 std::string messageRefName("\01l_");
John McCalla729c622012-02-17 03:33:10 +00006481 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00006482 if (isSuper) {
6483 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
6484 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006485 } else {
John McCall5880fb82011-05-14 21:12:11 +00006486 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00006487 fn = ObjCTypes.getMessageSendStretFixupFn();
6488 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006489 }
John McCall234eac82011-05-13 23:16:18 +00006490 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
6491 fn = ObjCTypes.getMessageSendFpretFixupFn();
6492 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00006493 } else {
John McCall234eac82011-05-13 23:16:18 +00006494 if (isSuper) {
6495 fn = ObjCTypes.getMessageSendSuper2FixupFn();
6496 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006497 } else {
John McCall234eac82011-05-13 23:16:18 +00006498 fn = ObjCTypes.getMessageSendFixupFn();
6499 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006500 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006501 }
John McCall234eac82011-05-13 23:16:18 +00006502 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
6503 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006504
John McCall234eac82011-05-13 23:16:18 +00006505 // Append the selector name, except use underscores anywhere we
6506 // would have used colons.
6507 appendSelectorForMessageRefTable(messageRefName, selector);
6508
6509 llvm::GlobalVariable *messageRef
6510 = CGM.getModule().getGlobalVariable(messageRefName);
6511 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00006512 // Build the message ref structure.
John McCall234eac82011-05-13 23:16:18 +00006513 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006514 llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
John McCall234eac82011-05-13 23:16:18 +00006515 messageRef = new llvm::GlobalVariable(CGM.getModule(),
6516 init->getType(),
6517 /*constant*/ false,
6518 llvm::GlobalValue::WeakAnyLinkage,
6519 init,
6520 messageRefName);
6521 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
6522 messageRef->setAlignment(16);
6523 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
6524 }
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006525
6526 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006527 if (CGM.getLangOpts().ObjCAutoRefCount && method)
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006528 for (ObjCMethodDecl::param_const_iterator i = method->param_begin(),
6529 e = method->param_end(); i != e; ++i) {
6530 const ParmVarDecl *ParamDecl = (*i);
6531 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
6532 if (!nullReturn.NullBB)
6533 nullReturn.init(CGF, arg0);
6534 requiresnullCheck = true;
6535 break;
6536 }
6537 }
6538
John McCall234eac82011-05-13 23:16:18 +00006539 llvm::Value *mref =
6540 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
6541
John McCall9e8bb002011-05-14 03:10:52 +00006542 // Update the message ref argument.
John McCall234eac82011-05-13 23:16:18 +00006543 args[1].RV = RValue::get(mref);
6544
6545 // Load the function to call from the message ref table.
6546 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
6547 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
6548
John McCalla729c622012-02-17 03:33:10 +00006549 callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
John McCall234eac82011-05-13 23:16:18 +00006550
John McCalla729c622012-02-17 03:33:10 +00006551 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006552 return nullReturn.complete(CGF, result, resultType, formalArgs,
6553 requiresnullCheck ? method : 0);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00006554}
6555
6556/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006557CodeGen::RValue
6558CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00006559 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006560 QualType ResultType,
6561 Selector Sel,
6562 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006563 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00006564 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006565 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00006566 return isVTableDispatchedSelector(Sel)
6567 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006568 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00006569 false, CallArgs, Method)
6570 : EmitMessageSend(CGF, Return, ResultType,
6571 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006572 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00006573 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00006574}
6575
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006576llvm::GlobalVariable *
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006577CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006578 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
6579
Daniel Dunbara6468342009-03-02 05:18:14 +00006580 if (!GV) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006581 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006582 false, llvm::GlobalValue::ExternalLinkage,
6583 0, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006584 }
6585
6586 return GV;
6587}
6588
John McCall31168b02011-06-15 23:02:42 +00006589llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CGBuilderTy &Builder,
6590 IdentifierInfo *II) {
6591 llvm::GlobalVariable *&Entry = ClassReferences[II];
6592
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006593 if (!Entry) {
John McCall31168b02011-06-15 23:02:42 +00006594 std::string ClassName(getClassSymbolPrefix() + II->getName().str());
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006595 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006596 Entry =
John McCall31168b02011-06-15 23:02:42 +00006597 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
6598 false, llvm::GlobalValue::InternalLinkage,
6599 ClassGV,
6600 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006601 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006602 CGM.getDataLayout().getABITypeAlignment(
John McCall31168b02011-06-15 23:02:42 +00006603 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006604 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006605 CGM.AddUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006606 }
John McCall31168b02011-06-15 23:02:42 +00006607
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006608 return Builder.CreateLoad(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006609}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006610
John McCall31168b02011-06-15 23:02:42 +00006611llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
6612 const ObjCInterfaceDecl *ID) {
6613 return EmitClassRefFromId(Builder, ID->getIdentifier());
6614}
6615
6616llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
6617 CGBuilderTy &Builder) {
6618 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
6619 return EmitClassRefFromId(Builder, II);
6620}
6621
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006622llvm::Value *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006623CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006624 const ObjCInterfaceDecl *ID) {
6625 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006626
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006627 if (!Entry) {
6628 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6629 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006630 Entry =
6631 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006632 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006633 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006634 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006635 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006636 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006637 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006638 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006639 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006640 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006641
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006642 return Builder.CreateLoad(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006643}
6644
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006645/// EmitMetaClassRef - Return a Value * of the address of _class_t
6646/// meta-data
6647///
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006648llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
6649 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006650 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
6651 if (Entry)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006652 return Builder.CreateLoad(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006653
Daniel Dunbar15894b72009-04-07 05:48:37 +00006654 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006655 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006656 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006657 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006658 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006659 MetaClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006660 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006661 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006662 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006663 ObjCTypes.ClassnfABIPtrTy));
6664
Daniel Dunbare60aa052009-04-15 19:03:14 +00006665 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006666 CGM.AddUsedGlobal(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006667
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006668 return Builder.CreateLoad(Entry);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006669}
6670
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006671/// GetClass - Return a reference to the class for the given interface
6672/// decl.
6673llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
6674 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00006675 if (ID->isWeakImported()) {
Fariborz Jahanian95ace552009-11-17 22:42:00 +00006676 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6677 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
6678 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
6679 }
6680
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006681 return EmitClassRef(Builder, ID);
6682}
6683
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006684/// Generates a message send where the super is the receiver. This is
6685/// a message send to self with special delivery semantics indicating
6686/// which class's method should be called.
6687CodeGen::RValue
6688CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00006689 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006690 QualType ResultType,
6691 Selector Sel,
6692 const ObjCInterfaceDecl *Class,
6693 bool isCategoryImpl,
6694 llvm::Value *Receiver,
6695 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006696 const CodeGen::CallArgList &CallArgs,
6697 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006698 // ...
6699 // Create and init a super structure; this is a (receiver, class)
6700 // pair we will pass to objc_msgSendSuper.
6701 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00006702 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006703
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006704 llvm::Value *ReceiverAsObject =
6705 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
6706 CGF.Builder.CreateStore(ReceiverAsObject,
6707 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006708
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006709 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006710 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00006711 if (IsClassMessage)
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006712 Target = EmitMetaClassRef(CGF.Builder, Class);
Fariborz Jahanian27678b02012-10-10 23:11:18 +00006713 else
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006714 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006715
Mike Stump18bb9282009-05-16 07:57:57 +00006716 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
6717 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00006718 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006719 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
6720 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
6721 CGF.Builder.CreateStore(Target,
6722 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006723
John McCall9e8bb002011-05-14 03:10:52 +00006724 return (isVTableDispatchedSelector(Sel))
6725 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006726 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006727 true, CallArgs, Method)
6728 : EmitMessageSend(CGF, Return, ResultType,
6729 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006730 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006731 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006732}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006733
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006734llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006735 Selector Sel, bool lval) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006736 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006737
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006738 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006739 llvm::Constant *Casted =
6740 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
6741 ObjCTypes.SelectorPtrTy);
6742 Entry =
6743 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
6744 llvm::GlobalValue::InternalLinkage,
6745 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006746 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006747 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006748 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006749
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006750 if (lval)
6751 return Entry;
Pete Cooper9d605512011-11-10 21:45:06 +00006752 llvm::LoadInst* LI = Builder.CreateLoad(Entry);
6753
6754 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6755 llvm::MDNode::get(VMContext,
6756 ArrayRef<llvm::Value*>()));
6757 return LI;
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006758}
Fariborz Jahanian06292952009-02-16 22:52:32 +00006759/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006760/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00006761///
6762void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006763 llvm::Value *src,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006764 llvm::Value *dst,
6765 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006766 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006767 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006768 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006769 assert(Size <= 8 && "does not support size > 8");
6770 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6771 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006772 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6773 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006774 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6775 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006776 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
6777 src, dst, ivarOffset);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006778 return;
6779}
6780
6781/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
6782/// objc_assign_strongCast (id src, id *dst)
6783///
6784void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006785 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006786 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006787 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006788 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006789 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006790 assert(Size <= 8 && "does not support size > 8");
6791 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006792 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006793 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6794 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006795 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6796 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00006797 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006798 src, dst, "weakassign");
6799 return;
6800}
6801
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006802void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006803 CodeGen::CodeGenFunction &CGF,
6804 llvm::Value *DestPtr,
6805 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006806 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006807 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
6808 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006809 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006810 DestPtr, SrcPtr, Size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006811 return;
6812}
6813
Fariborz Jahanian06292952009-02-16 22:52:32 +00006814/// EmitObjCWeakRead - Code gen for loading value of a __weak
6815/// object: objc_read_weak (id *src)
6816///
6817llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006818 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006819 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006820 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006821 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
6822 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00006823 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006824 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00006825 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006826 return read_weak;
6827}
6828
6829/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
6830/// objc_assign_weak (id src, id *dst)
6831///
6832void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006833 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006834 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006835 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006836 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006837 assert(Size <= 8 && "does not support size > 8");
6838 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6839 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006840 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6841 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006842 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6843 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00006844 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006845 src, dst, "weakassign");
6846 return;
6847}
6848
6849/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
6850/// objc_assign_global (id src, id *dst)
6851///
6852void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00006853 llvm::Value *src, llvm::Value *dst,
6854 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006855 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006856 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006857 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006858 assert(Size <= 8 && "does not support size > 8");
6859 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6860 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006861 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6862 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006863 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6864 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00006865 if (!threadlocal)
6866 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
6867 src, dst, "globalassign");
6868 else
6869 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
6870 src, dst, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00006871 return;
6872}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006873
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006874void
John McCallbd309292010-07-06 01:34:17 +00006875CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6876 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006877 EmitAtSynchronizedStmt(CGF, S,
6878 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6879 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00006880}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006881
John McCall2ca705e2010-07-24 00:37:23 +00006882llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00006883CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00006884 // There's a particular fixed type info for 'id'.
6885 if (T->isObjCIdType() ||
6886 T->isObjCQualifiedIdType()) {
6887 llvm::Constant *IDEHType =
6888 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6889 if (!IDEHType)
6890 IDEHType =
6891 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6892 false,
6893 llvm::GlobalValue::ExternalLinkage,
6894 0, "OBJC_EHTYPE_id");
6895 return IDEHType;
6896 }
6897
6898 // All other types should be Objective-C interface pointer types.
6899 const ObjCObjectPointerType *PT =
6900 T->getAs<ObjCObjectPointerType>();
6901 assert(PT && "Invalid @catch type.");
6902 const ObjCInterfaceType *IT = PT->getInterfaceType();
6903 assert(IT && "Invalid @catch type.");
6904 return GetInterfaceEHType(IT->getDecl(), false);
6905}
6906
John McCallbd309292010-07-06 01:34:17 +00006907void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6908 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006909 EmitTryCatchStmt(CGF, S,
6910 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6911 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6912 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006913}
6914
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006915/// EmitThrowStmt - Generate code for a throw statement.
6916void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6917 const ObjCAtThrowStmt &S) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006918 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00006919 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006920 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Jay Foad5bd375a2011-07-15 08:37:34 +00006921 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall17afe452010-10-16 08:21:07 +00006922 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006923 } else {
Jay Foad5bd375a2011-07-15 08:37:34 +00006924 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall17afe452010-10-16 08:21:07 +00006925 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006926 }
6927
John McCall17afe452010-10-16 08:21:07 +00006928 CGF.Builder.CreateUnreachable();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006929 CGF.Builder.ClearInsertionPoint();
6930}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006931
John McCall2ca705e2010-07-24 00:37:23 +00006932llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006933CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006934 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006935 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006936
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006937 // If we don't need a definition, return the entry if found or check
6938 // if we use an external reference.
6939 if (!ForDefinition) {
6940 if (Entry)
6941 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00006942
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006943 // If this type (or a super class) has the __objc_exception__
6944 // attribute, emit an external reference.
Douglas Gregor78bd61f2009-06-18 16:11:24 +00006945 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006946 return Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006947 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006948 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006949 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006950 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006951 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006952 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006953
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006954 // Otherwise we need to either make a new entry or fill in the
6955 // initializer.
6956 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar15894b72009-04-07 05:48:37 +00006957 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006958 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006959 llvm::GlobalVariable *VTableGV =
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006960 CGM.getModule().getGlobalVariable(VTableName);
6961 if (!VTableGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006962 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6963 false,
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006964 llvm::GlobalValue::ExternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006965 0, VTableName);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006966
Chris Lattnerece04092012-02-07 00:39:47 +00006967 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006968
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006969 llvm::Constant *Values[] = {
6970 llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
6971 GetClassName(ID->getIdentifier()),
6972 GetClassGlobal(ClassName)
6973 };
Owen Anderson170229f2009-07-14 23:10:40 +00006974 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00006975 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006976
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006977 if (Entry) {
6978 Entry->setInitializer(Init);
6979 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00006980 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006981 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006982 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006983 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006984 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006985 }
6986
David Blaikiebbafb8a2012-03-11 07:00:24 +00006987 if (CGM.getLangOpts().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar15894b72009-04-07 05:48:37 +00006988 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Micah Villmowdd31ca12012-10-08 16:25:52 +00006989 Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00006990 ObjCTypes.EHTypeTy));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006991
6992 if (ForDefinition) {
6993 Entry->setSection("__DATA,__objc_const");
6994 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6995 } else {
6996 Entry->setSection("__DATA,__datacoal_nt,coalesced");
6997 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006998
6999 return Entry;
7000}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007001
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00007002/* *** */
7003
Daniel Dunbarb036db82008-08-13 03:21:16 +00007004CodeGen::CGObjCRuntime *
7005CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00007006 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7007 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007008 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00007009
7010 case ObjCRuntime::MacOSX:
7011 case ObjCRuntime::iOS:
7012 return new CGObjCNonFragileABIMac(CGM);
7013
David Chisnallb601c962012-07-03 20:49:52 +00007014 case ObjCRuntime::GNUstep:
7015 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00007016 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00007017 llvm_unreachable("these runtimes are not Mac runtimes");
7018 }
7019 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007020}