blob: d84875bfd5145ac7fbd7f421808b4c8417d278ad [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.
Fariborz Jahanian4cf177e2012-12-04 17:20:57 +00002427 if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2428 UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2429 blockInfo.BlockHeaderForcedGapOffset,
2430 blockInfo.BlockHeaderForcedGapSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002431 // Walk the captured variables.
2432 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
2433 ce = blockDecl->capture_end(); ci != ce; ++ci) {
2434 const VarDecl *variable = ci->getVariable();
2435 QualType type = variable->getType();
2436
2437 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2438
2439 // Ignore constant captures.
2440 if (capture.isConstant()) continue;
2441
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002442 CharUnits fieldOffset =
2443 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002444
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002445 assert(!type->isArrayType() && "array variable should not be caught");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002446 if (!ci->isByRef())
2447 if (const RecordType *record = type->getAs<RecordType>()) {
2448 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2449 continue;
2450 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002451 CharUnits fieldSize;
2452 if (ci->isByRef())
2453 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2454 else
2455 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002456 UpdateRunSkipBlockVars(ci->isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002457 fieldOffset, fieldSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002458 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002459 return getBitmapBlockLayout(false);
2460}
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002461
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002462
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002463llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2464 QualType T) {
2465 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2466 assert(!T->isArrayType() && "__block array variable should not be caught");
2467 CharUnits fieldOffset;
2468 RunSkipBlockVars.clear();
2469 bool hasUnion = false;
2470 if (const RecordType *record = T->getAs<RecordType>()) {
2471 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
2472 llvm::Constant *Result = getBitmapBlockLayout(true);
2473 return Result;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002474 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002475 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2476 return nullPtr;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002477}
2478
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002479llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00002480 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00002481 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002482 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00002483 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2484
Owen Andersonade90fd2009-07-29 18:54:39 +00002485 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00002486 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002487}
2488
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002489void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00002490 // FIXME: We shouldn't need this, the protocol decl should contain enough
2491 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00002492 DefinedProtocols.insert(PD->getIdentifier());
2493
2494 // If we have generated a forward reference to this protocol, emit
2495 // it now. Otherwise do nothing, the protocol objects are lazily
2496 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002497 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00002498 GetOrEmitProtocol(PD);
2499}
2500
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002501llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002502 if (DefinedProtocols.count(PD->getIdentifier()))
2503 return GetOrEmitProtocol(PD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002504
Daniel Dunbarc475d422008-10-29 22:36:39 +00002505 return GetOrEmitProtocolRef(PD);
2506}
2507
Daniel Dunbarb036db82008-08-13 03:21:16 +00002508/*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002509// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
2510struct _objc_protocol {
2511struct _objc_protocol_extension *isa;
2512char *protocol_name;
2513struct _objc_protocol_list *protocol_list;
2514struct _objc__method_prototype_list *instance_methods;
2515struct _objc__method_prototype_list *class_methods
2516};
Daniel Dunbarb036db82008-08-13 03:21:16 +00002517
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002518See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00002519*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00002520llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00002521 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00002522
2523 // Early exit if a defining object has already been generated.
2524 if (Entry && Entry->hasInitializer())
2525 return Entry;
2526
Douglas Gregora715bff2012-01-01 19:51:50 +00002527 // Use the protocol definition, if there is one.
2528 if (const ObjCProtocolDecl *Def = PD->getDefinition())
2529 PD = Def;
2530
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002531 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002532 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002533 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2534
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002535 // Construct method lists.
2536 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2537 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002538 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002539 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002540 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002541 ObjCMethodDecl *MD = *i;
2542 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002543 if (!C)
2544 return GetOrEmitProtocolRef(PD);
2545
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002546 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2547 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002548 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002549 } else {
2550 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002551 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002552 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002553 }
2554
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002555 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002556 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002557 ObjCMethodDecl *MD = *i;
2558 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002559 if (!C)
2560 return GetOrEmitProtocolRef(PD);
2561
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002562 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2563 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002564 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002565 } else {
2566 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002567 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002568 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002569 }
2570
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002571 MethodTypesExt.insert(MethodTypesExt.end(),
2572 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
2573
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002574 llvm::Constant *Values[] = {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002575 EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
2576 MethodTypesExt),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002577 GetClassName(PD->getIdentifier()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002578 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00002579 PD->protocol_begin(),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002580 PD->protocol_end()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002581 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002582 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002583 InstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002584 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002585 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002586 ClassMethods)
2587 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002588 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002589 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002590
Daniel Dunbarb036db82008-08-13 03:21:16 +00002591 if (Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002592 // Already created, fix the linkage and update the initializer.
2593 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002594 Entry->setInitializer(Init);
2595 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002596 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002597 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002598 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002599 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002600 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002601 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002602 // FIXME: Is this necessary? Why only for protocol?
2603 Entry->setAlignment(4);
John McCallf9582a72012-03-30 21:29:05 +00002604
2605 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002606 }
Chris Lattnerf56501c2009-07-17 23:57:13 +00002607 CGM.AddUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00002608
2609 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002610}
2611
Daniel Dunbarc475d422008-10-29 22:36:39 +00002612llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002613 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2614
2615 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002616 // We use the initializer as a marker of whether this is a forward
2617 // reference or not. At module finalization we add the empty
2618 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002619 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002620 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarc475d422008-10-29 22:36:39 +00002621 llvm::GlobalValue::ExternalLinkage,
2622 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002623 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002624 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002625 // FIXME: Is this necessary? Why only for protocol?
2626 Entry->setAlignment(4);
2627 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002628
Daniel Dunbarb036db82008-08-13 03:21:16 +00002629 return Entry;
2630}
2631
2632/*
2633 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002634 uint32_t size;
2635 struct objc_method_description_list *optional_instance_methods;
2636 struct objc_method_description_list *optional_class_methods;
2637 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002638 const char ** extendedMethodTypes;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002639 };
2640*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002641llvm::Constant *
2642CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002643 ArrayRef<llvm::Constant*> OptInstanceMethods,
2644 ArrayRef<llvm::Constant*> OptClassMethods,
2645 ArrayRef<llvm::Constant*> MethodTypesExt) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002646 uint64_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002647 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002648 llvm::Constant *Values[] = {
2649 llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002650 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002651 + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002652 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002653 OptInstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002654 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002655 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002656 OptClassMethods),
2657 EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002658 ObjCTypes),
2659 EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
2660 MethodTypesExt, ObjCTypes)
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002661 };
Daniel Dunbarb036db82008-08-13 03:21:16 +00002662
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002663 // Return null if no extension bits are used.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002664 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002665 Values[3]->isNullValue() && Values[4]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002666 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002667
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002668 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002669 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002670
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002671 // No special section, but goes in llvm.used
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002672 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002673 Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002674 0, 0, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002675}
2676
2677/*
2678 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002679 struct objc_protocol_list *next;
2680 long count;
2681 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002682 };
2683*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00002684llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002685CGObjCMac::EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00002686 ObjCProtocolDecl::protocol_iterator begin,
2687 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendlinga515b582012-02-09 22:16:49 +00002688 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002689
Daniel Dunbardec75f82008-08-21 21:57:41 +00002690 for (; begin != end; ++begin)
2691 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002692
2693 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002694 if (ProtocolRefs.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002695 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002696
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002697 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00002698 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002699
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002700 llvm::Constant *Values[3];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002701 // This field is only used by the runtime.
Owen Anderson0b75f232009-07-31 20:28:54 +00002702 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002703 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002704 ProtocolRefs.size() - 1);
2705 Values[2] =
2706 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
2707 ProtocolRefs.size()),
Daniel Dunbarb036db82008-08-13 03:21:16 +00002708 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002709
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002710 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002711 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002712 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002713 4, false);
Owen Andersonade90fd2009-07-29 18:54:39 +00002714 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002715}
2716
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002717void CGObjCCommonMac::
2718PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
Bill Wendlinga515b582012-02-09 22:16:49 +00002719 llvm::SmallVectorImpl<llvm::Constant*> &Properties,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002720 const Decl *Container,
2721 const ObjCProtocolDecl *PROTO,
2722 const ObjCCommonTypesHelper &ObjCTypes) {
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002723 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
2724 E = PROTO->protocol_end(); P != E; ++P)
2725 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
2726 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
2727 E = PROTO->prop_end(); I != E; ++I) {
David Blaikie40ed2972012-06-06 20:45:41 +00002728 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002729 if (!PropertySet.insert(PD->getIdentifier()))
2730 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002731 llvm::Constant *Prop[] = {
2732 GetPropertyName(PD->getIdentifier()),
2733 GetPropertyTypeString(PD, Container)
2734 };
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002735 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
2736 }
2737}
2738
Daniel Dunbarb036db82008-08-13 03:21:16 +00002739/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002740 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00002741 const char * const name;
2742 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002743 };
2744
2745 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002746 uint32_t entsize; // sizeof (struct _objc_property)
2747 uint32_t prop_count;
2748 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002749 };
2750*/
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002751llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002752 const Decl *Container,
2753 const ObjCContainerDecl *OCD,
2754 const ObjCCommonTypesHelper &ObjCTypes) {
Bill Wendlinga515b582012-02-09 22:16:49 +00002755 llvm::SmallVector<llvm::Constant*, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002756 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002757 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2758 E = OCD->prop_end(); I != E; ++I) {
David Blaikie40ed2972012-06-06 20:45:41 +00002759 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002760 PropertySet.insert(PD->getIdentifier());
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002761 llvm::Constant *Prop[] = {
2762 GetPropertyName(PD->getIdentifier()),
2763 GetPropertyTypeString(PD, Container)
2764 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002765 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002766 Prop));
2767 }
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002768 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002769 for (ObjCInterfaceDecl::all_protocol_iterator
2770 P = OID->all_referenced_protocol_begin(),
2771 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002772 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2773 ObjCTypes);
2774 }
2775 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2776 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
2777 E = CD->protocol_end(); P != E; ++P)
2778 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2779 ObjCTypes);
2780 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002781
2782 // Return null for empty list.
2783 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002784 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002785
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002786 unsigned PropertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002787 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002788 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002789 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2790 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002791 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002792 Properties.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002793 Values[2] = llvm::ConstantArray::get(AT, Properties);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002794 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002795
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002796 llvm::GlobalVariable *GV =
2797 CreateMetadataVar(Name, Init,
2798 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002799 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002800 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002801 true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002802 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002803}
2804
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002805llvm::Constant *
2806CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
2807 ArrayRef<llvm::Constant*> MethodTypes,
2808 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002809 // Return null for empty list.
2810 if (MethodTypes.empty())
2811 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
2812
2813 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
2814 MethodTypes.size());
2815 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
2816
2817 llvm::GlobalVariable *GV =
2818 CreateMetadataVar(Name, Init,
2819 (ObjCABI == 2) ? "__DATA, __objc_const" : 0,
2820 (ObjCABI == 2) ? 8 : 4,
2821 true);
2822 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
2823}
2824
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002825/*
Daniel Dunbarb036db82008-08-13 03:21:16 +00002826 struct objc_method_description_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002827 int count;
2828 struct objc_method_description list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002829 };
2830*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002831llvm::Constant *
2832CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002833 llvm::Constant *Desc[] = {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002834 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002835 ObjCTypes.SelectorPtrTy),
2836 GetMethodVarType(MD)
2837 };
Douglas Gregora9d84932011-05-27 01:19:52 +00002838 if (!Desc[1])
2839 return 0;
2840
Owen Anderson0e0189d2009-07-27 22:29:56 +00002841 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002842 Desc);
2843}
Daniel Dunbarb036db82008-08-13 03:21:16 +00002844
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002845llvm::Constant *
2846CGObjCMac::EmitMethodDescList(Twine Name, const char *Section,
2847 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002848 // Return null for empty list.
2849 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002850 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002851
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002852 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002853 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002854 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002855 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002856 Values[1] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002857 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002858
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002859 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002860 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002861 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002862}
2863
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002864/*
2865 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002866 char *category_name;
2867 char *class_name;
2868 struct _objc_method_list *instance_methods;
2869 struct _objc_method_list *class_methods;
2870 struct _objc_protocol_list *protocols;
2871 uint32_t size; // <rdar://4585769>
2872 struct _objc_property_list *instance_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002873 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002874*/
Daniel Dunbar92992502008-08-15 22:20:32 +00002875void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00002876 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002877
Mike Stump18bb9282009-05-16 07:57:57 +00002878 // FIXME: This is poor design, the OCD should have a pointer to the category
2879 // decl. Additionally, note that Category can be null for the @implementation
2880 // w/o an @interface case. Sema should just create one for us as it does for
2881 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002882 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002883 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002884 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002885
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002886 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002887 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2888 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002889
Bill Wendlinga515b582012-02-09 22:16:49 +00002890 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002891 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002892 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002893 // Instance methods should always be defined.
2894 InstanceMethods.push_back(GetMethodConstant(*i));
2895 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002896 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002897 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002898 // Class methods should always be defined.
2899 ClassMethods.push_back(GetMethodConstant(*i));
2900 }
2901
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002902 llvm::Constant *Values[7];
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002903 Values[0] = GetClassName(OCD->getIdentifier());
2904 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00002905 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002906 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002907 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002908 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002909 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002910 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002911 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002912 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002913 ClassMethods);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002914 if (Category) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002915 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002916 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002917 Category->protocol_begin(),
2918 Category->protocol_end());
2919 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002920 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002921 }
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002922 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002923
2924 // If there is no category @interface then there can be no properties.
2925 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002926 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002927 OCD, Category, ObjCTypes);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002928 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002929 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002930 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002931
Owen Anderson0e0189d2009-07-27 22:29:56 +00002932 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002933 Values);
2934
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002935 llvm::GlobalVariable *GV =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002936 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002937 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002938 4, true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002939 DefinedCategories.push_back(GV);
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00002940 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002941 // method definition entries must be clear for next implementation.
2942 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002943}
2944
John McCallef19dbb2012-10-17 04:53:23 +00002945enum FragileClassFlags {
2946 FragileABI_Class_Factory = 0x00001,
2947 FragileABI_Class_Meta = 0x00002,
2948 FragileABI_Class_HasCXXStructors = 0x02000,
2949 FragileABI_Class_Hidden = 0x20000
2950};
2951
2952enum NonFragileClassFlags {
2953 /// Is a meta-class.
2954 NonFragileABI_Class_Meta = 0x00001,
2955
2956 /// Is a root class.
2957 NonFragileABI_Class_Root = 0x00002,
2958
2959 /// Has a C++ constructor and destructor.
2960 NonFragileABI_Class_HasCXXStructors = 0x00004,
2961
2962 /// Has hidden visibility.
2963 NonFragileABI_Class_Hidden = 0x00010,
2964
2965 /// Has the exception attribute.
2966 NonFragileABI_Class_Exception = 0x00020,
2967
2968 /// (Obsolete) ARC-specific: this class has a .release_ivars method
2969 NonFragileABI_Class_HasIvarReleaser = 0x00040,
2970
2971 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00002972 NonFragileABI_Class_CompiledByARC = 0x00080,
2973
2974 /// Class has non-trivial destructors, but zero-initialization is okay.
2975 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002976};
2977
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002978/*
2979 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002980 Class isa;
2981 Class super_class;
2982 const char *name;
2983 long version;
2984 long info;
2985 long instance_size;
2986 struct _objc_ivar_list *ivars;
2987 struct _objc_method_list *methods;
2988 struct _objc_cache *cache;
2989 struct _objc_protocol_list *protocols;
2990 // Objective-C 1.0 extensions (<rdr://4585769>)
2991 const char *ivar_layout;
2992 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002993 };
2994
2995 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002996*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002997void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002998 DefinedSymbols.insert(ID->getIdentifier());
2999
Chris Lattner86d7d912008-11-24 03:54:41 +00003000 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003001 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003002 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003003 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003004 llvm::Constant *Protocols =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003005 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003006 Interface->all_referenced_protocol_begin(),
3007 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00003008 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00003009 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00003010 Flags |= FragileABI_Class_HasCXXStructors;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003011 unsigned Size =
Ken Dyckc8ae5502011-02-09 01:59:34 +00003012 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003013
3014 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00003015 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003016 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003017
Bill Wendlinga515b582012-02-09 22:16:49 +00003018 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003019 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003020 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003021 // Instance methods should always be defined.
3022 InstanceMethods.push_back(GetMethodConstant(*i));
3023 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003024 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003025 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003026 // Class methods should always be defined.
3027 ClassMethods.push_back(GetMethodConstant(*i));
3028 }
3029
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003030 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003031 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie40ed2972012-06-06 20:45:41 +00003032 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003033
3034 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3035 ObjCPropertyDecl *PD = PID->getPropertyDecl();
3036
3037 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
3038 if (llvm::Constant *C = GetMethodConstant(MD))
3039 InstanceMethods.push_back(C);
3040 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
3041 if (llvm::Constant *C = GetMethodConstant(MD))
3042 InstanceMethods.push_back(C);
3043 }
3044 }
3045
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003046 llvm::Constant *Values[12];
Daniel Dunbarccf61832009-05-03 08:56:52 +00003047 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003048 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003049 // Record a reference to the super class.
3050 LazySymbols.insert(Super->getIdentifier());
3051
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003052 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003053 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003054 ObjCTypes.ClassPtrTy);
3055 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00003056 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003057 }
3058 Values[ 2] = GetClassName(ID->getIdentifier());
3059 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003060 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3061 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3062 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003063 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003064 Values[ 7] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003065 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003066 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003067 InstanceMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003068 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003069 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003070 Values[ 9] = Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003071 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003072 Values[11] = EmitClassExtension(ID);
Owen Anderson0e0189d2009-07-27 22:29:56 +00003073 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003074 Values);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003075 std::string Name("\01L_OBJC_CLASS_");
3076 Name += ClassName;
3077 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3078 // Check for a forward reference.
3079 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
3080 if (GV) {
3081 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3082 "Forward metaclass reference has incorrect type.");
3083 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
3084 GV->setInitializer(Init);
3085 GV->setSection(Section);
3086 GV->setAlignment(4);
3087 CGM.AddUsedGlobal(GV);
3088 }
3089 else
3090 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003091 DefinedClasses.push_back(GV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003092 // method definition entries must be clear for next implementation.
3093 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003094}
3095
3096llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3097 llvm::Constant *Protocols,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003098 ArrayRef<llvm::Constant*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00003099 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00003100 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003101
John McCall457a04e2010-10-22 21:05:15 +00003102 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003103 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003104
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003105 llvm::Constant *Values[12];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003106 // The isa for the metaclass is the root of the hierarchy.
3107 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3108 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3109 Root = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003110 Values[ 0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003111 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003112 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003113 // The super class for the metaclass is emitted as the name of the
3114 // super class. The runtime fixes this up to point to the
3115 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003116 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003117 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003118 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003119 ObjCTypes.ClassPtrTy);
3120 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00003121 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003122 }
3123 Values[ 2] = GetClassName(ID->getIdentifier());
3124 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003125 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3126 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3127 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003128 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003129 Values[ 7] =
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00003130 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003131 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003132 Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003133 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003134 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003135 Values[ 9] = Protocols;
3136 // ivar_layout for metaclass is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003137 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003138 // The class extension is always unused for metaclasses.
Owen Anderson0b75f232009-07-31 20:28:54 +00003139 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00003140 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003141 Values);
3142
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003143 std::string Name("\01L_OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00003144 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003145
3146 // Check for a forward reference.
3147 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
3148 if (GV) {
3149 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3150 "Forward metaclass reference has incorrect type.");
3151 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
3152 GV->setInitializer(Init);
3153 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00003154 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003155 llvm::GlobalValue::InternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00003156 Init, Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003157 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003158 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbarae333842009-03-09 22:18:41 +00003159 GV->setAlignment(4);
Chris Lattnerf56501c2009-07-17 23:57:13 +00003160 CGM.AddUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003161
3162 return GV;
3163}
3164
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003165llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00003166 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003167
Mike Stump18bb9282009-05-16 07:57:57 +00003168 // FIXME: Should we look these up somewhere other than the module. Its a bit
3169 // silly since we only generate these while processing an implementation, so
3170 // exactly one pointer would work if know when we entered/exitted an
3171 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003172
3173 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00003174 // Previously, metaclass with internal linkage may have been defined.
3175 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003176 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
3177 true)) {
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003178 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3179 "Forward metaclass reference has incorrect type.");
3180 return GV;
3181 } else {
3182 // Generate as an external reference to keep a consistent
3183 // module. This will be patched up when we emit the metaclass.
Owen Andersonc10c8d32009-07-08 19:05:04 +00003184 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003185 llvm::GlobalValue::ExternalLinkage,
3186 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00003187 Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003188 }
3189}
3190
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003191llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
3192 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
3193
3194 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
3195 true)) {
3196 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3197 "Forward class metadata reference has incorrect type.");
3198 return GV;
3199 } else {
3200 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
3201 llvm::GlobalValue::ExternalLinkage,
3202 0,
3203 Name);
3204 }
3205}
3206
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003207/*
3208 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003209 uint32_t size;
3210 const char *weak_ivar_layout;
3211 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003212 };
3213*/
3214llvm::Constant *
3215CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003216 uint64_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00003217 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003218
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003219 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003220 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian6df69862009-04-22 23:00:43 +00003221 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003222 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00003223 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003224
3225 // Return null if no extension bits are used.
3226 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00003227 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003228
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003229 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00003230 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003231 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003232 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003233 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003234}
3235
3236/*
3237 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003238 char *ivar_name;
3239 char *ivar_type;
3240 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003241 };
3242
3243 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003244 int ivar_count;
3245 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003246 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003247*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003248llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003249 bool ForClass) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003250 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003251
3252 // When emitting the root class GCC emits ivar entries for the
3253 // actual class structure. It is not clear if we need to follow this
3254 // behavior; for now lets try and get away with not doing it. If so,
3255 // the cleanest solution would be to make up an ObjCInterfaceDecl
3256 // for the class.
3257 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00003258 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003259
Jordy Rosea91768e2011-07-22 02:08:32 +00003260 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003261
Jordy Rosea91768e2011-07-22 02:08:32 +00003262 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00003263 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00003264 // Ignore unnamed bit-fields.
3265 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003266 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003267 llvm::Constant *Ivar[] = {
3268 GetMethodVarName(IVD->getIdentifier()),
3269 GetMethodVarType(IVD),
3270 llvm::ConstantInt::get(ObjCTypes.IntTy,
Eli Friedman8cbca202012-11-06 22:15:52 +00003271 ComputeIvarBaseOffset(CGM, OID, IVD))
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003272 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00003273 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003274 }
3275
3276 // Return null for empty list.
3277 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003278 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003279
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003280 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003281 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00003282 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003283 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00003284 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003285 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003286
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003287 llvm::GlobalVariable *GV;
3288 if (ForClass)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003289 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003290 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003291 4, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003292 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003293 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003294 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003295 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003296 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003297}
3298
3299/*
3300 struct objc_method {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003301 SEL method_name;
3302 char *method_types;
3303 void *method;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003304 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003305
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003306 struct objc_method_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003307 struct objc_method_list *obsolete;
3308 int count;
3309 struct objc_method methods_list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003310 };
3311*/
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003312
3313/// GetMethodConstant - Return a struct objc_method constant for the
3314/// given method if it has been defined. The result is null if the
3315/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003316llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00003317 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003318 if (!Fn)
3319 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003320
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003321 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00003322 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003323 ObjCTypes.SelectorPtrTy),
3324 GetMethodVarType(MD),
3325 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
3326 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00003327 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003328}
3329
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003330llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003331 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003332 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003333 // Return null for empty list.
3334 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003335 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003336
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003337 llvm::Constant *Values[3];
Owen Anderson0b75f232009-07-31 20:28:54 +00003338 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003339 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00003340 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003341 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00003342 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003343 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003344
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003345 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003346 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003347}
3348
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00003349llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003350 const ObjCContainerDecl *CD) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003351 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00003352 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003353
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00003354 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00003355 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00003356 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003357 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00003358 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003359 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00003360 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003361 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003362 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003363
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003364 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003365}
3366
Daniel Dunbar30c65362009-03-09 20:09:19 +00003367llvm::GlobalVariable *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003368CGObjCCommonMac::CreateMetadataVar(Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00003369 llvm::Constant *Init,
3370 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003371 unsigned Align,
3372 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003373 llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003374 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00003375 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerf56501c2009-07-17 23:57:13 +00003376 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003377 if (Section)
3378 GV->setSection(Section);
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003379 if (Align)
3380 GV->setAlignment(Align);
3381 if (AddToUsed)
Chris Lattnerf56501c2009-07-17 23:57:13 +00003382 CGM.AddUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003383 return GV;
3384}
3385
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003386llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003387 // Abuse this interface function as a place to finalize.
3388 FinishModule();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003389 return NULL;
3390}
3391
Chris Lattnerd4808922009-03-22 21:03:39 +00003392llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003393 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003394}
3395
Chris Lattnerd4808922009-03-22 21:03:39 +00003396llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003397 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003398}
3399
Ted Kremeneke65b0862012-03-06 20:05:56 +00003400llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3401 bool copy) {
3402 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3403}
3404
David Chisnall168b80f2010-12-26 22:13:16 +00003405llvm::Constant *CGObjCMac::GetGetStructFunction() {
3406 return ObjCTypes.getCopyStructFn();
3407}
3408llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00003409 return ObjCTypes.getCopyStructFn();
3410}
3411
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00003412llvm::Constant *CGObjCMac::GetCppAtomicObjectFunction() {
3413 return ObjCTypes.getCppAtomicObjectFunction();
3414}
3415
Chris Lattnerd4808922009-03-22 21:03:39 +00003416llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003417 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00003418}
3419
John McCallbd309292010-07-06 01:34:17 +00003420void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
3421 return EmitTryOrSynchronizedStmt(CGF, S);
3422}
3423
3424void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
3425 const ObjCAtSynchronizedStmt &S) {
3426 return EmitTryOrSynchronizedStmt(CGF, S);
3427}
3428
John McCall65bea082010-07-21 06:59:36 +00003429namespace {
John McCallcda666c2010-07-21 07:22:38 +00003430 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00003431 const Stmt &S;
John McCall2dd7d442010-08-04 05:59:32 +00003432 llvm::Value *SyncArgSlot;
John McCall65bea082010-07-21 06:59:36 +00003433 llvm::Value *CallTryExitVar;
3434 llvm::Value *ExceptionData;
3435 ObjCTypesHelper &ObjCTypes;
3436 PerformFragileFinally(const Stmt *S,
John McCall2dd7d442010-08-04 05:59:32 +00003437 llvm::Value *SyncArgSlot,
John McCall65bea082010-07-21 06:59:36 +00003438 llvm::Value *CallTryExitVar,
3439 llvm::Value *ExceptionData,
3440 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00003441 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00003442 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
3443
John McCall30317fd2011-07-12 20:27:29 +00003444 void Emit(CodeGenFunction &CGF, Flags flags) {
John McCall65bea082010-07-21 06:59:36 +00003445 // Check whether we need to call objc_exception_try_exit.
3446 // In optimized code, this branch will always be folded.
3447 llvm::BasicBlock *FinallyCallExit =
3448 CGF.createBasicBlock("finally.call_exit");
3449 llvm::BasicBlock *FinallyNoCallExit =
3450 CGF.createBasicBlock("finally.no_call_exit");
3451 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
3452 FinallyCallExit, FinallyNoCallExit);
3453
3454 CGF.EmitBlock(FinallyCallExit);
3455 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
3456 ->setDoesNotThrow();
3457
3458 CGF.EmitBlock(FinallyNoCallExit);
3459
3460 if (isa<ObjCAtTryStmt>(S)) {
3461 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00003462 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
3463 // Save the current cleanup destination in case there's
3464 // control flow inside the finally statement.
3465 llvm::Value *CurCleanupDest =
3466 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
3467
John McCall65bea082010-07-21 06:59:36 +00003468 CGF.EmitStmt(FinallyStmt->getFinallyBody());
3469
John McCallcebe0ca2010-08-11 00:16:14 +00003470 if (CGF.HaveInsertPoint()) {
3471 CGF.Builder.CreateStore(CurCleanupDest,
3472 CGF.getNormalCleanupDestSlot());
3473 } else {
3474 // Currently, the end of the cleanup must always exist.
3475 CGF.EnsureInsertPoint();
3476 }
3477 }
John McCall65bea082010-07-21 06:59:36 +00003478 } else {
3479 // Emit objc_sync_exit(expr); as finally's sole statement for
3480 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00003481 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall65bea082010-07-21 06:59:36 +00003482 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
3483 ->setDoesNotThrow();
3484 }
3485 }
3486 };
John McCall42227ed2010-07-31 23:20:56 +00003487
3488 class FragileHazards {
3489 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003490 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00003491 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
3492
3493 llvm::InlineAsm *ReadHazard;
3494 llvm::InlineAsm *WriteHazard;
3495
3496 llvm::FunctionType *GetAsmFnType();
3497
3498 void collectLocals();
3499 void emitReadHazard(CGBuilderTy &Builder);
3500
3501 public:
3502 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00003503
John McCall42227ed2010-07-31 23:20:56 +00003504 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00003505 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003506 };
3507}
3508
3509/// Create the fragile-ABI read and write hazards based on the current
3510/// state of the function, which is presumed to be immediately prior
3511/// to a @try block. These hazards are used to maintain correct
3512/// semantics in the face of optimization and the fragile ABI's
3513/// cavalier use of setjmp/longjmp.
3514FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
3515 collectLocals();
3516
3517 if (Locals.empty()) return;
3518
3519 // Collect all the blocks in the function.
3520 for (llvm::Function::iterator
3521 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
3522 BlocksBeforeTry.insert(&*I);
3523
3524 llvm::FunctionType *AsmFnTy = GetAsmFnType();
3525
3526 // Create a read hazard for the allocas. This inhibits dead-store
3527 // optimizations and forces the values to memory. This hazard is
3528 // inserted before any 'throwing' calls in the protected scope to
3529 // reflect the possibility that the variables might be read from the
3530 // catch block if the call throws.
3531 {
3532 std::string Constraint;
3533 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3534 if (I) Constraint += ',';
3535 Constraint += "*m";
3536 }
3537
3538 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3539 }
3540
3541 // Create a write hazard for the allocas. This inhibits folding
3542 // loads across the hazard. This hazard is inserted at the
3543 // beginning of the catch path to reflect the possibility that the
3544 // variables might have been written within the protected scope.
3545 {
3546 std::string Constraint;
3547 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3548 if (I) Constraint += ',';
3549 Constraint += "=*m";
3550 }
3551
3552 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3553 }
3554}
3555
3556/// Emit a write hazard at the current location.
3557void FragileHazards::emitWriteHazard() {
3558 if (Locals.empty()) return;
3559
Jay Foad5bd375a2011-07-15 08:37:34 +00003560 CGF.Builder.CreateCall(WriteHazard, Locals)->setDoesNotThrow();
John McCall42227ed2010-07-31 23:20:56 +00003561}
3562
John McCall42227ed2010-07-31 23:20:56 +00003563void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
3564 assert(!Locals.empty());
Jay Foad5bd375a2011-07-15 08:37:34 +00003565 Builder.CreateCall(ReadHazard, Locals)->setDoesNotThrow();
John McCall42227ed2010-07-31 23:20:56 +00003566}
3567
3568/// Emit read hazards in all the protected blocks, i.e. all the blocks
3569/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00003570void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00003571 if (Locals.empty()) return;
3572
3573 CGBuilderTy Builder(CGF.getLLVMContext());
3574
3575 // Iterate through all blocks, skipping those prior to the try.
3576 for (llvm::Function::iterator
3577 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
3578 llvm::BasicBlock &BB = *FI;
3579 if (BlocksBeforeTry.count(&BB)) continue;
3580
3581 // Walk through all the calls in the block.
3582 for (llvm::BasicBlock::iterator
3583 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
3584 llvm::Instruction &I = *BI;
3585
3586 // Ignore instructions that aren't non-intrinsic calls.
3587 // These are the only calls that can possibly call longjmp.
3588 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
3589 if (isa<llvm::IntrinsicInst>(I))
3590 continue;
3591
3592 // Ignore call sites marked nounwind. This may be questionable,
3593 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
3594 llvm::CallSite CS(&I);
3595 if (CS.doesNotThrow()) continue;
3596
John McCall2dd7d442010-08-04 05:59:32 +00003597 // Insert a read hazard before the call. This will ensure that
3598 // any writes to the locals are performed before making the
3599 // call. If the call throws, then this is sufficient to
3600 // guarantee correctness as long as it doesn't also write to any
3601 // locals.
John McCall42227ed2010-07-31 23:20:56 +00003602 Builder.SetInsertPoint(&BB, BI);
3603 emitReadHazard(Builder);
3604 }
3605 }
3606}
3607
3608static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
3609 if (V) S.insert(V);
3610}
3611
3612void FragileHazards::collectLocals() {
3613 // Compute a set of allocas to ignore.
3614 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
3615 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
3616 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00003617
3618 // Collect all the allocas currently in the function. This is
3619 // probably way too aggressive.
3620 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
3621 for (llvm::BasicBlock::iterator
3622 I = Entry.begin(), E = Entry.end(); I != E; ++I)
3623 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
3624 Locals.push_back(&*I);
3625}
3626
3627llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003628 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00003629 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
3630 tys[i] = Locals[i]->getType();
3631 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00003632}
3633
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003634/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003635
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003636 Objective-C setjmp-longjmp (sjlj) Exception Handling
3637 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003638
John McCallbd309292010-07-06 01:34:17 +00003639 A catch buffer is a setjmp buffer plus:
3640 - a pointer to the exception that was caught
3641 - a pointer to the previous exception data buffer
3642 - two pointers of reserved storage
3643 Therefore catch buffers form a stack, with a pointer to the top
3644 of the stack kept in thread-local storage.
3645
3646 objc_exception_try_enter pushes a catch buffer onto the EH stack.
3647 objc_exception_try_exit pops the given catch buffer, which is
3648 required to be the top of the EH stack.
3649 objc_exception_throw pops the top of the EH stack, writes the
3650 thrown exception into the appropriate field, and longjmps
3651 to the setjmp buffer. It crashes the process (with a printf
3652 and an abort()) if there are no catch buffers on the stack.
3653 objc_exception_extract just reads the exception pointer out of the
3654 catch buffer.
3655
3656 There's no reason an implementation couldn't use a light-weight
3657 setjmp here --- something like __builtin_setjmp, but API-compatible
3658 with the heavyweight setjmp. This will be more important if we ever
3659 want to implement correct ObjC/C++ exception interactions for the
3660 fragile ABI.
3661
3662 Note that for this use of setjmp/longjmp to be correct, we may need
3663 to mark some local variables volatile: if a non-volatile local
3664 variable is modified between the setjmp and the longjmp, it has
3665 indeterminate value. For the purposes of LLVM IR, it may be
3666 sufficient to make loads and stores within the @try (to variables
3667 declared outside the @try) volatile. This is necessary for
3668 optimized correctness, but is not currently being done; this is
3669 being tracked as rdar://problem/8160285
3670
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003671 The basic framework for a @try-catch-finally is as follows:
3672 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003673 objc_exception_data d;
3674 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00003675 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003676
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003677 objc_exception_try_enter(&d);
3678 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003679 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003680 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003681 // exception path
3682 id _caught = objc_exception_extract(&d);
3683
3684 // enter new try scope for handlers
3685 if (!setjmp(d.jmp_buf)) {
3686 ... match exception and execute catch blocks ...
3687
3688 // fell off end, rethrow.
3689 _rethrow = _caught;
3690 ... jump-through-finally to finally_rethrow ...
3691 } else {
3692 // exception in catch block
3693 _rethrow = objc_exception_extract(&d);
3694 _call_try_exit = false;
3695 ... jump-through-finally to finally_rethrow ...
3696 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003697 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003698 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003699
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003700 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00003701 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003702 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00003703
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003704 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003705 ... dispatch to finally destination ...
3706
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003707 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003708 objc_exception_throw(_rethrow);
3709
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003710 finally_end:
3711 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003712
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003713 This framework differs slightly from the one gcc uses, in that gcc
3714 uses _rethrow to determine if objc_exception_try_exit should be called
3715 and if the object should be rethrown. This breaks in the face of
3716 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003717
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003718 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003719
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003720 - If there are no catch blocks, then we avoid emitting the second
3721 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003722
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003723 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
3724 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003725
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003726 - FIXME: If there is no @finally block we can do a few more
3727 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003728
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003729 Rethrows and Jumps-Through-Finally
3730 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003731
John McCallbd309292010-07-06 01:34:17 +00003732 '@throw;' is supported by pushing the currently-caught exception
3733 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003734
John McCallbd309292010-07-06 01:34:17 +00003735 Branches through the @finally block are handled with an ordinary
3736 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
3737 exceptions are not compatible with C++ exceptions, and this is
3738 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003739
John McCallbd309292010-07-06 01:34:17 +00003740 @synchronized(expr) { stmt; } is emitted as if it were:
3741 id synch_value = expr;
3742 objc_sync_enter(synch_value);
3743 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003744*/
3745
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00003746void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
3747 const Stmt &S) {
3748 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00003749
3750 // A destination for the fall-through edges of the catch handlers to
3751 // jump to.
3752 CodeGenFunction::JumpDest FinallyEnd =
3753 CGF.getJumpDestInCurrentScope("finally.end");
3754
3755 // A destination for the rethrow edge of the catch handlers to jump
3756 // to.
3757 CodeGenFunction::JumpDest FinallyRethrow =
3758 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003759
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003760 // For @synchronized, call objc_sync_enter(sync.expr). The
3761 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00003762 // @synchronized. We can't avoid a temp here because we need the
3763 // value to be preserved. If the backend ever does liveness
3764 // correctly after setjmp, this will be unnecessary.
3765 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003766 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00003767 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003768 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
3769 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallbd309292010-07-06 01:34:17 +00003770 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
3771 ->setDoesNotThrow();
John McCall2dd7d442010-08-04 05:59:32 +00003772
3773 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
3774 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003775 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003776
John McCall2dd7d442010-08-04 05:59:32 +00003777 // Allocate memory for the setjmp buffer. This needs to be kept
3778 // live throughout the try and catch blocks.
3779 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
3780 "exceptiondata.ptr");
3781
John McCall42227ed2010-07-31 23:20:56 +00003782 // Create the fragile hazards. Note that this will not capture any
3783 // of the allocas required for exception processing, but will
3784 // capture the current basic block (which extends all the way to the
3785 // setjmp call) as "before the @try".
3786 FragileHazards Hazards(CGF);
3787
John McCallbd309292010-07-06 01:34:17 +00003788 // Create a flag indicating whether the cleanup needs to call
3789 // objc_exception_try_exit. This is true except when
3790 // - no catches match and we're branching through the cleanup
3791 // just to rethrow the exception, or
3792 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00003793 // The setjmp-safety rule here is that we should always store to this
3794 // variable in a place that dominates the branch through the cleanup
3795 // without passing through any setjmps.
John McCallbd309292010-07-06 01:34:17 +00003796 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlssonda0e4562009-02-07 21:26:04 +00003797 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003798
John McCall9916e3f2010-10-04 23:42:51 +00003799 // A slot containing the exception to rethrow. Only needed when we
3800 // have both a @catch and a @finally.
3801 llvm::Value *PropagatingExnVar = 0;
3802
John McCallbd309292010-07-06 01:34:17 +00003803 // Push a normal cleanup to leave the try scope.
John McCallcda666c2010-07-21 07:22:38 +00003804 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00003805 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00003806 CallTryExitVar,
3807 ExceptionData,
3808 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00003809
3810 // Enter a try block:
3811 // - Call objc_exception_try_enter to push ExceptionData on top of
3812 // the EH stack.
3813 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3814 ->setDoesNotThrow();
3815
3816 // - Call setjmp on the exception data buffer.
3817 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3818 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3819 llvm::Value *SetJmpBuffer =
Jay Foad040dd822011-07-22 08:16:57 +00003820 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
John McCallbd309292010-07-06 01:34:17 +00003821 llvm::CallInst *SetJmpResult =
3822 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3823 SetJmpResult->setDoesNotThrow();
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003824 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00003825
3826 // If setjmp returned 0, enter the protected block; otherwise,
3827 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00003828 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3829 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00003830 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00003831 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3832 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003833
John McCallbd309292010-07-06 01:34:17 +00003834 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003835 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00003836 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003837 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00003838 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00003839
3840 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003841
John McCallbd309292010-07-06 01:34:17 +00003842 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00003843 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003844
John McCall42227ed2010-07-31 23:20:56 +00003845 // Don't optimize loads of the in-scope locals across this point.
3846 Hazards.emitWriteHazard();
3847
John McCallbd309292010-07-06 01:34:17 +00003848 // For a @synchronized (or a @try with no catches), just branch
3849 // through the cleanup to the rethrow block.
3850 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3851 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00003852 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003853 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00003854
3855 // Otherwise, we have to match against the caught exceptions.
3856 } else {
John McCall2dd7d442010-08-04 05:59:32 +00003857 // Retrieve the exception object. We may emit multiple blocks but
3858 // nothing can cross this so the value is already in SSA form.
3859 llvm::CallInst *Caught =
3860 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3861 ExceptionData, "caught");
3862 Caught->setDoesNotThrow();
3863
John McCallbd309292010-07-06 01:34:17 +00003864 // Push the exception to rethrow onto the EH value stack for the
3865 // benefit of any @throws in the handlers.
3866 CGF.ObjCEHValueStack.push_back(Caught);
3867
Douglas Gregor96c79492010-04-23 22:50:49 +00003868 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003869
John McCall2dd7d442010-08-04 05:59:32 +00003870 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallbd309292010-07-06 01:34:17 +00003871
John McCall2dd7d442010-08-04 05:59:32 +00003872 llvm::BasicBlock *CatchBlock = 0;
3873 llvm::BasicBlock *CatchHandler = 0;
3874 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00003875 // Save the currently-propagating exception before
3876 // objc_exception_try_enter clears the exception slot.
3877 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3878 "propagating_exception");
3879 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3880
John McCall2dd7d442010-08-04 05:59:32 +00003881 // Enter a new exception try block (in case a @catch block
3882 // throws an exception).
3883 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3884 ->setDoesNotThrow();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003885
John McCall2dd7d442010-08-04 05:59:32 +00003886 llvm::CallInst *SetJmpResult =
3887 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3888 "setjmp.result");
3889 SetJmpResult->setDoesNotThrow();
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003890 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003891
John McCall2dd7d442010-08-04 05:59:32 +00003892 llvm::Value *Threw =
3893 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3894
3895 CatchBlock = CGF.createBasicBlock("catch");
3896 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3897 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3898
3899 CGF.EmitBlock(CatchBlock);
3900 }
3901
3902 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003903
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003904 // Handle catch list. As a special case we check if everything is
3905 // matched and avoid generating code for falling off the end if
3906 // so.
3907 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00003908 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3909 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003910
Douglas Gregor46a572b2010-04-26 16:46:50 +00003911 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff7cae42b2009-07-10 23:34:53 +00003912 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar523208f2008-09-27 07:36:24 +00003913
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003914 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003915 if (!CatchParam) {
3916 AllMatched = true;
3917 } else {
John McCall9dd450b2009-09-21 23:43:11 +00003918 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003919
John McCallbd309292010-07-06 01:34:17 +00003920 // catch(id e) always matches under this ABI, since only
3921 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00003922 // FIXME: For the time being we also match id<X>; this should
3923 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00003924 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003925 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003926 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003927
John McCallbd309292010-07-06 01:34:17 +00003928 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003929 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00003930 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3931
Anders Carlsson9396a892008-09-11 09:15:33 +00003932 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00003933 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003934 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00003935
3936 // These types work out because ConvertType(id) == i8*.
Steve Naroff371b8fb2009-03-03 19:52:17 +00003937 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson9396a892008-09-11 09:15:33 +00003938 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003939
Anders Carlsson9396a892008-09-11 09:15:33 +00003940 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003941
3942 // The scope of the catch variable ends right here.
3943 CatchVarCleanups.ForceCleanup();
3944
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003945 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003946 break;
3947 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003948
Steve Naroff7cae42b2009-07-10 23:34:53 +00003949 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00003950 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00003951
3952 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00003953 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3954 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003955
3956 // Check if the @catch block matches the exception object.
John McCall96fa4842010-05-17 21:00:27 +00003957 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003958
John McCallbd309292010-07-06 01:34:17 +00003959 llvm::CallInst *Match =
Chris Lattnerc6406db2009-04-22 02:26:14 +00003960 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3961 Class, Caught, "match");
John McCallbd309292010-07-06 01:34:17 +00003962 Match->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003963
John McCallbd309292010-07-06 01:34:17 +00003964 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3965 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003966
3967 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00003968 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003969
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003970 // Emit the @catch block.
3971 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00003972
3973 // Collect any cleanups for the catch variable. The scope lasts until
3974 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00003975 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00003976
John McCall1c9c3fd2010-10-15 04:57:14 +00003977 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003978 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003979
John McCallbd309292010-07-06 01:34:17 +00003980 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003981 llvm::Value *Tmp =
3982 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00003983 CGF.ConvertType(CatchParam->getType()));
Steve Naroff371b8fb2009-03-03 19:52:17 +00003984 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003985
Anders Carlsson9396a892008-09-11 09:15:33 +00003986 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003987
3988 // We're done with the catch variable.
3989 CatchVarCleanups.ForceCleanup();
3990
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003991 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003992
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003993 CGF.EmitBlock(NextCatchBlock);
3994 }
3995
John McCallbd309292010-07-06 01:34:17 +00003996 CGF.ObjCEHValueStack.pop_back();
3997
John McCall2dd7d442010-08-04 05:59:32 +00003998 // If nothing wanted anything to do with the caught exception,
3999 // kill the extract call.
4000 if (Caught->use_empty())
4001 Caught->eraseFromParent();
4002
4003 if (!AllMatched)
4004 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4005
4006 if (HasFinally) {
4007 // Emit the exception handler for the @catch blocks.
4008 CGF.EmitBlock(CatchHandler);
4009
4010 // In theory we might now need a write hazard, but actually it's
4011 // unnecessary because there's no local-accessing code between
4012 // the try's write hazard and here.
4013 //Hazards.emitWriteHazard();
4014
John McCall9916e3f2010-10-04 23:42:51 +00004015 // Extract the new exception and save it to the
4016 // propagating-exception slot.
4017 assert(PropagatingExnVar);
4018 llvm::CallInst *NewCaught =
4019 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
4020 ExceptionData, "caught");
4021 NewCaught->setDoesNotThrow();
4022 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4023
John McCall2dd7d442010-08-04 05:59:32 +00004024 // Don't pop the catch handler; the throw already did.
4025 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004026 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004027 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004028 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004029
John McCall42227ed2010-07-31 23:20:56 +00004030 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00004031 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004032
John McCallbd309292010-07-06 01:34:17 +00004033 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00004034 CGF.Builder.restoreIP(TryFallthroughIP);
4035 if (CGF.HaveInsertPoint())
4036 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00004037 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00004038 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004039
John McCallbd309292010-07-06 01:34:17 +00004040 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00004041 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00004042 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00004043 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00004044 // If we have a propagating-exception variable, check it.
4045 llvm::Value *PropagatingExn;
4046 if (PropagatingExnVar) {
4047 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00004048
John McCall9916e3f2010-10-04 23:42:51 +00004049 // Otherwise, just look in the buffer for the exception to throw.
4050 } else {
4051 llvm::CallInst *Caught =
4052 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
4053 ExceptionData);
4054 Caught->setDoesNotThrow();
4055 PropagatingExn = Caught;
4056 }
4057
4058 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallbd309292010-07-06 01:34:17 +00004059 ->setDoesNotThrow();
4060 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00004061 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004062
John McCall42227ed2010-07-31 23:20:56 +00004063 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004064}
4065
4066void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2efd5382008-09-30 01:06:03 +00004067 const ObjCAtThrowStmt &S) {
Anders Carlssone005aa12008-09-09 16:16:55 +00004068 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004069
Anders Carlssone005aa12008-09-09 16:16:55 +00004070 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00004071 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004072 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004073 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00004074 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004075 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004076 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00004077 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00004078 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004079
John McCallbd309292010-07-06 01:34:17 +00004080 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4081 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004082 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004083
4084 // Clear the insertion point to indicate we are in unreachable code.
4085 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004086}
4087
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004088/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004089/// object: objc_read_weak (id *src)
4090///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004091llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004092 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004093 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004094 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
4095 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4096 ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00004097 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004098 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00004099 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004100 return read_weak;
4101}
4102
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004103/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4104/// objc_assign_weak (id src, id *dst)
4105///
4106void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004107 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004108 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004109 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004110 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004111 assert(Size <= 8 && "does not support size > 8");
4112 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004113 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004114 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4115 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004116 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4117 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00004118 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004119 src, dst, "weakassign");
4120 return;
4121}
4122
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004123/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4124/// objc_assign_global (id src, id *dst)
4125///
4126void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00004127 llvm::Value *src, llvm::Value *dst,
4128 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004129 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004130 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004131 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004132 assert(Size <= 8 && "does not support size > 8");
4133 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004134 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004135 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4136 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004137 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4138 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00004139 if (!threadlocal)
4140 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
4141 src, dst, "globalassign");
4142 else
4143 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
4144 src, dst, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004145 return;
4146}
4147
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004148/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004149/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004150///
4151void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004152 llvm::Value *src, llvm::Value *dst,
4153 llvm::Value *ivarOffset) {
4154 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00004155 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004156 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004157 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004158 assert(Size <= 8 && "does not support size > 8");
4159 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004160 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004161 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4162 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004163 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4164 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004165 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
4166 src, dst, ivarOffset);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004167 return;
4168}
4169
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004170/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4171/// objc_assign_strongCast (id src, id *dst)
4172///
4173void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004174 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004175 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004176 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004177 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004178 assert(Size <= 8 && "does not support size > 8");
4179 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004180 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004181 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4182 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004183 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4184 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00004185 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004186 src, dst, "weakassign");
4187 return;
4188}
4189
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004190void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004191 llvm::Value *DestPtr,
4192 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004193 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004194 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4195 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004196 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004197 DestPtr, SrcPtr, size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004198 return;
4199}
4200
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004201/// EmitObjCValueForIvar - Code Gen for ivar reference.
4202///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004203LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4204 QualType ObjectTy,
4205 llvm::Value *BaseValue,
4206 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004207 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00004208 const ObjCInterfaceDecl *ID =
4209 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00004210 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4211 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004212}
4213
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004214llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00004215 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004216 const ObjCIvarDecl *Ivar) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004217 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4218 return llvm::ConstantInt::get(
4219 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
4220 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004221}
4222
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004223/* *** Private Interface *** */
4224
4225/// EmitImageInfo - Emit the image info marker used to encode some module
4226/// level information.
4227///
4228/// See: <rdr://4810609&4810587&4810587>
4229/// struct IMAGE_INFO {
4230/// unsigned version;
4231/// unsigned flags;
4232/// };
4233enum ImageInfoFlags {
Daniel Dunbar5e639272010-04-25 20:39:01 +00004234 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004235 eImageInfo_GarbageCollected = (1 << 1),
4236 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbar75e909f2009-04-20 07:11:47 +00004237 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
4238
Daniel Dunbar5e639272010-04-25 20:39:01 +00004239 // A flag indicating that the module has no instances of a @synthesize of a
4240 // superclass variable. <rdar://problem/6803242>
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004241 eImageInfo_CorrectedSynthesize = (1 << 4),
4242 eImageInfo_ImageIsSimulated = (1 << 5)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004243};
4244
Daniel Dunbar5e639272010-04-25 20:39:01 +00004245void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004246 unsigned version = 0; // Version is unused?
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004247 const char *Section = (ObjCABI == 1) ?
4248 "__OBJC, __image_info,regular" :
4249 "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004250
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004251 // Generate module-level named metadata to convey this information to the
4252 // linker and code-gen.
4253 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004254
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004255 // Add the ObjC ABI version to the module flags.
4256 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
4257 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
4258 version);
4259 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
4260 llvm::MDString::get(VMContext,Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004261
David Blaikiebbafb8a2012-03-11 07:00:24 +00004262 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004263 // Non-GC overrides those files which specify GC.
4264 Mod.addModuleFlag(llvm::Module::Override,
4265 "Objective-C Garbage Collection", (uint32_t)0);
4266 } else {
4267 // Add the ObjC garbage collection value.
4268 Mod.addModuleFlag(llvm::Module::Error,
4269 "Objective-C Garbage Collection",
4270 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004271
David Blaikiebbafb8a2012-03-11 07:00:24 +00004272 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004273 // Add the ObjC GC Only value.
4274 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
4275 eImageInfo_GCOnly);
4276
4277 // Require that GC be specified and set to eImageInfo_GarbageCollected.
4278 llvm::Value *Ops[2] = {
4279 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
4280 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
4281 eImageInfo_GarbageCollected)
4282 };
4283 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
4284 llvm::MDNode::get(VMContext, Ops));
4285 }
4286 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004287
4288 // Indicate whether we're compiling this to run on a simulator.
4289 const llvm::Triple &Triple = CGM.getTarget().getTriple();
4290 if (Triple.getOS() == llvm::Triple::IOS &&
4291 (Triple.getArch() == llvm::Triple::x86 ||
4292 Triple.getArch() == llvm::Triple::x86_64))
4293 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
4294 eImageInfo_ImageIsSimulated);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004295}
4296
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004297// struct objc_module {
4298// unsigned long version;
4299// unsigned long size;
4300// const char *name;
4301// Symtab symtab;
4302// };
4303
4304// FIXME: Get from somewhere
4305static const int ModuleVersion = 7;
4306
4307void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004308 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004309
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004310 llvm::Constant *Values[] = {
4311 llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion),
4312 llvm::ConstantInt::get(ObjCTypes.LongTy, Size),
4313 // This used to be the filename, now it is unused. <rdr://4327263>
4314 GetClassName(&CGM.getContext().Idents.get("")),
4315 EmitModuleSymbols()
4316 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004317 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson0e0189d2009-07-27 22:29:56 +00004318 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004319 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00004320 4, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004321}
4322
4323llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004324 unsigned NumClasses = DefinedClasses.size();
4325 unsigned NumCategories = DefinedCategories.size();
4326
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004327 // Return null if no symbols were defined.
4328 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00004329 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004330
Chris Lattnere64d7ba2011-06-20 04:01:35 +00004331 llvm::Constant *Values[5];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004332 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Anderson0b75f232009-07-31 20:28:54 +00004333 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004334 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
4335 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004336
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004337 // The runtime expects exactly the list of defined classes followed
4338 // by the list of defined categories, in a single array.
Chris Lattner3def9ae2012-02-06 22:16:34 +00004339 SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004340 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00004341 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004342 ObjCTypes.Int8PtrTy);
4343 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004344 Symbols[NumClasses + i] =
Owen Andersonade90fd2009-07-29 18:54:39 +00004345 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004346 ObjCTypes.Int8PtrTy);
4347
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004348 Values[4] =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004349 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00004350 Symbols.size()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004351 Symbols);
4352
Chris Lattnere64d7ba2011-06-20 04:01:35 +00004353 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004354
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004355 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004356 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
4357 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00004358 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00004359 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004360}
4361
John McCall31168b02011-06-15 23:02:42 +00004362llvm::Value *CGObjCMac::EmitClassRefFromId(CGBuilderTy &Builder,
4363 IdentifierInfo *II) {
4364 LazySymbols.insert(II);
4365
4366 llvm::GlobalVariable *&Entry = ClassReferences[II];
4367
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004368 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004369 llvm::Constant *Casted =
John McCall31168b02011-06-15 23:02:42 +00004370 llvm::ConstantExpr::getBitCast(GetClassName(II),
4371 ObjCTypes.ClassPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004372 Entry =
John McCall31168b02011-06-15 23:02:42 +00004373 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
4374 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
4375 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004376 }
John McCall31168b02011-06-15 23:02:42 +00004377
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004378 return Builder.CreateLoad(Entry);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004379}
4380
John McCall31168b02011-06-15 23:02:42 +00004381llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
4382 const ObjCInterfaceDecl *ID) {
4383 return EmitClassRefFromId(Builder, ID->getIdentifier());
4384}
4385
4386llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder) {
4387 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
4388 return EmitClassRefFromId(Builder, II);
4389}
4390
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00004391llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
4392 bool lvalue) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004393 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004394
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004395 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004396 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00004397 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004398 ObjCTypes.SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004399 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004400 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
4401 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00004402 4, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004403 }
4404
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00004405 if (lvalue)
4406 return Entry;
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004407 return Builder.CreateLoad(Entry);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004408}
4409
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004410llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00004411 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004412
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004413 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004414 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004415 llvm::ConstantDataArray::getString(VMContext,
4416 Ident->getNameStart()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004417 ((ObjCABI == 2) ?
4418 "__TEXT,__objc_classname,cstring_literals" :
4419 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004420 1, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004421
Owen Anderson170229f2009-07-14 23:10:40 +00004422 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004423}
4424
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004425llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
4426 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
4427 I = MethodDefinitions.find(MD);
4428 if (I != MethodDefinitions.end())
4429 return I->second;
4430
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004431 return NULL;
4432}
4433
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004434/// GetIvarLayoutName - Returns a unique constant for the given
4435/// ivar layout bitmap.
4436llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004437 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00004438 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004439}
4440
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004441void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Eli Friedman8cbca202012-11-06 22:15:52 +00004442 unsigned int BytePos,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004443 bool ForStrongLayout,
4444 bool &HasUnion) {
4445 const RecordDecl *RD = RT->getDecl();
4446 // FIXME - Use iterator.
David Blaikie2d7c57e2012-04-30 02:36:29 +00004447 SmallVector<const FieldDecl*, 16> Fields;
4448 for (RecordDecl::field_iterator i = RD->field_begin(),
4449 e = RD->field_end(); i != e; ++i)
David Blaikie40ed2972012-06-06 20:45:41 +00004450 Fields.push_back(*i);
Chris Lattner2192fe52011-07-18 04:24:23 +00004451 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004452 const llvm::StructLayout *RecLayout =
Micah Villmowdd31ca12012-10-08 16:25:52 +00004453 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004454
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004455 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
4456 ForStrongLayout, HasUnion);
4457}
4458
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +00004459void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004460 const llvm::StructLayout *Layout,
4461 const RecordDecl *RD,
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00004462 ArrayRef<const FieldDecl*> RecFields,
Eli Friedman8cbca202012-11-06 22:15:52 +00004463 unsigned int BytePos, bool ForStrongLayout,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004464 bool &HasUnion) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004465 bool IsUnion = (RD && RD->isUnion());
Eli Friedman8cbca202012-11-06 22:15:52 +00004466 uint64_t MaxUnionIvarSize = 0;
4467 uint64_t MaxSkippedUnionIvarSize = 0;
Jordy Rosea91768e2011-07-22 02:08:32 +00004468 const FieldDecl *MaxField = 0;
4469 const FieldDecl *MaxSkippedField = 0;
4470 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Eli Friedman8cbca202012-11-06 22:15:52 +00004471 uint64_t MaxFieldOffset = 0;
4472 uint64_t MaxSkippedFieldOffset = 0;
4473 uint64_t LastBitfieldOrUnnamedOffset = 0;
4474 uint64_t FirstFieldDelta = 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004475
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004476 if (RecFields.empty())
4477 return;
Eli Friedman8cbca202012-11-06 22:15:52 +00004478 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
Douglas Gregore8bbc122011-09-02 00:18:52 +00004479 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
David Blaikiebbafb8a2012-03-11 07:00:24 +00004480 if (!RD && CGM.getLangOpts().ObjCAutoRefCount) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004481 const FieldDecl *FirstField = RecFields[0];
4482 FirstFieldDelta =
4483 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
John McCall31168b02011-06-15 23:02:42 +00004484 }
4485
Chris Lattner5b36ddb2009-03-31 08:48:01 +00004486 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004487 const FieldDecl *Field = RecFields[i];
Eli Friedman8cbca202012-11-06 22:15:52 +00004488 uint64_t FieldOffset;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00004489 if (RD) {
Daniel Dunbard51c1a62010-04-14 17:02:21 +00004490 // Note that 'i' here is actually the field index inside RD of Field,
4491 // although this dependency is hidden.
4492 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Eli Friedman8cbca202012-11-06 22:15:52 +00004493 FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00004494 } else
John McCall31168b02011-06-15 23:02:42 +00004495 FieldOffset =
4496 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004497
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004498 // Skip over unnamed or bitfields
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004499 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004500 LastFieldBitfieldOrUnnamed = Field;
4501 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004502 continue;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004503 }
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004504
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004505 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004506 QualType FQT = Field->getType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004507 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004508 if (FQT->isUnionType())
4509 HasUnion = true;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004510
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004511 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004512 BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004513 ForStrongLayout, HasUnion);
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004514 continue;
4515 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004516
Chris Lattner5b36ddb2009-03-31 08:48:01 +00004517 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004518 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004519 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004520 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004521 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004522 FQT = CArray->getElementType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004523 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
4524 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004525 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004526 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004527 FQT = CArray->getElementType();
4528 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004529
4530 assert(!FQT->isUnionType() &&
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004531 "layout for array of unions not supported");
Fariborz Jahanian9a7d57d2011-01-03 19:23:18 +00004532 if (FQT->isRecordType() && ElCount) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004533 int OldIndex = IvarsInfo.size() - 1;
4534 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004535
Ted Kremenekc23c7e62009-07-29 21:53:49 +00004536 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004537 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004538 ForStrongLayout, HasUnion);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004539
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004540 // Replicate layout information for each array element. Note that
4541 // one element is already done.
4542 uint64_t ElIx = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004543 for (int FirstIndex = IvarsInfo.size() - 1,
4544 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004545 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004546 for (int i = OldIndex+1; i <= FirstIndex; ++i)
4547 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
4548 IvarsInfo[i].ivar_size));
4549 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
4550 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
4551 SkipIvars[i].ivar_size));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004552 }
4553 continue;
4554 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004555 }
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004556 // At this point, we are done with Record/Union and array there of.
4557 // For other arrays we are down to its element type.
John McCall8ccfcb52009-09-24 19:53:00 +00004558 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004559
Eli Friedman8cbca202012-11-06 22:15:52 +00004560 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall8ccfcb52009-09-24 19:53:00 +00004561 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
4562 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00004563 if (IsUnion) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004564 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00004565 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004566 MaxUnionIvarSize = UnionIvarSize;
4567 MaxField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004568 MaxFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004569 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00004570 } else {
Eli Friedman8cbca202012-11-06 22:15:52 +00004571 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
4572 FieldSize / WordSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004573 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004574 } else if ((ForStrongLayout &&
John McCall8ccfcb52009-09-24 19:53:00 +00004575 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
4576 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00004577 if (IsUnion) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004578 // FIXME: Why the asymmetry? We divide by word size in bits on other
4579 // side.
4580 uint64_t UnionIvarSize = FieldSize / ByteSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00004581 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004582 MaxSkippedUnionIvarSize = UnionIvarSize;
4583 MaxSkippedField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004584 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004585 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00004586 } else {
Eli Friedman8cbca202012-11-06 22:15:52 +00004587 // FIXME: Why the asymmetry, we divide by byte size in bits here?
4588 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
4589 FieldSize / ByteSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004590 }
4591 }
4592 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004593
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004594 if (LastFieldBitfieldOrUnnamed) {
4595 if (LastFieldBitfieldOrUnnamed->isBitField()) {
4596 // Last field was a bitfield. Must update skip info.
Richard Smithcaf33902011-10-10 18:28:20 +00004597 uint64_t BitFieldSize
4598 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004599 GC_IVAR skivar;
4600 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
Eli Friedman8cbca202012-11-06 22:15:52 +00004601 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
4602 + ((BitFieldSize % ByteSizeInBits) != 0);
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004603 SkipIvars.push_back(skivar);
4604 } else {
4605 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
4606 // Last field was unnamed. Must update skip info.
Eli Friedman8cbca202012-11-06 22:15:52 +00004607 unsigned FieldSize
4608 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004609 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
Eli Friedman8cbca202012-11-06 22:15:52 +00004610 FieldSize / ByteSizeInBits));
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004611 }
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004612 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004613
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004614 if (MaxField)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004615 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004616 MaxUnionIvarSize));
4617 if (MaxSkippedField)
Daniel Dunbar5b743912009-05-03 23:31:46 +00004618 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004619 MaxSkippedUnionIvarSize));
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004620}
4621
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004622/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
4623/// the computations and returning the layout bitmap (for ivar or blocks) in
4624/// the given argument BitMap string container. Routine reads
4625/// two containers, IvarsInfo and SkipIvars which are assumed to be
4626/// filled already by the caller.
Chris Lattner9c818332012-02-05 02:30:40 +00004627llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004628 unsigned int WordsToScan, WordsToSkip;
Chris Lattnerece04092012-02-07 00:39:47 +00004629 llvm::Type *PtrTy = CGM.Int8PtrTy;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004630
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004631 // Build the string of skip/scan nibbles
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004632 SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Eli Friedman8cbca202012-11-06 22:15:52 +00004633 unsigned int WordSize =
4634 CGM.getTypes().getDataLayout().getTypeAllocSize(PtrTy);
4635 if (IvarsInfo[0].ivar_bytepos == 0) {
4636 WordsToSkip = 0;
4637 WordsToScan = IvarsInfo[0].ivar_size;
4638 } else {
4639 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
4640 WordsToScan = IvarsInfo[0].ivar_size;
4641 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004642 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004643 unsigned int TailPrevGCObjC =
4644 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004645 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004646 // consecutive 'scanned' object pointers.
Eli Friedman8cbca202012-11-06 22:15:52 +00004647 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004648 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004649 // Skip over 'gc'able object pointer which lay over each other.
4650 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
4651 continue;
4652 // Must skip over 1 or more words. We save current skip/scan values
4653 // and start a new pair.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004654 SKIP_SCAN SkScan;
4655 SkScan.skip = WordsToSkip;
4656 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004657 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004658
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004659 // Skip the hole.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004660 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
4661 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004662 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004663 WordsToSkip = 0;
Eli Friedman8cbca202012-11-06 22:15:52 +00004664 WordsToScan = IvarsInfo[i].ivar_size;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004665 }
4666 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004667 if (WordsToScan > 0) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004668 SKIP_SCAN SkScan;
4669 SkScan.skip = WordsToSkip;
4670 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004671 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004672 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004673
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004674 if (!SkipIvars.empty()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004675 unsigned int LastIndex = SkipIvars.size()-1;
Eli Friedman8cbca202012-11-06 22:15:52 +00004676 int LastByteSkipped =
4677 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004678 LastIndex = IvarsInfo.size()-1;
Eli Friedman8cbca202012-11-06 22:15:52 +00004679 int LastByteScanned =
4680 IvarsInfo[LastIndex].ivar_bytepos +
4681 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004682 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramerd20ef752009-12-25 15:43:36 +00004683 if (LastByteSkipped > LastByteScanned) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004684 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004685 SKIP_SCAN SkScan;
Eli Friedman8cbca202012-11-06 22:15:52 +00004686 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004687 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004688 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004689 }
4690 }
4691 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
4692 // as 0xMN.
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004693 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004694 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004695 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
4696 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
4697 // 0xM0 followed by 0x0N detected.
4698 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
4699 for (int j = i+1; j < SkipScan; j++)
4700 SkipScanIvars[j] = SkipScanIvars[j+1];
4701 --SkipScan;
4702 }
4703 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004704
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004705 // Generate the string.
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004706 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004707 unsigned char byte;
4708 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
4709 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
4710 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
4711 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004712
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004713 // first skip big.
4714 for (unsigned int ix = 0; ix < skip_big; ix++)
4715 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004716
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004717 // next (skip small, scan)
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004718 if (skip_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004719 byte = skip_small << 4;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004720 if (scan_big > 0) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004721 byte |= 0xf;
4722 --scan_big;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004723 } else if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004724 byte |= scan_small;
4725 scan_small = 0;
4726 }
4727 BitMap += byte;
4728 }
4729 // next scan big
4730 for (unsigned int ix = 0; ix < scan_big; ix++)
4731 BitMap += (unsigned char)(0x0f);
4732 // last scan small
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004733 if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004734 byte = scan_small;
4735 BitMap += byte;
4736 }
4737 }
4738 // null terminate string.
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004739 unsigned char zero = 0;
4740 BitMap += zero;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004741
4742 llvm::GlobalVariable * Entry =
4743 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004744 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004745 ((ObjCABI == 2) ?
4746 "__TEXT,__objc_classname,cstring_literals" :
4747 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004748 1, true);
4749 return getConstantGEP(VMContext, Entry, 0, 0);
4750}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004751
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004752/// BuildIvarLayout - Builds ivar layout bitmap for the class
4753/// implementation for the __strong or __weak case.
4754/// The layout map displays which words in ivar list must be skipped
4755/// and which must be scanned by GC (see below). String is built of bytes.
4756/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
4757/// of words to skip and right nibble is count of words to scan. So, each
4758/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
4759/// represented by a 0x00 byte which also ends the string.
4760/// 1. when ForStrongLayout is true, following ivars are scanned:
4761/// - id, Class
4762/// - object *
4763/// - __strong anything
4764///
4765/// 2. When ForStrongLayout is false, following ivars are scanned:
4766/// - __weak anything
4767///
4768llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
4769 const ObjCImplementationDecl *OMD,
4770 bool ForStrongLayout) {
4771 bool hasUnion = false;
4772
Chris Lattnerece04092012-02-07 00:39:47 +00004773 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00004774 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
4775 !CGM.getLangOpts().ObjCAutoRefCount)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004776 return llvm::Constant::getNullValue(PtrTy);
4777
Jordy Rosea91768e2011-07-22 02:08:32 +00004778 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
4779 SmallVector<const FieldDecl*, 32> RecFields;
David Blaikiebbafb8a2012-03-11 07:00:24 +00004780 if (CGM.getLangOpts().ObjCAutoRefCount) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004781 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004782 IVD; IVD = IVD->getNextIvar())
4783 RecFields.push_back(cast<FieldDecl>(IVD));
4784 }
4785 else {
Jordy Rosea91768e2011-07-22 02:08:32 +00004786 SmallVector<const ObjCIvarDecl*, 32> Ivars;
John McCall31168b02011-06-15 23:02:42 +00004787 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004788
Jordy Rosea91768e2011-07-22 02:08:32 +00004789 // FIXME: This is not ideal; we shouldn't have to do this copy.
4790 RecFields.append(Ivars.begin(), Ivars.end());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004791 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004792
4793 if (RecFields.empty())
4794 return llvm::Constant::getNullValue(PtrTy);
4795
4796 SkipIvars.clear();
4797 IvarsInfo.clear();
4798
Eli Friedman8cbca202012-11-06 22:15:52 +00004799 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004800 if (IvarsInfo.empty())
4801 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004802 // Sort on byte position in case we encounterred a union nested in
4803 // the ivar list.
4804 if (hasUnion && !IvarsInfo.empty())
4805 std::sort(IvarsInfo.begin(), IvarsInfo.end());
4806 if (hasUnion && !SkipIvars.empty())
4807 std::sort(SkipIvars.begin(), SkipIvars.end());
4808
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004809 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004810 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004811
David Blaikiebbafb8a2012-03-11 07:00:24 +00004812 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004813 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004814 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar56df9772010-08-17 22:39:59 +00004815 OMD->getClassInterface()->getName().data());
Roman Divackye6377112012-09-06 15:59:27 +00004816 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00004817 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004818 if (!(s[i] & 0xf0))
4819 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
4820 else
4821 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
4822 printf("\n");
4823 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004824 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004825}
4826
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004827llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004828 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
4829
Chris Lattner3def9ae2012-02-06 22:16:34 +00004830 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004831 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004832 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004833 llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004834 ((ObjCABI == 2) ?
4835 "__TEXT,__objc_methname,cstring_literals" :
4836 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004837 1, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004838
Owen Anderson170229f2009-07-14 23:10:40 +00004839 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004840}
4841
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004842// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004843llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004844 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4845}
4846
Daniel Dunbarf5c18462009-04-20 06:54:31 +00004847llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004848 std::string TypeStr;
4849 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
4850
4851 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarb036db82008-08-13 03:21:16 +00004852
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004853 if (!Entry)
4854 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004855 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004856 ((ObjCABI == 2) ?
4857 "__TEXT,__objc_methtype,cstring_literals" :
4858 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004859 1, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004860
Owen Anderson170229f2009-07-14 23:10:40 +00004861 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004862}
4863
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004864llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
4865 bool Extended) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004866 std::string TypeStr;
Bill Wendlinge22bef72012-02-09 22:45:21 +00004867 if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
Douglas Gregora9d84932011-05-27 01:19:52 +00004868 return 0;
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004869
4870 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4871
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004872 if (!Entry)
4873 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004874 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004875 ((ObjCABI == 2) ?
4876 "__TEXT,__objc_methtype,cstring_literals" :
4877 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004878 1, true);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004879
Owen Anderson170229f2009-07-14 23:10:40 +00004880 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004881}
4882
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004883// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004884llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004885 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004886
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004887 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004888 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Chris Lattner9c818332012-02-05 02:30:40 +00004889 llvm::ConstantDataArray::getString(VMContext,
4890 Ident->getNameStart()),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004891 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004892 1, true);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004893
Owen Anderson170229f2009-07-14 23:10:40 +00004894 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004895}
4896
4897// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00004898// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004899llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004900CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4901 const Decl *Container) {
Daniel Dunbar4932b362008-08-28 04:38:10 +00004902 std::string TypeStr;
4903 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004904 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4905}
4906
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004907void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004908 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004909 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00004910 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00004911 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00004912 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4913 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004914 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00004915 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00004916 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00004917 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004918}
4919
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004920void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004921 EmitModuleInfo();
4922
Daniel Dunbarc475d422008-10-29 22:36:39 +00004923 // Emit the dummy bodies for any protocols which were referenced but
4924 // never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004925 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerf56501c2009-07-17 23:57:13 +00004926 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4927 if (I->second->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00004928 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004929
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004930 llvm::Constant *Values[5];
Owen Anderson0b75f232009-07-31 20:28:54 +00004931 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004932 Values[1] = GetClassName(I->first);
Owen Anderson0b75f232009-07-31 20:28:54 +00004933 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004934 Values[3] = Values[4] =
Owen Anderson0b75f232009-07-31 20:28:54 +00004935 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004936 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004937 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarc475d422008-10-29 22:36:39 +00004938 Values));
Chris Lattnerf56501c2009-07-17 23:57:13 +00004939 CGM.AddUsedGlobal(I->second);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004940 }
4941
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004942 // Add assembler directives to add lazy undefined symbol references
4943 // for classes which are referenced but not defined. This is
4944 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00004945 //
4946 // FIXME: It would be nice if we had an LLVM construct for this.
4947 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00004948 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00004949 Asm += CGM.getModule().getModuleInlineAsm();
4950 if (!Asm.empty() && Asm.back() != '\n')
4951 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004952
Daniel Dunbard027a922009-09-07 00:20:42 +00004953 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbard027a922009-09-07 00:20:42 +00004954 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4955 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar07d07852009-10-18 21:17:35 +00004956 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4957 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnera299f2c2010-04-17 18:26:20 +00004958 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004959 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnera299f2c2010-04-17 18:26:20 +00004960 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004961 }
4962
Bill Wendling53136852012-02-07 09:06:01 +00004963 for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) {
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004964 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4965 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4966 }
Chris Lattnera299f2c2010-04-17 18:26:20 +00004967
Daniel Dunbard027a922009-09-07 00:20:42 +00004968 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004969 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004970}
4971
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004972CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004973 : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00004974 ObjCTypes(cgm) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004975 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004976 ObjCABI = 2;
4977}
4978
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004979/* *** */
4980
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004981ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00004982 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(0)
4983{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004984 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4985 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004986
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004987 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004988 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004989 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004990 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Chris Lattnerece04092012-02-07 00:39:47 +00004991 Int8PtrTy = CGM.Int8PtrTy;
4992 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004993
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004994 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004995 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004996 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004997
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004998 // I'm not sure I like this. The implicit coordination is a bit
4999 // gross. We should solve this in a reasonable fashion because this
5000 // is a pretty common task (match some runtime data structure with
5001 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005002
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005003 // FIXME: This is leaked.
5004 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005005
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005006 // struct _objc_super {
5007 // id self;
5008 // Class cls;
5009 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00005010 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005011 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005012 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005013 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005014 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005015 Ctx.getObjCIdType(), 0, 0, false, ICIS_NoInit));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005016 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005017 Ctx.getObjCClassType(), 0, 0, false,
5018 ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005019 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005020
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005021 SuperCTy = Ctx.getTagDeclType(RD);
5022 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005023
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005024 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005025 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5026
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005027 // struct _prop_t {
5028 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005029 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005030 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005031 PropertyTy = llvm::StructType::create("struct._prop_t",
5032 Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005033
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005034 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005035 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005036 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005037 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005038 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005039 PropertyListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005040 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
5041 llvm::ArrayType::get(PropertyTy, 0), NULL);
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005042 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005043 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005044
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005045 // struct _objc_method {
5046 // SEL _cmd;
5047 // char *method_type;
5048 // char *_imp;
5049 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005050 MethodTy = llvm::StructType::create("struct._objc_method",
5051 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
5052 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005053
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005054 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00005055 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005056 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005057
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005058}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005059
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005060ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005061 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005062 // struct _objc_method_description {
5063 // SEL name;
5064 // char *types;
5065 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005066 MethodDescriptionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005067 llvm::StructType::create("struct._objc_method_description",
5068 SelectorPtrTy, Int8PtrTy, NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005069
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005070 // struct _objc_method_description_list {
5071 // int count;
5072 // struct _objc_method_description[1];
5073 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005074 MethodDescriptionListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005075 llvm::StructType::create("struct._objc_method_description_list",
5076 IntTy,
5077 llvm::ArrayType::get(MethodDescriptionTy, 0),NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005078
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005079 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005080 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005081 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005082
Daniel Dunbarb036db82008-08-13 03:21:16 +00005083 // Protocol description structures
5084
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005085 // struct _objc_protocol_extension {
5086 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5087 // struct _objc_method_description_list *optional_instance_methods;
5088 // struct _objc_method_description_list *optional_class_methods;
5089 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005090 // const char ** extendedMethodTypes;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005091 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005092 ProtocolExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005093 llvm::StructType::create("struct._objc_protocol_extension",
5094 IntTy, MethodDescriptionListPtrTy,
5095 MethodDescriptionListPtrTy, PropertyListPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005096 Int8PtrPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005097
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005098 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005099 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005100
Daniel Dunbarc475d422008-10-29 22:36:39 +00005101 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00005102
Chris Lattnera5f58b02011-07-09 17:41:47 +00005103 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005104 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00005105
Chris Lattnera5f58b02011-07-09 17:41:47 +00005106 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005107 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005108 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005109 LongTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00005110 llvm::ArrayType::get(ProtocolTy, 0),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005111 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005112
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005113 // struct _objc_protocol {
5114 // struct _objc_protocol_extension *isa;
5115 // char *protocol_name;
5116 // struct _objc_protocol **_objc_protocol_list;
5117 // struct _objc_method_description_list *instance_methods;
5118 // struct _objc_method_description_list *class_methods;
5119 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005120 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5121 llvm::PointerType::getUnqual(ProtocolListTy),
5122 MethodDescriptionListPtrTy,
5123 MethodDescriptionListPtrTy,
5124 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005125
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005126 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005127 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005128
Owen Anderson9793f0e2009-07-29 22:16:19 +00005129 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005130
5131 // Class description structures
5132
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005133 // struct _objc_ivar {
5134 // char *ivar_name;
5135 // char *ivar_type;
5136 // int ivar_offset;
5137 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005138 IvarTy = llvm::StructType::create("struct._objc_ivar",
5139 Int8PtrTy, Int8PtrTy, IntTy, NULL);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005140
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005141 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005142 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005143 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005144 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005145
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005146 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005147 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005148 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005149 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005150
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005151 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005152 ClassExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005153 llvm::StructType::create("struct._objc_class_extension",
5154 IntTy, Int8PtrTy, PropertyListPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005155 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005156
Chris Lattner5ec04a52011-08-12 17:43:31 +00005157 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005158
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005159 // struct _objc_class {
5160 // Class isa;
5161 // Class super_class;
5162 // char *name;
5163 // long version;
5164 // long info;
5165 // long instance_size;
5166 // struct _objc_ivar_list *ivars;
5167 // struct _objc_method_list *methods;
5168 // struct _objc_cache *cache;
5169 // struct _objc_protocol_list *protocols;
5170 // char *ivar_layout;
5171 // struct _objc_class_ext *ext;
5172 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005173 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5174 llvm::PointerType::getUnqual(ClassTy),
5175 Int8PtrTy,
5176 LongTy,
5177 LongTy,
5178 LongTy,
5179 IvarListPtrTy,
5180 MethodListPtrTy,
5181 CachePtrTy,
5182 ProtocolListPtrTy,
5183 Int8PtrTy,
5184 ClassExtensionPtrTy,
5185 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005186
Owen Anderson9793f0e2009-07-29 22:16:19 +00005187 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005188
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005189 // struct _objc_category {
5190 // char *category_name;
5191 // char *class_name;
5192 // struct _objc_method_list *instance_method;
5193 // struct _objc_method_list *class_method;
5194 // uint32_t size; // sizeof(struct _objc_category)
5195 // struct _objc_property_list *instance_properties;// category's @property
5196 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005197 CategoryTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005198 llvm::StructType::create("struct._objc_category",
5199 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5200 MethodListPtrTy, ProtocolListPtrTy,
5201 IntTy, PropertyListPtrTy, NULL);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005202
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005203 // Global metadata structures
5204
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005205 // struct _objc_symtab {
5206 // long sel_ref_cnt;
5207 // SEL *refs;
5208 // short cls_def_cnt;
5209 // short cat_def_cnt;
5210 // char *defs[cls_def_cnt + cat_def_cnt];
5211 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005212 SymtabTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005213 llvm::StructType::create("struct._objc_symtab",
5214 LongTy, SelectorPtrTy, ShortTy, ShortTy,
5215 llvm::ArrayType::get(Int8PtrTy, 0), NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005216 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005217
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00005218 // struct _objc_module {
5219 // long version;
5220 // long size; // sizeof(struct _objc_module)
5221 // char *name;
5222 // struct _objc_symtab* symtab;
5223 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005224 ModuleTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005225 llvm::StructType::create("struct._objc_module",
5226 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00005227
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005228
Mike Stump18bb9282009-05-16 07:57:57 +00005229 // FIXME: This is the size of the setjmp buffer and should be target
5230 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00005231 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005232
Anders Carlsson9ff22482008-09-09 10:10:21 +00005233 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00005234 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005235
5236 ExceptionDataTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005237 llvm::StructType::create("struct._objc_exception_data",
Chris Lattnerece04092012-02-07 00:39:47 +00005238 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
5239 StackPtrTy, NULL);
Anders Carlsson9ff22482008-09-09 10:10:21 +00005240
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005241}
5242
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005243ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005244 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005245 // struct _method_list_t {
5246 // uint32_t entsize; // sizeof(struct _objc_method)
5247 // uint32_t method_count;
5248 // struct _objc_method method_list[method_count];
5249 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005250 MethodListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005251 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
5252 llvm::ArrayType::get(MethodTy, 0), NULL);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005253 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005254 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005255
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005256 // struct _protocol_t {
5257 // id isa; // NULL
5258 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005259 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005260 // const struct method_list_t * const instance_methods;
5261 // const struct method_list_t * const class_methods;
5262 // const struct method_list_t *optionalInstanceMethods;
5263 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005264 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005265 // const uint32_t size; // sizeof(struct _protocol_t)
5266 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005267 // const char ** extendedMethodTypes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005268 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005269
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005270 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005271 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005272 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005273
Chris Lattnera5f58b02011-07-09 17:41:47 +00005274 ProtocolnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005275 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
5276 llvm::PointerType::getUnqual(ProtocolListnfABITy),
5277 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5278 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005279 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
5280 NULL);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005281
5282 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005283 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005284
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005285 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005286 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005287 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005288 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005289 ProtocolListnfABITy->setBody(LongTy,
5290 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
5291 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005292
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005293 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005294 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005295
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005296 // struct _ivar_t {
5297 // unsigned long int *offset; // pointer to ivar offset location
5298 // char *name;
5299 // char *type;
5300 // uint32_t alignment;
5301 // uint32_t size;
5302 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005303 IvarnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005304 llvm::StructType::create("struct._ivar_t",
5305 llvm::PointerType::getUnqual(LongTy),
5306 Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005307
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005308 // struct _ivar_list_t {
5309 // uint32 entsize; // sizeof(struct _ivar_t)
5310 // uint32 count;
5311 // struct _iver_t list[count];
5312 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005313 IvarListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005314 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
5315 llvm::ArrayType::get(IvarnfABITy, 0), NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005316
Owen Anderson9793f0e2009-07-29 22:16:19 +00005317 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005318
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005319 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005320 // uint32_t const flags;
5321 // uint32_t const instanceStart;
5322 // uint32_t const instanceSize;
5323 // uint32_t const reserved; // only when building for 64bit targets
5324 // const uint8_t * const ivarLayout;
5325 // const char *const name;
5326 // const struct _method_list_t * const baseMethods;
5327 // const struct _objc_protocol_list *const baseProtocols;
5328 // const struct _ivar_list_t *const ivars;
5329 // const uint8_t * const weakIvarLayout;
5330 // const struct _prop_list_t * const properties;
5331 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005332
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005333 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattner5ec04a52011-08-12 17:43:31 +00005334 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
5335 IntTy, IntTy, IntTy, Int8PtrTy,
5336 Int8PtrTy, MethodListnfABIPtrTy,
5337 ProtocolListnfABIPtrTy,
5338 IvarListnfABIPtrTy,
5339 Int8PtrTy, PropertyListPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005340
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005341 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00005342 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00005343 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5344 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005345
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005346 // struct _class_t {
5347 // struct _class_t *isa;
5348 // struct _class_t * const superclass;
5349 // void *cache;
5350 // IMP *vtable;
5351 // struct class_ro_t *ro;
5352 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005353
Chris Lattner5ec04a52011-08-12 17:43:31 +00005354 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005355 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
5356 llvm::PointerType::getUnqual(ClassnfABITy),
5357 CachePtrTy,
5358 llvm::PointerType::getUnqual(ImpnfABITy),
5359 llvm::PointerType::getUnqual(ClassRonfABITy),
5360 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005361
Fariborz Jahanian71394042009-01-23 23:53:38 +00005362 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005363 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005364
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005365 // struct _category_t {
5366 // const char * const name;
5367 // struct _class_t *const cls;
5368 // const struct _method_list_t * const instance_methods;
5369 // const struct _method_list_t * const class_methods;
5370 // const struct _protocol_list_t * const protocols;
5371 // const struct _prop_list_t * const properties;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00005372 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005373 CategorynfABITy = llvm::StructType::create("struct._category_t",
5374 Int8PtrTy, ClassnfABIPtrTy,
5375 MethodListnfABIPtrTy,
5376 MethodListnfABIPtrTy,
5377 ProtocolListnfABIPtrTy,
5378 PropertyListPtrTy,
5379 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005380
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005381 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005382 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5383 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005384
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005385 // MessageRefTy - LLVM for:
5386 // struct _message_ref_t {
5387 // IMP messenger;
5388 // SEL name;
5389 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005390
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005391 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00005392 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005393 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005394 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005395 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005396 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005397 Ctx.VoidPtrTy, 0, 0, false, ICIS_NoInit));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005398 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005399 Ctx.getObjCSelType(), 0, 0, false,
5400 ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005401 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005402
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005403 MessageRefCTy = Ctx.getTagDeclType(RD);
5404 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5405 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005406
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005407 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005408 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005409
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005410 // SuperMessageRefTy - LLVM for:
5411 // struct _super_message_ref_t {
5412 // SUPER_IMP messenger;
5413 // SEL name;
5414 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005415 SuperMessageRefTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005416 llvm::StructType::create("struct._super_message_ref_t",
5417 ImpnfABITy, SelectorPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005418
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005419 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005420 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005421
Daniel Dunbarb1559a42009-03-01 04:46:24 +00005422
5423 // struct objc_typeinfo {
5424 // const void** vtable; // objc_ehtype_vtable + 2
5425 // const char* name; // c++ typeinfo string
5426 // Class cls;
5427 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005428 EHTypeTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005429 llvm::StructType::create("struct._objc_typeinfo",
5430 llvm::PointerType::getUnqual(Int8PtrTy),
5431 Int8PtrTy, ClassnfABIPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005432 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005433}
5434
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005435llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00005436 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005437
Fariborz Jahanian71394042009-01-23 23:53:38 +00005438 return NULL;
5439}
5440
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00005441void CGObjCNonFragileABIMac::
5442AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
5443 const char *SymbolName,
5444 const char *SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00005445 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005446
Daniel Dunbar19573e72009-05-15 21:48:48 +00005447 if (!NumClasses)
5448 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005449
Chris Lattner3def9ae2012-02-06 22:16:34 +00005450 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005451 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00005452 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00005453 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00005454 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005455 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00005456 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00005457 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005458
Daniel Dunbar19573e72009-05-15 21:48:48 +00005459 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005460 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005461 llvm::GlobalValue::InternalLinkage,
5462 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005463 SymbolName);
Micah Villmowdd31ca12012-10-08 16:25:52 +00005464 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00005465 GV->setSection(SectionName);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005466 CGM.AddUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005467}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005468
Fariborz Jahanian71394042009-01-23 23:53:38 +00005469void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5470 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005471
Daniel Dunbar19573e72009-05-15 21:48:48 +00005472 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005473 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005474 AddModuleClassList(DefinedClasses,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005475 "\01L_OBJC_LABEL_CLASS_$",
5476 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahanian67260552009-11-17 21:37:35 +00005477
Bill Wendling53136852012-02-07 09:06:01 +00005478 for (unsigned i = 0, e = DefinedClasses.size(); i < e; i++) {
Fariborz Jahanian67260552009-11-17 21:37:35 +00005479 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
5480 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
5481 continue;
5482 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahanian67260552009-11-17 21:37:35 +00005483 }
5484
Bill Wendling53136852012-02-07 09:06:01 +00005485 for (unsigned i = 0, e = DefinedMetaClasses.size(); i < e; i++) {
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005486 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
5487 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
5488 continue;
5489 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
5490 }
Fariborz Jahanian67260552009-11-17 21:37:35 +00005491
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005492 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005493 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
5494 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005495
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005496 // Build list of all implemented category addresses in array
5497 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005498 AddModuleClassList(DefinedCategories,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005499 "\01L_OBJC_LABEL_CATEGORY_$",
5500 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005501 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005502 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
5503 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005504
Daniel Dunbar5e639272010-04-25 20:39:01 +00005505 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005506}
5507
John McCall9e8bb002011-05-14 03:10:52 +00005508/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
5509/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005510/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005511/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00005512bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
5513 // At various points we've experimented with using vtable-based
5514 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005515 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005516 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00005517 return false;
John McCall9e8bb002011-05-14 03:10:52 +00005518 case CodeGenOptions::NonLegacy:
5519 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005520 case CodeGenOptions::Mixed:
5521 break;
5522 }
5523
5524 // If so, see whether this selector is in the white-list of things which must
5525 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00005526 if (VTableDispatchMethods.empty()) {
5527 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
5528 VTableDispatchMethods.insert(GetNullarySelector("class"));
5529 VTableDispatchMethods.insert(GetNullarySelector("self"));
5530 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
5531 VTableDispatchMethods.insert(GetNullarySelector("length"));
5532 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005533
John McCall9e8bb002011-05-14 03:10:52 +00005534 // These are vtable-based if GC is disabled.
5535 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005536 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00005537 VTableDispatchMethods.insert(GetNullarySelector("retain"));
5538 VTableDispatchMethods.insert(GetNullarySelector("release"));
5539 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
5540 }
5541
5542 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
5543 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
5544 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
5545 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
5546 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
5547 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
5548 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
5549
5550 // These are vtable-based if GC is enabled.
5551 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005552 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00005553 VTableDispatchMethods.insert(GetNullarySelector("hash"));
5554 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
5555
5556 // "countByEnumeratingWithState:objects:count"
5557 IdentifierInfo *KeyIdents[] = {
5558 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
5559 &CGM.getContext().Idents.get("objects"),
5560 &CGM.getContext().Idents.get("count")
5561 };
5562 VTableDispatchMethods.insert(
5563 CGM.getContext().Selectors.getSelector(3, KeyIdents));
5564 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005565 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005566
John McCall9e8bb002011-05-14 03:10:52 +00005567 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005568}
5569
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005570/// BuildClassRoTInitializer - generate meta-data for:
5571/// struct _class_ro_t {
5572/// uint32_t const flags;
5573/// uint32_t const instanceStart;
5574/// uint32_t const instanceSize;
5575/// uint32_t const reserved; // only when building for 64bit targets
5576/// const uint8_t * const ivarLayout;
5577/// const char *const name;
5578/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005579/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005580/// const struct _ivar_list_t *const ivars;
5581/// const uint8_t * const weakIvarLayout;
5582/// const struct _prop_list_t * const properties;
5583/// }
5584///
5585llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005586 unsigned flags,
5587 unsigned InstanceStart,
5588 unsigned InstanceSize,
5589 const ObjCImplementationDecl *ID) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005590 std::string ClassName = ID->getNameAsString();
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005591 llvm::Constant *Values[10]; // 11 for 64bit targets!
John McCall31168b02011-06-15 23:02:42 +00005592
David Blaikiebbafb8a2012-03-11 07:00:24 +00005593 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00005594 flags |= NonFragileABI_Class_CompiledByARC;
John McCall31168b02011-06-15 23:02:42 +00005595
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005596 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
5597 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
5598 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005599 // FIXME. For 64bit targets add 0 here.
John McCallef19dbb2012-10-17 04:53:23 +00005600 Values[ 3] = (flags & NonFragileABI_Class_Meta)
5601 ? GetIvarLayoutName(0, ObjCTypes)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005602 : BuildIvarLayout(ID, true);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005603 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005604 // const struct _method_list_t * const baseMethods;
5605 std::vector<llvm::Constant*> Methods;
5606 std::string MethodListName("\01l_OBJC_$_");
John McCallef19dbb2012-10-17 04:53:23 +00005607 if (flags & NonFragileABI_Class_Meta) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005608 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005609 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005610 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005611 // Class methods should always be defined.
5612 Methods.push_back(GetMethodConstant(*i));
5613 }
5614 } else {
5615 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005616 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005617 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005618 // Instance methods should always be defined.
5619 Methods.push_back(GetMethodConstant(*i));
5620 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005621 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005622 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie40ed2972012-06-06 20:45:41 +00005623 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005624
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005625 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
5626 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005627
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005628 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
5629 if (llvm::Constant *C = GetMethodConstant(MD))
5630 Methods.push_back(C);
5631 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
5632 if (llvm::Constant *C = GetMethodConstant(MD))
5633 Methods.push_back(C);
5634 }
5635 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005636 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005637 Values[ 5] = EmitMethodList(MethodListName,
5638 "__DATA, __objc_const", Methods);
5639
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005640 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5641 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005642 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005643 + OID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00005644 OID->all_referenced_protocol_begin(),
5645 OID->all_referenced_protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005646
John McCallef19dbb2012-10-17 04:53:23 +00005647 if (flags & NonFragileABI_Class_Meta) {
Owen Anderson0b75f232009-07-31 20:28:54 +00005648 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCallef19dbb2012-10-17 04:53:23 +00005649 Values[ 8] = GetIvarLayoutName(0, ObjCTypes);
Owen Anderson0b75f232009-07-31 20:28:54 +00005650 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
John McCallef19dbb2012-10-17 04:53:23 +00005651 } else {
5652 Values[ 7] = EmitIvarList(ID);
5653 Values[ 8] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005654 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
5655 ID, ID->getClassInterface(), ObjCTypes);
John McCallef19dbb2012-10-17 04:53:23 +00005656 }
Owen Anderson0e0189d2009-07-27 22:29:56 +00005657 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005658 Values);
5659 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005660 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
5661 llvm::GlobalValue::InternalLinkage,
5662 Init,
John McCallef19dbb2012-10-17 04:53:23 +00005663 (flags & NonFragileABI_Class_Meta) ?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005664 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
5665 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005666 CLASS_RO_GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005667 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005668 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005669 return CLASS_RO_GV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005670
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005671}
5672
5673/// BuildClassMetaData - This routine defines that to-level meta-data
5674/// for the given ClassName for:
5675/// struct _class_t {
5676/// struct _class_t *isa;
5677/// struct _class_t * const superclass;
5678/// void *cache;
5679/// IMP *vtable;
5680/// struct class_ro_t *ro;
5681/// }
5682///
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005683llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005684 std::string &ClassName,
5685 llvm::Constant *IsAGV,
5686 llvm::Constant *SuperClassGV,
5687 llvm::Constant *ClassRoGV,
5688 bool HiddenVisibility) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005689 llvm::Constant *Values[] = {
5690 IsAGV,
5691 SuperClassGV,
5692 ObjCEmptyCacheVar, // &ObjCEmptyCacheVar
5693 ObjCEmptyVtableVar, // &ObjCEmptyVtableVar
5694 ClassRoGV // &CLASS_RO_GV
5695 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005696 if (!Values[1])
5697 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005698 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005699 Values);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005700 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
5701 GV->setInitializer(Init);
Fariborz Jahanian04087232009-01-31 01:07:39 +00005702 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005703 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005704 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian82208252009-01-31 00:59:10 +00005705 if (HiddenVisibility)
5706 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005707 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005708}
5709
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005710bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00005711CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005712 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005713}
5714
Daniel Dunbar961202372009-05-03 12:57:56 +00005715void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00005716 uint32_t &InstanceStart,
5717 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005718 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00005719 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005720
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005721 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00005722 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005723
5724 // If there are no fields, the start is the same as the end.
5725 if (!RL.getFieldCount())
5726 InstanceStart = InstanceSize;
5727 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00005728 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00005729}
5730
Fariborz Jahanian71394042009-01-23 23:53:38 +00005731void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
5732 std::string ClassName = ID->getNameAsString();
5733 if (!ObjCEmptyCacheVar) {
5734 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005735 CGM.getModule(),
5736 ObjCTypes.CacheTy,
5737 false,
5738 llvm::GlobalValue::ExternalLinkage,
5739 0,
5740 "_objc_empty_cache");
5741
Fariborz Jahanian71394042009-01-23 23:53:38 +00005742 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005743 CGM.getModule(),
5744 ObjCTypes.ImpnfABITy,
5745 false,
5746 llvm::GlobalValue::ExternalLinkage,
5747 0,
5748 "_objc_empty_vtable");
Fariborz Jahanian71394042009-01-23 23:53:38 +00005749 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005750 assert(ID->getClassInterface() &&
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005751 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00005752 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005753 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00005754 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005755 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00005756 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar15894b72009-04-07 05:48:37 +00005757 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
5758 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005759
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005760 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005761
John McCall0d54a172012-10-17 04:53:31 +00005762 // Build the flags for the metaclass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005763 bool classIsHidden =
John McCall457a04e2010-10-22 21:05:15 +00005764 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005765 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00005766 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00005767
5768 // FIXME: why is this flag set on the metaclass?
5769 // ObjC metaclasses have no fields and don't really get constructed.
5770 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00005771 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00005772 if (!ID->hasNonZeroConstructors())
5773 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5774 }
5775
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005776 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005777 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00005778 flags |= NonFragileABI_Class_Root;
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005779 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005780 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005781 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005782 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005783 const ObjCInterfaceDecl *Root = ID->getClassInterface();
5784 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
5785 Root = Super;
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005786 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005787 if (Root->isWeakImported())
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005788 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005789 // work on super class metadata symbol.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005790 std::string SuperClassName =
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005791 ObjCMetaClassName +
5792 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005793 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005794 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005795 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005796 }
5797 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
5798 InstanceStart,
5799 InstanceSize,ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005800 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005801 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005802 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
5803 classIsHidden);
Fariborz Jahanian67260552009-11-17 21:37:35 +00005804 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00005805
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005806 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00005807 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005808 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00005809 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00005810
5811 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00005812 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005813
John McCall0d54a172012-10-17 04:53:31 +00005814 // Set a flag to enable a runtime optimization when a class has
5815 // fields that require destruction but which don't require
5816 // anything except zero-initialization during construction. This
5817 // is most notably true of __strong and __weak types, but you can
5818 // also imagine there being C++ types with non-trivial default
5819 // constructors that merely set all fields to null.
5820 if (!ID->hasNonZeroConstructors())
5821 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5822 }
5823
Douglas Gregor78bd61f2009-06-18 16:11:24 +00005824 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
John McCallef19dbb2012-10-17 04:53:23 +00005825 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005826
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005827 if (!ID->getClassInterface()->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00005828 flags |= NonFragileABI_Class_Root;
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005829 SuperClassGV = 0;
Chris Lattnerb433b272009-04-19 06:02:28 +00005830 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005831 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005832 std::string RootClassName =
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005833 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005834 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005835 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005836 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005837 }
Daniel Dunbar961202372009-05-03 12:57:56 +00005838 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005839 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005840 InstanceStart,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005841 InstanceSize,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005842 ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005843
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005844 TClassName = ObjCClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005845 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005846 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5847 classIsHidden);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005848 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005849
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005850 // Determine if this class is also "non-lazy".
5851 if (ImplementationIsNonLazy(ID))
5852 DefinedNonLazyClasses.push_back(ClassMD);
5853
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005854 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00005855 if (flags & NonFragileABI_Class_Exception)
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005856 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005857 // Make sure method definition entries are all clear for next implementation.
5858 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005859}
5860
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005861/// GenerateProtocolRef - This routine is called to generate code for
5862/// a protocol reference expression; as in:
5863/// @code
5864/// @protocol(Proto1);
5865/// @endcode
5866/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5867/// which will hold address of the protocol meta-data.
5868///
5869llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005870 const ObjCProtocolDecl *PD) {
5871
Fariborz Jahanian464423d2009-04-10 18:47:34 +00005872 // This routine is called for @protocol only. So, we must build definition
5873 // of protocol's meta-data (not a reference to it!)
5874 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005875 llvm::Constant *Init =
5876 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00005877 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005878
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005879 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar56df9772010-08-17 22:39:59 +00005880 ProtocolName += PD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005881
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005882 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5883 if (PTGV)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005884 return Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005885 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005886 CGM.getModule(),
5887 Init->getType(), false,
5888 llvm::GlobalValue::WeakAnyLinkage,
5889 Init,
5890 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005891 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5892 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005893 CGM.AddUsedGlobal(PTGV);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005894 return Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005895}
5896
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005897/// GenerateCategory - Build metadata for a category implementation.
5898/// struct _category_t {
5899/// const char * const name;
5900/// struct _class_t *const cls;
5901/// const struct _method_list_t * const instance_methods;
5902/// const struct _method_list_t * const class_methods;
5903/// const struct _protocol_list_t * const protocols;
5904/// const struct _prop_list_t * const properties;
5905/// }
5906///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005907void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005908 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005909 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005910 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5911 "_$_" + OCD->getNameAsString());
5912 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar15894b72009-04-07 05:48:37 +00005913 Interface->getNameAsString());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005914
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005915 llvm::Constant *Values[6];
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005916 Values[0] = GetClassName(OCD->getIdentifier());
5917 // meta-class entry symbol
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005918 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005919 if (Interface->isWeakImported())
Fariborz Jahanian3ad8dcf2009-11-17 22:02:21 +00005920 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5921
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005922 Values[1] = ClassGV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005923 std::vector<llvm::Constant*> Methods;
5924 std::string MethodListName(Prefix);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005925 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005926 "_$_" + OCD->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005927
5928 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005929 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005930 // Instance methods should always be defined.
5931 Methods.push_back(GetMethodConstant(*i));
5932 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005933
5934 Values[2] = EmitMethodList(MethodListName,
5935 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005936 Methods);
5937
5938 MethodListName = Prefix;
5939 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5940 OCD->getNameAsString();
5941 Methods.clear();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005942 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005943 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005944 // Class methods should always be defined.
5945 Methods.push_back(GetMethodConstant(*i));
5946 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005947
5948 Values[3] = EmitMethodList(MethodListName,
5949 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005950 Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005951 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00005952 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005953 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005954 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005955 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5956 << OCD->getName();
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005957 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005958 + Interface->getName() + "_$_"
5959 + Category->getName(),
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005960 Category->protocol_begin(),
5961 Category->protocol_end());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005962 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5963 OCD, Category, ObjCTypes);
Mike Stump658fe022009-07-30 22:28:39 +00005964 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00005965 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5966 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005967 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005968
5969 llvm::Constant *Init =
5970 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005971 Values);
5972 llvm::GlobalVariable *GCATV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005973 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005974 false,
5975 llvm::GlobalValue::InternalLinkage,
5976 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005977 ExtCatName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005978 GCATV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005979 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005980 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005981 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005982 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005983
5984 // Determine if this category is also "non-lazy".
5985 if (ImplementationIsNonLazy(OCD))
5986 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005987 // method definition entries must be clear for next implementation.
5988 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005989}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005990
5991/// GetMethodConstant - Return a struct objc_method constant for the
5992/// given method if it has been defined. The result is null if the
5993/// method has not been defined. The return value has type MethodPtrTy.
5994llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005995 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005996 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005997 if (!Fn)
5998 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005999
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006000 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00006001 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006002 ObjCTypes.SelectorPtrTy),
6003 GetMethodVarType(MD),
6004 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
6005 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00006006 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006007}
6008
6009/// EmitMethodList - Build meta-data for method declarations
6010/// struct _method_list_t {
6011/// uint32_t entsize; // sizeof(struct _objc_method)
6012/// uint32_t method_count;
6013/// struct _objc_method method_list[method_count];
6014/// }
6015///
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00006016llvm::Constant *
6017CGObjCNonFragileABIMac::EmitMethodList(Twine Name,
6018 const char *Section,
6019 ArrayRef<llvm::Constant*> Methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006020 // Return null for empty list.
6021 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006022 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006023
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006024 llvm::Constant *Values[3];
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006025 // sizeof(struct _objc_method)
Micah Villmowdd31ca12012-10-08 16:25:52 +00006026 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006027 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006028 // method_count
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006029 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00006030 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006031 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00006032 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006033 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006034
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006035 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006036 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006037 llvm::GlobalValue::InternalLinkage, Init, Name);
Micah Villmowdd31ca12012-10-08 16:25:52 +00006038 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006039 GV->setSection(Section);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006040 CGM.AddUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006041 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006042}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006043
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006044/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6045/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006046llvm::GlobalVariable *
6047CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6048 const ObjCIvarDecl *Ivar) {
6049 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar3f86b9c2009-05-05 00:36:57 +00006050 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregorbcced4e2009-04-09 21:40:53 +00006051 '.' + Ivar->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006052 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006053 CGM.getModule().getGlobalVariable(Name);
6054 if (!IvarOffsetGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006055 IvarOffsetGV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006056 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006057 false,
6058 llvm::GlobalValue::ExternalLinkage,
6059 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006060 Name);
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006061 return IvarOffsetGV;
6062}
6063
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006064llvm::Constant *
6065CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6066 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00006067 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006068 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006069 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Eli Friedman8cbca202012-11-06 22:15:52 +00006070 Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006071 IvarOffsetGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006072 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006073
Mike Stump18bb9282009-05-16 07:57:57 +00006074 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
6075 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006076 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6077 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall457a04e2010-10-22 21:05:15 +00006078 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00006079 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00006080 else
Fariborz Jahanianbc3c77b2009-04-06 18:30:00 +00006081 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendlingf7d45982011-05-04 21:37:25 +00006082 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006083 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006084}
6085
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006086/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006087/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006088/// IvarListnfABIPtrTy.
6089/// struct _ivar_t {
6090/// unsigned long int *offset; // pointer to ivar offset location
6091/// char *name;
6092/// char *type;
6093/// uint32_t alignment;
6094/// uint32_t size;
6095/// }
6096/// struct _ivar_list_t {
6097/// uint32 entsize; // sizeof(struct _ivar_t)
6098/// uint32 count;
6099/// struct _iver_t list[count];
6100/// }
6101///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00006102
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006103llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006104 const ObjCImplementationDecl *ID) {
6105
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006106 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006107
Jordy Rosea91768e2011-07-22 02:08:32 +00006108 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006109 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006110
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006111 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006112
Jordy Rosea91768e2011-07-22 02:08:32 +00006113 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00006114 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00006115 // Ignore unnamed bit-fields.
6116 if (!IVD->getDeclName())
6117 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006118 llvm::Constant *Ivar[5];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006119 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar961202372009-05-03 12:57:56 +00006120 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006121 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
6122 Ivar[2] = GetMethodVarType(IVD);
Chris Lattner2192fe52011-07-18 04:24:23 +00006123 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006124 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00006125 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006126 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006127 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006128 Align = llvm::Log2_32(Align);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006129 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00006130 // NOTE. Size of a bitfield does not match gcc's, because of the
6131 // way bitfields are treated special in each. But I am told that
6132 // 'size' for bitfield ivars is ignored by the runtime so it does
6133 // not matter. If it matters, there is enough info to get the
6134 // bitfield right!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006135 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006136 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006137 }
6138 // Return null for empty list.
6139 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006140 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006141
6142 llvm::Constant *Values[3];
Micah Villmowdd31ca12012-10-08 16:25:52 +00006143 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006144 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
6145 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00006146 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006147 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00006148 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006149 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006150 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
6151 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006152 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006153 llvm::GlobalValue::InternalLinkage,
6154 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006155 Prefix + OID->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006156 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006157 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006158 GV->setSection("__DATA, __objc_const");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006159
Chris Lattnerf56501c2009-07-17 23:57:13 +00006160 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00006161 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006162}
6163
6164llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006165 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006166 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006167
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006168 if (!Entry) {
6169 // We use the initializer as a marker of whether this is a forward
6170 // reference or not. At module finalization we add the empty
6171 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006172 Entry =
6173 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
6174 llvm::GlobalValue::ExternalLinkage,
6175 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006176 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006177 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006178 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006179
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006180 return Entry;
6181}
6182
6183/// GetOrEmitProtocol - Generate the protocol meta-data:
6184/// @code
6185/// struct _protocol_t {
6186/// id isa; // NULL
6187/// const char * const protocol_name;
6188/// const struct _protocol_list_t * protocol_list; // super protocols
6189/// const struct method_list_t * const instance_methods;
6190/// const struct method_list_t * const class_methods;
6191/// const struct method_list_t *optionalInstanceMethods;
6192/// const struct method_list_t *optionalClassMethods;
6193/// const struct _prop_list_t * properties;
6194/// const uint32_t size; // sizeof(struct _protocol_t)
6195/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006196/// const char ** extendedMethodTypes;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006197/// }
6198/// @endcode
6199///
6200
6201llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006202 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00006203 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006204
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006205 // Early exit if a defining object has already been generated.
6206 if (Entry && Entry->hasInitializer())
6207 return Entry;
6208
Douglas Gregora715bff2012-01-01 19:51:50 +00006209 // Use the protocol definition, if there is one.
6210 if (const ObjCProtocolDecl *Def = PD->getDefinition())
6211 PD = Def;
6212
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006213 // Construct method lists.
6214 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
6215 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006216 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006217 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00006218 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006219 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006220 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006221 if (!C)
6222 return GetOrEmitProtocolRef(PD);
6223
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006224 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6225 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006226 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006227 } else {
6228 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006229 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006230 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006231 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006232
6233 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00006234 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006235 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006236 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006237 if (!C)
6238 return GetOrEmitProtocolRef(PD);
6239
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006240 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6241 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006242 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006243 } else {
6244 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006245 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006246 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006247 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006248
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006249 MethodTypesExt.insert(MethodTypesExt.end(),
6250 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
6251
6252 llvm::Constant *Values[11];
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006253 // isa is NULL
Owen Anderson0b75f232009-07-31 20:28:54 +00006254 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006255 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006256 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
6257 PD->protocol_begin(),
6258 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006259
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006260 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006261 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006262 "__DATA, __objc_const",
6263 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006264 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006265 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006266 "__DATA, __objc_const",
6267 ClassMethods);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006268 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006269 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006270 "__DATA, __objc_const",
6271 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006272 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006273 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006274 "__DATA, __objc_const",
6275 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006276 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006277 0, PD, ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006278 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006279 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006280 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0b75f232009-07-31 20:28:54 +00006281 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006282 Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
6283 + PD->getName(),
6284 MethodTypesExt, ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006285 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006286 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006287
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006288 if (Entry) {
6289 // Already created, fix the linkage and update the initializer.
Mike Stumpa6ca3342009-03-07 16:33:28 +00006290 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006291 Entry->setInitializer(Init);
6292 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006293 Entry =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006294 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6295 false, llvm::GlobalValue::WeakAnyLinkage, Init,
6296 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006297 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006298 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006299 Entry->setSection("__DATA,__datacoal_nt,coalesced");
John McCallf9582a72012-03-30 21:29:05 +00006300
6301 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006302 }
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006303 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006304 CGM.AddUsedGlobal(Entry);
6305
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006306 // Use this protocol meta-data to build protocol list table in section
6307 // __DATA, __objc_protolist
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006308 llvm::GlobalVariable *PTGV =
6309 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
6310 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
6311 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006312 PTGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006313 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbarb25452a2009-04-15 02:56:18 +00006314 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006315 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006316 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006317 return Entry;
6318}
6319
6320/// EmitProtocolList - Generate protocol list meta-data:
6321/// @code
6322/// struct _protocol_list_t {
6323/// long protocol_count; // Note, this is 32/64 bit
6324/// struct _protocol_t[protocol_count];
6325/// }
6326/// @endcode
6327///
6328llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006329CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006330 ObjCProtocolDecl::protocol_iterator begin,
6331 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendlinga515b582012-02-09 22:16:49 +00006332 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006333
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006334 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006335 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00006336 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006337
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006338 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006339 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006340 Name.toVector(TmpName);
6341 llvm::GlobalVariable *GV =
6342 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006343 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006344 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006345
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006346 for (; begin != end; ++begin)
6347 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
6348
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006349 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00006350 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006351 ObjCTypes.ProtocolnfABIPtrTy));
6352
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006353 llvm::Constant *Values[2];
Owen Anderson170229f2009-07-14 23:10:40 +00006354 Values[0] =
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006355 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006356 Values[1] =
Bill Wendlinga515b582012-02-09 22:16:49 +00006357 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
6358 ProtocolRefs.size()),
6359 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006360
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006361 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Owen Andersonc10c8d32009-07-08 19:05:04 +00006362 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006363 llvm::GlobalValue::InternalLinkage,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006364 Init, Name);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006365 GV->setSection("__DATA, __objc_const");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006366 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006367 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Chris Lattnerf56501c2009-07-17 23:57:13 +00006368 CGM.AddUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006369 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006370 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006371}
6372
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006373/// GetMethodDescriptionConstant - This routine build following meta-data:
6374/// struct _objc_method {
6375/// SEL _cmd;
6376/// char *method_type;
6377/// char *_imp;
6378/// }
6379
6380llvm::Constant *
6381CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006382 llvm::Constant *Desc[3];
Owen Anderson170229f2009-07-14 23:10:40 +00006383 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006384 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
6385 ObjCTypes.SelectorPtrTy);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006386 Desc[1] = GetMethodVarType(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006387 if (!Desc[1])
6388 return 0;
6389
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006390 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00006391 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006392 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006393}
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006394
6395/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
6396/// This code gen. amounts to generating code for:
6397/// @code
6398/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
6399/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006400///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00006401LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00006402 CodeGen::CodeGenFunction &CGF,
6403 QualType ObjectTy,
6404 llvm::Value *BaseValue,
6405 const ObjCIvarDecl *Ivar,
6406 unsigned CVRQualifiers) {
6407 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006408 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
6409 if (llvm::LoadInst *LI = dyn_cast<llvm::LoadInst>(Offset))
6410 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6411 llvm::MDNode::get(VMContext,
6412 ArrayRef<llvm::Value*>()));
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00006413 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006414 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006415}
6416
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006417llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006418 CodeGen::CodeGenFunction &CGF,
6419 const ObjCInterfaceDecl *Interface,
6420 const ObjCIvarDecl *Ivar) {
Daniel Dunbarc76493a2009-11-29 21:23:36 +00006421 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006422}
6423
John McCall234eac82011-05-13 23:16:18 +00006424static void appendSelectorForMessageRefTable(std::string &buffer,
6425 Selector selector) {
6426 if (selector.isUnarySelector()) {
6427 buffer += selector.getNameForSlot(0);
6428 return;
6429 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006430
John McCall234eac82011-05-13 23:16:18 +00006431 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
6432 buffer += selector.getNameForSlot(i);
6433 buffer += '_';
6434 }
6435}
6436
John McCall9e8bb002011-05-14 03:10:52 +00006437/// Emit a "v-table" message send. We emit a weak hidden-visibility
6438/// struct, initially containing the selector pointer and a pointer to
6439/// a "fixup" variant of the appropriate objc_msgSend. To call, we
6440/// load and call the function pointer, passing the address of the
6441/// struct as the second parameter. The runtime determines whether
6442/// the selector is currently emitted using vtable dispatch; if so, it
6443/// substitutes a stub function which simply tail-calls through the
6444/// appropriate vtable slot, and if not, it substitues a stub function
6445/// which tail-calls objc_msgSend. Both stubs adjust the selector
6446/// argument to correctly point to the selector.
6447RValue
6448CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
6449 ReturnValueSlot returnSlot,
6450 QualType resultType,
6451 Selector selector,
6452 llvm::Value *arg0,
6453 QualType arg0Type,
6454 bool isSuper,
6455 const CallArgList &formalArgs,
6456 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00006457 // Compute the actual arguments.
6458 CallArgList args;
6459
John McCall9e8bb002011-05-14 03:10:52 +00006460 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00006461 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00006462 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
6463 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00006464
John McCall9e8bb002011-05-14 03:10:52 +00006465 // Second argument: a pointer to the message ref structure. Leave
6466 // the actual argument value blank for now.
John McCall234eac82011-05-13 23:16:18 +00006467 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
6468
6469 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
6470
John McCalla729c622012-02-17 03:33:10 +00006471 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00006472
John McCall5880fb82011-05-14 21:12:11 +00006473 NullReturnState nullReturn;
6474
John McCall9e8bb002011-05-14 03:10:52 +00006475 // Find the function to call and the mangled name for the message
6476 // ref structure. Using a different mangled name wouldn't actually
6477 // be a problem; it would just be a waste.
6478 //
6479 // The runtime currently never uses vtable dispatch for anything
6480 // except normal, non-super message-sends.
6481 // FIXME: don't use this for that.
John McCall234eac82011-05-13 23:16:18 +00006482 llvm::Constant *fn = 0;
6483 std::string messageRefName("\01l_");
John McCalla729c622012-02-17 03:33:10 +00006484 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00006485 if (isSuper) {
6486 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
6487 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006488 } else {
John McCall5880fb82011-05-14 21:12:11 +00006489 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00006490 fn = ObjCTypes.getMessageSendStretFixupFn();
6491 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006492 }
John McCall234eac82011-05-13 23:16:18 +00006493 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
6494 fn = ObjCTypes.getMessageSendFpretFixupFn();
6495 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00006496 } else {
John McCall234eac82011-05-13 23:16:18 +00006497 if (isSuper) {
6498 fn = ObjCTypes.getMessageSendSuper2FixupFn();
6499 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006500 } else {
John McCall234eac82011-05-13 23:16:18 +00006501 fn = ObjCTypes.getMessageSendFixupFn();
6502 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006503 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006504 }
John McCall234eac82011-05-13 23:16:18 +00006505 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
6506 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006507
John McCall234eac82011-05-13 23:16:18 +00006508 // Append the selector name, except use underscores anywhere we
6509 // would have used colons.
6510 appendSelectorForMessageRefTable(messageRefName, selector);
6511
6512 llvm::GlobalVariable *messageRef
6513 = CGM.getModule().getGlobalVariable(messageRefName);
6514 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00006515 // Build the message ref structure.
John McCall234eac82011-05-13 23:16:18 +00006516 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006517 llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
John McCall234eac82011-05-13 23:16:18 +00006518 messageRef = new llvm::GlobalVariable(CGM.getModule(),
6519 init->getType(),
6520 /*constant*/ false,
6521 llvm::GlobalValue::WeakAnyLinkage,
6522 init,
6523 messageRefName);
6524 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
6525 messageRef->setAlignment(16);
6526 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
6527 }
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006528
6529 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006530 if (CGM.getLangOpts().ObjCAutoRefCount && method)
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006531 for (ObjCMethodDecl::param_const_iterator i = method->param_begin(),
6532 e = method->param_end(); i != e; ++i) {
6533 const ParmVarDecl *ParamDecl = (*i);
6534 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
6535 if (!nullReturn.NullBB)
6536 nullReturn.init(CGF, arg0);
6537 requiresnullCheck = true;
6538 break;
6539 }
6540 }
6541
John McCall234eac82011-05-13 23:16:18 +00006542 llvm::Value *mref =
6543 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
6544
John McCall9e8bb002011-05-14 03:10:52 +00006545 // Update the message ref argument.
John McCall234eac82011-05-13 23:16:18 +00006546 args[1].RV = RValue::get(mref);
6547
6548 // Load the function to call from the message ref table.
6549 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
6550 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
6551
John McCalla729c622012-02-17 03:33:10 +00006552 callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
John McCall234eac82011-05-13 23:16:18 +00006553
John McCalla729c622012-02-17 03:33:10 +00006554 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006555 return nullReturn.complete(CGF, result, resultType, formalArgs,
6556 requiresnullCheck ? method : 0);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00006557}
6558
6559/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006560CodeGen::RValue
6561CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00006562 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006563 QualType ResultType,
6564 Selector Sel,
6565 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006566 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00006567 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006568 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00006569 return isVTableDispatchedSelector(Sel)
6570 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006571 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00006572 false, CallArgs, Method)
6573 : EmitMessageSend(CGF, Return, ResultType,
6574 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006575 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00006576 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00006577}
6578
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006579llvm::GlobalVariable *
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006580CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006581 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
6582
Daniel Dunbara6468342009-03-02 05:18:14 +00006583 if (!GV) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006584 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006585 false, llvm::GlobalValue::ExternalLinkage,
6586 0, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006587 }
6588
6589 return GV;
6590}
6591
John McCall31168b02011-06-15 23:02:42 +00006592llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CGBuilderTy &Builder,
6593 IdentifierInfo *II) {
6594 llvm::GlobalVariable *&Entry = ClassReferences[II];
6595
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006596 if (!Entry) {
John McCall31168b02011-06-15 23:02:42 +00006597 std::string ClassName(getClassSymbolPrefix() + II->getName().str());
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006598 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006599 Entry =
John McCall31168b02011-06-15 23:02:42 +00006600 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
6601 false, llvm::GlobalValue::InternalLinkage,
6602 ClassGV,
6603 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006604 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006605 CGM.getDataLayout().getABITypeAlignment(
John McCall31168b02011-06-15 23:02:42 +00006606 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006607 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006608 CGM.AddUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006609 }
John McCall31168b02011-06-15 23:02:42 +00006610
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006611 return Builder.CreateLoad(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006612}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006613
John McCall31168b02011-06-15 23:02:42 +00006614llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
6615 const ObjCInterfaceDecl *ID) {
6616 return EmitClassRefFromId(Builder, ID->getIdentifier());
6617}
6618
6619llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
6620 CGBuilderTy &Builder) {
6621 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
6622 return EmitClassRefFromId(Builder, II);
6623}
6624
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006625llvm::Value *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006626CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006627 const ObjCInterfaceDecl *ID) {
6628 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006629
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006630 if (!Entry) {
6631 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6632 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006633 Entry =
6634 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006635 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006636 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006637 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006638 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006639 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006640 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006641 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006642 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006643 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006644
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006645 return Builder.CreateLoad(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006646}
6647
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006648/// EmitMetaClassRef - Return a Value * of the address of _class_t
6649/// meta-data
6650///
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006651llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
6652 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006653 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
6654 if (Entry)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006655 return Builder.CreateLoad(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006656
Daniel Dunbar15894b72009-04-07 05:48:37 +00006657 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006658 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006659 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006660 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006661 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006662 MetaClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006663 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006664 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006665 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006666 ObjCTypes.ClassnfABIPtrTy));
6667
Daniel Dunbare60aa052009-04-15 19:03:14 +00006668 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006669 CGM.AddUsedGlobal(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006670
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006671 return Builder.CreateLoad(Entry);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006672}
6673
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006674/// GetClass - Return a reference to the class for the given interface
6675/// decl.
6676llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
6677 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00006678 if (ID->isWeakImported()) {
Fariborz Jahanian95ace552009-11-17 22:42:00 +00006679 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6680 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
6681 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
6682 }
6683
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006684 return EmitClassRef(Builder, ID);
6685}
6686
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006687/// Generates a message send where the super is the receiver. This is
6688/// a message send to self with special delivery semantics indicating
6689/// which class's method should be called.
6690CodeGen::RValue
6691CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00006692 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006693 QualType ResultType,
6694 Selector Sel,
6695 const ObjCInterfaceDecl *Class,
6696 bool isCategoryImpl,
6697 llvm::Value *Receiver,
6698 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006699 const CodeGen::CallArgList &CallArgs,
6700 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006701 // ...
6702 // Create and init a super structure; this is a (receiver, class)
6703 // pair we will pass to objc_msgSendSuper.
6704 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00006705 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006706
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006707 llvm::Value *ReceiverAsObject =
6708 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
6709 CGF.Builder.CreateStore(ReceiverAsObject,
6710 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006711
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006712 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006713 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00006714 if (IsClassMessage)
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006715 Target = EmitMetaClassRef(CGF.Builder, Class);
Fariborz Jahanian27678b02012-10-10 23:11:18 +00006716 else
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006717 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006718
Mike Stump18bb9282009-05-16 07:57:57 +00006719 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
6720 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00006721 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006722 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
6723 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
6724 CGF.Builder.CreateStore(Target,
6725 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006726
John McCall9e8bb002011-05-14 03:10:52 +00006727 return (isVTableDispatchedSelector(Sel))
6728 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006729 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006730 true, CallArgs, Method)
6731 : EmitMessageSend(CGF, Return, ResultType,
6732 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006733 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006734 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006735}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006736
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006737llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006738 Selector Sel, bool lval) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006739 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006740
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006741 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006742 llvm::Constant *Casted =
6743 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
6744 ObjCTypes.SelectorPtrTy);
6745 Entry =
6746 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
6747 llvm::GlobalValue::InternalLinkage,
6748 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006749 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006750 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006751 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006752
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006753 if (lval)
6754 return Entry;
Pete Cooper9d605512011-11-10 21:45:06 +00006755 llvm::LoadInst* LI = Builder.CreateLoad(Entry);
6756
6757 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6758 llvm::MDNode::get(VMContext,
6759 ArrayRef<llvm::Value*>()));
6760 return LI;
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006761}
Fariborz Jahanian06292952009-02-16 22:52:32 +00006762/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006763/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00006764///
6765void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006766 llvm::Value *src,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006767 llvm::Value *dst,
6768 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006769 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006770 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006771 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006772 assert(Size <= 8 && "does not support size > 8");
6773 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6774 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006775 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6776 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006777 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6778 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006779 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
6780 src, dst, ivarOffset);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006781 return;
6782}
6783
6784/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
6785/// objc_assign_strongCast (id src, id *dst)
6786///
6787void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006788 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006789 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006790 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006791 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006792 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006793 assert(Size <= 8 && "does not support size > 8");
6794 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006795 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006796 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6797 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006798 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6799 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00006800 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006801 src, dst, "weakassign");
6802 return;
6803}
6804
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006805void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006806 CodeGen::CodeGenFunction &CGF,
6807 llvm::Value *DestPtr,
6808 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006809 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006810 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
6811 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006812 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006813 DestPtr, SrcPtr, Size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006814 return;
6815}
6816
Fariborz Jahanian06292952009-02-16 22:52:32 +00006817/// EmitObjCWeakRead - Code gen for loading value of a __weak
6818/// object: objc_read_weak (id *src)
6819///
6820llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006821 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006822 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006823 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006824 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
6825 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00006826 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006827 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00006828 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006829 return read_weak;
6830}
6831
6832/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
6833/// objc_assign_weak (id src, id *dst)
6834///
6835void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006836 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006837 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006838 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006839 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006840 assert(Size <= 8 && "does not support size > 8");
6841 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6842 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006843 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6844 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006845 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6846 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00006847 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006848 src, dst, "weakassign");
6849 return;
6850}
6851
6852/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
6853/// objc_assign_global (id src, id *dst)
6854///
6855void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00006856 llvm::Value *src, llvm::Value *dst,
6857 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006858 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006859 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006860 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006861 assert(Size <= 8 && "does not support size > 8");
6862 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6863 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006864 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6865 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006866 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6867 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00006868 if (!threadlocal)
6869 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
6870 src, dst, "globalassign");
6871 else
6872 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
6873 src, dst, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00006874 return;
6875}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006876
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006877void
John McCallbd309292010-07-06 01:34:17 +00006878CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6879 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006880 EmitAtSynchronizedStmt(CGF, S,
6881 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6882 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00006883}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006884
John McCall2ca705e2010-07-24 00:37:23 +00006885llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00006886CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00006887 // There's a particular fixed type info for 'id'.
6888 if (T->isObjCIdType() ||
6889 T->isObjCQualifiedIdType()) {
6890 llvm::Constant *IDEHType =
6891 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6892 if (!IDEHType)
6893 IDEHType =
6894 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6895 false,
6896 llvm::GlobalValue::ExternalLinkage,
6897 0, "OBJC_EHTYPE_id");
6898 return IDEHType;
6899 }
6900
6901 // All other types should be Objective-C interface pointer types.
6902 const ObjCObjectPointerType *PT =
6903 T->getAs<ObjCObjectPointerType>();
6904 assert(PT && "Invalid @catch type.");
6905 const ObjCInterfaceType *IT = PT->getInterfaceType();
6906 assert(IT && "Invalid @catch type.");
6907 return GetInterfaceEHType(IT->getDecl(), false);
6908}
6909
John McCallbd309292010-07-06 01:34:17 +00006910void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6911 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006912 EmitTryCatchStmt(CGF, S,
6913 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6914 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6915 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006916}
6917
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006918/// EmitThrowStmt - Generate code for a throw statement.
6919void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6920 const ObjCAtThrowStmt &S) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006921 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00006922 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006923 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Jay Foad5bd375a2011-07-15 08:37:34 +00006924 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall17afe452010-10-16 08:21:07 +00006925 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006926 } else {
Jay Foad5bd375a2011-07-15 08:37:34 +00006927 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall17afe452010-10-16 08:21:07 +00006928 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006929 }
6930
John McCall17afe452010-10-16 08:21:07 +00006931 CGF.Builder.CreateUnreachable();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006932 CGF.Builder.ClearInsertionPoint();
6933}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006934
John McCall2ca705e2010-07-24 00:37:23 +00006935llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006936CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006937 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006938 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006939
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006940 // If we don't need a definition, return the entry if found or check
6941 // if we use an external reference.
6942 if (!ForDefinition) {
6943 if (Entry)
6944 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00006945
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006946 // If this type (or a super class) has the __objc_exception__
6947 // attribute, emit an external reference.
Douglas Gregor78bd61f2009-06-18 16:11:24 +00006948 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006949 return Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006950 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006951 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006952 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006953 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006954 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006955 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006956
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006957 // Otherwise we need to either make a new entry or fill in the
6958 // initializer.
6959 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar15894b72009-04-07 05:48:37 +00006960 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006961 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006962 llvm::GlobalVariable *VTableGV =
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006963 CGM.getModule().getGlobalVariable(VTableName);
6964 if (!VTableGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006965 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6966 false,
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006967 llvm::GlobalValue::ExternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006968 0, VTableName);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006969
Chris Lattnerece04092012-02-07 00:39:47 +00006970 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006971
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006972 llvm::Constant *Values[] = {
6973 llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
6974 GetClassName(ID->getIdentifier()),
6975 GetClassGlobal(ClassName)
6976 };
Owen Anderson170229f2009-07-14 23:10:40 +00006977 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00006978 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006979
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006980 if (Entry) {
6981 Entry->setInitializer(Init);
6982 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00006983 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006984 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006985 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006986 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006987 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006988 }
6989
David Blaikiebbafb8a2012-03-11 07:00:24 +00006990 if (CGM.getLangOpts().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar15894b72009-04-07 05:48:37 +00006991 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Micah Villmowdd31ca12012-10-08 16:25:52 +00006992 Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00006993 ObjCTypes.EHTypeTy));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006994
6995 if (ForDefinition) {
6996 Entry->setSection("__DATA,__objc_const");
6997 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6998 } else {
6999 Entry->setSection("__DATA,__datacoal_nt,coalesced");
7000 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007001
7002 return Entry;
7003}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007004
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00007005/* *** */
7006
Daniel Dunbarb036db82008-08-13 03:21:16 +00007007CodeGen::CGObjCRuntime *
7008CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00007009 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7010 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007011 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00007012
7013 case ObjCRuntime::MacOSX:
7014 case ObjCRuntime::iOS:
7015 return new CGObjCNonFragileABIMac(CGM);
7016
David Chisnallb601c962012-07-03 20:49:52 +00007017 case ObjCRuntime::GNUstep:
7018 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00007019 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00007020 llvm_unreachable("these runtimes are not Mac runtimes");
7021 }
7022 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007023}