blob: ddc422395b8593b72facb80821b7abb70b818183 [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"
Chandler Carruthffd55512013-01-02 11:45:17 +000031#include "llvm/IR/DataLayout.h"
32#include "llvm/IR/InlineAsm.h"
33#include "llvm/IR/IntrinsicInst.h"
34#include "llvm/IR/LLVMContext.h"
35#include "llvm/IR/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 Wendling207f0532012-12-20 19:27:06 +000067 llvm::Attribute::get(CGM.getLLVMContext(),
68 llvm::Attribute::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 Wendling207f0532012-12-20 19:27:06 +0000585 llvm::Attribute::get(CGM.getLLVMContext(),
586 llvm::Attribute::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();
David Chisnall0d75e062012-12-17 18:54:24 +00001226 virtual llvm::Constant *GetCppAtomicObjectGetFunction();
1227 virtual llvm::Constant *GetCppAtomicObjectSetFunction();
Chris Lattnerd4808922009-03-22 21:03:39 +00001228 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001229
John McCallbd309292010-07-06 01:34:17 +00001230 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1231 const ObjCAtTryStmt &S);
1232 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1233 const ObjCAtSynchronizedStmt &S);
1234 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00001235 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00001236 const ObjCAtThrowStmt &S,
1237 bool ClearInsertionPoint=true);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001238 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001239 llvm::Value *AddrWeakObj);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001240 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001241 llvm::Value *src, llvm::Value *dst);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001242 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001243 llvm::Value *src, llvm::Value *dest,
1244 bool threadlocal = false);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00001245 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001246 llvm::Value *src, llvm::Value *dest,
1247 llvm::Value *ivarOffset);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001248 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1249 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001250 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1251 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001252 llvm::Value *size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001253
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001254 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1255 QualType ObjectTy,
1256 llvm::Value *BaseValue,
1257 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001258 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001259 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001260 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001261 const ObjCIvarDecl *Ivar);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001262
1263 /// GetClassGlobal - Return the global variable for the Objective-C
1264 /// class of the given name.
1265 virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) {
David Blaikie83d382b2011-09-23 05:06:16 +00001266 llvm_unreachable("CGObjCMac::GetClassGlobal");
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001267 }
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001268};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001269
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001270class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001271private:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001272 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001273 llvm::GlobalVariable* ObjCEmptyCacheVar;
1274 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001275
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001276 /// SuperClassReferences - uniqued super class references.
1277 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001278
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001279 /// MetaClassReferences - uniqued meta class references.
1280 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001281
1282 /// EHTypeReferences - uniqued class ehtype references.
1283 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001284
John McCall9e8bb002011-05-14 03:10:52 +00001285 /// VTableDispatchMethods - List of methods for which we generate
1286 /// vtable-based message dispatch.
1287 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001288
Fariborz Jahanian67260552009-11-17 21:37:35 +00001289 /// DefinedMetaClasses - List of defined meta-classes.
1290 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1291
John McCall9e8bb002011-05-14 03:10:52 +00001292 /// isVTableDispatchedSelector - Returns true if SEL is a
1293 /// vtable-based selector.
1294 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001295
Fariborz Jahanian71394042009-01-23 23:53:38 +00001296 /// FinishNonFragileABIModule - Write out global data structures at the end of
1297 /// processing a translation unit.
1298 void FinishNonFragileABIModule();
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001299
Daniel Dunbar19573e72009-05-15 21:48:48 +00001300 /// AddModuleClassList - Add the given list of class pointers to the
1301 /// module with the provided symbol and section names.
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001302 void AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
Daniel Dunbar19573e72009-05-15 21:48:48 +00001303 const char *SymbolName,
1304 const char *SectionName);
1305
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001306 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1307 unsigned InstanceStart,
1308 unsigned InstanceSize,
1309 const ObjCImplementationDecl *ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001310 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001311 llvm::Constant *IsAGV,
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001312 llvm::Constant *SuperClassGV,
Fariborz Jahanian82208252009-01-31 00:59:10 +00001313 llvm::Constant *ClassRoGV,
1314 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001315
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001316 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001317
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00001318 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001319
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001320 /// EmitMethodList - Emit the method list for the given
1321 /// implementation. The return value has type MethodListnfABITy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001322 llvm::Constant *EmitMethodList(Twine Name,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001323 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00001324 ArrayRef<llvm::Constant*> Methods);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00001325 /// EmitIvarList - Emit the ivar list for the given
1326 /// implementation. If ForClass is true the list of class ivars
1327 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1328 /// interface ivars will be emitted. The return value has type
1329 /// IvarListnfABIPtrTy.
1330 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001331
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001332 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001333 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00001334 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001335
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001336 /// GetOrEmitProtocol - Get the protocol object for the given
1337 /// declaration, emitting it if necessary. The return value has type
1338 /// ProtocolPtrTy.
1339 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001340
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001341 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1342 /// object for the given declaration, emitting it if needed. These
1343 /// forward references will be filled in with empty bodies if no
1344 /// definition is seen. The return value has type ProtocolPtrTy.
1345 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001346
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001347 /// EmitProtocolList - Generate the list of referenced
1348 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001349 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001350 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001351 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001352
John McCall9e8bb002011-05-14 03:10:52 +00001353 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1354 ReturnValueSlot Return,
1355 QualType ResultType,
1356 Selector Sel,
1357 llvm::Value *Receiver,
1358 QualType Arg0Ty,
1359 bool IsSuper,
1360 const CallArgList &CallArgs,
1361 const ObjCMethodDecl *Method);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001362
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00001363 /// GetClassGlobal - Return the global variable for the Objective-C
1364 /// class of the given name.
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00001365 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Fariborz Jahanian7bd3d1c2011-05-17 22:21:16 +00001366
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001367 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001368 /// for the given class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001369 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001370 const ObjCInterfaceDecl *ID);
John McCall31168b02011-06-15 23:02:42 +00001371
1372 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
1373 IdentifierInfo *II);
1374
1375 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001376
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001377 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1378 /// for the given super class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001379 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1380 const ObjCInterfaceDecl *ID);
1381
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001382 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1383 /// meta-data
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001384 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001385 const ObjCInterfaceDecl *ID);
1386
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001387 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1388 /// the given ivar.
1389 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001390 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001391 const ObjCInterfaceDecl *ID,
1392 const ObjCIvarDecl *Ivar);
1393
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001394 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1395 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001396 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1397 bool lval=false);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001398
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001399 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001400 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001401 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001402 bool ForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001403
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001404 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar15894b72009-04-07 05:48:37 +00001405 return "OBJC_METACLASS_$_";
1406 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001407
Daniel Dunbar15894b72009-04-07 05:48:37 +00001408 const char *getClassSymbolPrefix() const {
1409 return "OBJC_CLASS_$_";
1410 }
1411
Daniel Dunbar961202372009-05-03 12:57:56 +00001412 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001413 uint32_t &InstanceStart,
1414 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001415
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001416 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001417 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001418 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1419 return CGM.getContext().Selectors.getSelector(0, &II);
1420 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001421
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001422 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001423 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1424 return CGM.getContext().Selectors.getSelector(1, &II);
1425 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001426
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001427 /// ImplementationIsNonLazy - Check whether the given category or
1428 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001429 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001430
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001431public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001432 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001433 // FIXME. All stubs for now!
1434 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001435
Fariborz Jahanian71394042009-01-23 23:53:38 +00001436 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001437 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001438 QualType ResultType,
1439 Selector Sel,
1440 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001441 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001442 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001443 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001444
1445 virtual CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001446 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001447 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001448 QualType ResultType,
1449 Selector Sel,
1450 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001451 bool isCategoryImpl,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001452 llvm::Value *Receiver,
1453 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001454 const CallArgList &CallArgs,
1455 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001456
Fariborz Jahanian71394042009-01-23 23:53:38 +00001457 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001458 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001459
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001460 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1461 bool lvalue = false)
1462 { return EmitSelector(Builder, Sel, lvalue); }
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001463
1464 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1465 /// untyped one.
1466 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1467 const ObjCMethodDecl *Method)
1468 { return EmitSelector(Builder, Method->getSelector()); }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001469
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00001470 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001471
Fariborz Jahanian71394042009-01-23 23:53:38 +00001472 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
David Chisnall92d436b2012-01-31 18:59:20 +00001473
Daniel Dunbarf3d3b012012-02-28 15:36:15 +00001474 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}
David Chisnall92d436b2012-01-31 18:59:20 +00001475
Fariborz Jahanian71394042009-01-23 23:53:38 +00001476 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian097feda2009-01-30 18:58:59 +00001477 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001478
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001479 virtual llvm::Constant *GetEHType(QualType T);
John McCall2ca705e2010-07-24 00:37:23 +00001480
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001481 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001482 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001483 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001484 virtual llvm::Constant *GetPropertySetFunction() {
1485 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001486 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001487
Ted Kremeneke65b0862012-03-06 20:05:56 +00001488 virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1489 bool copy) {
1490 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1491 }
1492
David Chisnall168b80f2010-12-26 22:13:16 +00001493 virtual llvm::Constant *GetSetStructFunction() {
1494 return ObjCTypes.getCopyStructFn();
1495 }
1496 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001497 return ObjCTypes.getCopyStructFn();
1498 }
David Chisnall0d75e062012-12-17 18:54:24 +00001499 virtual llvm::Constant *GetCppAtomicObjectSetFunction() {
1500 return ObjCTypes.getCppAtomicObjectFunction();
1501 }
1502 virtual llvm::Constant *GetCppAtomicObjectGetFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00001503 return ObjCTypes.getCppAtomicObjectFunction();
1504 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001505
Chris Lattnerd4808922009-03-22 21:03:39 +00001506 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001507 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001508 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001509
John McCallbd309292010-07-06 01:34:17 +00001510 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1511 const ObjCAtTryStmt &S);
1512 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1513 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001514 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00001515 const ObjCAtThrowStmt &S,
1516 bool ClearInsertionPoint=true);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001517 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001518 llvm::Value *AddrWeakObj);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001519 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001520 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001521 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001522 llvm::Value *src, llvm::Value *dest,
1523 bool threadlocal = false);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001524 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001525 llvm::Value *src, llvm::Value *dest,
1526 llvm::Value *ivarOffset);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001527 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001528 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001529 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1530 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001531 llvm::Value *size);
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001532 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1533 QualType ObjectTy,
1534 llvm::Value *BaseValue,
1535 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001536 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001537 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001538 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001539 const ObjCIvarDecl *Ivar);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001540};
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001541
1542/// A helper class for performing the null-initialization of a return
1543/// value.
1544struct NullReturnState {
1545 llvm::BasicBlock *NullBB;
1546 llvm::BasicBlock *callBB;
1547 NullReturnState() : NullBB(0), callBB(0) {}
1548
1549 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1550 // Make blocks for the null-init and call edges.
1551 NullBB = CGF.createBasicBlock("msgSend.nullinit");
1552 callBB = CGF.createBasicBlock("msgSend.call");
1553
1554 // Check for a null receiver and, if there is one, jump to the
1555 // null-init test.
1556 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1557 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1558
1559 // Otherwise, start performing the call.
1560 CGF.EmitBlock(callBB);
1561 }
1562
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001563 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1564 const CallArgList &CallArgs,
1565 const ObjCMethodDecl *Method) {
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001566 if (!NullBB) return result;
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001567
1568 llvm::Value *NullInitPtr = 0;
1569 if (result.isScalar() && !resultType->isVoidType()) {
1570 NullInitPtr = CGF.CreateTempAlloca(result.getScalarVal()->getType());
1571 CGF.Builder.CreateStore(result.getScalarVal(), NullInitPtr);
1572 }
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001573
1574 // Finish the call path.
1575 llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
1576 if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
1577
1578 // Emit the null-init block and perform the null-initialization there.
1579 CGF.EmitBlock(NullBB);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001580
1581 // Release consumed arguments along the null-receiver path.
1582 if (Method) {
1583 CallArgList::const_iterator I = CallArgs.begin();
1584 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1585 e = Method->param_end(); i != e; ++i, ++I) {
1586 const ParmVarDecl *ParamDecl = (*i);
1587 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1588 RValue RV = I->RV;
1589 assert(RV.isScalar() &&
1590 "NullReturnState::complete - arg not on object");
1591 CGF.EmitARCRelease(RV.getScalarVal(), true);
1592 }
1593 }
1594 }
1595
1596 if (result.isScalar()) {
1597 if (NullInitPtr)
1598 CGF.EmitNullInitialization(NullInitPtr, resultType);
1599 // Jump to the continuation block.
1600 CGF.EmitBlock(contBB);
1601 return NullInitPtr ? RValue::get(CGF.Builder.CreateLoad(NullInitPtr))
1602 : result;
1603 }
1604
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001605 if (!resultType->isAnyComplexType()) {
1606 assert(result.isAggregate() && "null init of non-aggregate result?");
1607 CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
1608 // Jump to the continuation block.
1609 CGF.EmitBlock(contBB);
1610 return result;
1611 }
1612
1613 // _Complex type
1614 // FIXME. Now easy to handle any other scalar type whose result is returned
1615 // in memory due to ABI limitations.
1616 CGF.EmitBlock(contBB);
1617 CodeGenFunction::ComplexPairTy CallCV = result.getComplexVal();
1618 llvm::Type *MemberType = CallCV.first->getType();
1619 llvm::Constant *ZeroCV = llvm::Constant::getNullValue(MemberType);
1620 // Create phi instruction for scalar complex value.
1621 llvm::PHINode *PHIReal = CGF.Builder.CreatePHI(MemberType, 2);
1622 PHIReal->addIncoming(ZeroCV, NullBB);
1623 PHIReal->addIncoming(CallCV.first, callBB);
1624 llvm::PHINode *PHIImag = CGF.Builder.CreatePHI(MemberType, 2);
1625 PHIImag->addIncoming(ZeroCV, NullBB);
1626 PHIImag->addIncoming(CallCV.second, callBB);
1627 return RValue::getComplex(PHIReal, PHIImag);
1628 }
1629};
1630
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001631} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001632
1633/* *** Helper Functions *** */
1634
1635/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001636static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001637 llvm::Constant *C,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001638 unsigned idx0,
1639 unsigned idx1) {
1640 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001641 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1642 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001643 };
Jay Foaded8db7d2011-07-21 14:31:17 +00001644 return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001645}
1646
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001647/// hasObjCExceptionAttribute - Return true if this class or any super
1648/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001649static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001650 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001651 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001652 return true;
1653 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001654 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001655 return false;
1656}
1657
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001658/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001659
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001660CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001661 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001662 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001663 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001664}
1665
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001666/// GetClass - Return a reference to the class for the given interface
1667/// decl.
Daniel Dunbarcb463852008-11-01 01:53:16 +00001668llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001669 const ObjCInterfaceDecl *ID) {
1670 return EmitClassRef(Builder, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001671}
1672
1673/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001674llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1675 bool lval) {
1676 return EmitSelector(Builder, Sel, lval);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001677}
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001678llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001679 *Method) {
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001680 return EmitSelector(Builder, Method->getSelector());
1681}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001682
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001683llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001684 if (T->isObjCIdType() ||
1685 T->isObjCQualifiedIdType()) {
1686 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001687 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00001688 }
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001689 if (T->isObjCClassType() ||
1690 T->isObjCQualifiedClassType()) {
1691 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor97673472011-08-11 20:58:55 +00001692 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00001693 }
1694 if (T->isObjCObjectPointerType())
1695 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1696
John McCall2ca705e2010-07-24 00:37:23 +00001697 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall2ca705e2010-07-24 00:37:23 +00001698}
1699
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001700/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001701/*
1702 struct __builtin_CFString {
1703 const int *isa; // point to __CFConstantStringClassReference
1704 int flags;
1705 const char *str;
1706 long length;
1707 };
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001708*/
1709
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001710/// or Generate a constant NSString object.
1711/*
1712 struct __builtin_NSString {
1713 const int *isa; // point to __NSConstantStringClassReference
1714 const char *str;
1715 unsigned int length;
1716 };
1717*/
1718
Fariborz Jahanian71394042009-01-23 23:53:38 +00001719llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall481e3a82010-01-23 02:40:42 +00001720 const StringLiteral *SL) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001721 return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001722 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian50c925f2010-10-19 17:19:29 +00001723 CGM.GetAddrOfConstantString(SL));
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001724}
1725
Ted Kremeneke65b0862012-03-06 20:05:56 +00001726enum {
1727 kCFTaggedObjectID_Integer = (1 << 1) + 1
1728};
1729
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001730/// Generates a message send where the super is the receiver. This is
1731/// a message send to self with special delivery semantics indicating
1732/// which class's method should be called.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001733CodeGen::RValue
1734CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001735 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001736 QualType ResultType,
1737 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001738 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001739 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001740 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001741 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001742 const CodeGen::CallArgList &CallArgs,
1743 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001744 // Create and init a super structure; this is a (receiver, class)
1745 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001746 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00001747 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001748 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001749 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001750 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001751 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001752
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001753 // If this is a class message the metaclass is passed as the target.
1754 llvm::Value *Target;
1755 if (IsClassMessage) {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001756 if (isCategoryImpl) {
1757 // Message sent to 'super' in a class method defined in a category
1758 // implementation requires an odd treatment.
1759 // If we are in a class method, we must retrieve the
1760 // _metaclass_ for the current class, pointed at by
1761 // the class's "isa" pointer. The following assumes that
1762 // isa" is the first ivar in a class (which it must be).
1763 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1764 Target = CGF.Builder.CreateStructGEP(Target, 0);
1765 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00001766 } else {
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001767 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1768 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1769 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1770 Target = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001771 }
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00001772 }
1773 else if (isCategoryImpl)
1774 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1775 else {
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00001776 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1777 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1778 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001779 }
Mike Stump18bb9282009-05-16 07:57:57 +00001780 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1781 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00001782 llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00001783 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00001784 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001785 CGF.Builder.CreateStore(Target,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001786 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall9e8bb002011-05-14 03:10:52 +00001787 return EmitMessageSend(CGF, Return, ResultType,
1788 EmitSelector(CGF.Builder, Sel),
1789 ObjCSuper, ObjCTypes.SuperPtrCTy,
1790 true, CallArgs, Method, ObjCTypes);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001791}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001792
1793/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001794CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001795 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001796 QualType ResultType,
1797 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001798 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001799 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001800 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001801 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00001802 return EmitMessageSend(CGF, Return, ResultType,
1803 EmitSelector(CGF.Builder, Sel),
1804 Receiver, CGF.getContext().getObjCIdType(),
1805 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00001806}
1807
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001808CodeGen::RValue
John McCall9e8bb002011-05-14 03:10:52 +00001809CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1810 ReturnValueSlot Return,
1811 QualType ResultType,
1812 llvm::Value *Sel,
1813 llvm::Value *Arg0,
1814 QualType Arg0Ty,
1815 bool IsSuper,
1816 const CallArgList &CallArgs,
1817 const ObjCMethodDecl *Method,
1818 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc722b852008-08-30 03:02:31 +00001819 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00001820 if (!IsSuper)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00001821 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman43dca6a2011-05-02 17:57:46 +00001822 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1823 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCall31168b02011-06-15 23:02:42 +00001824 ActualArgs.addFrom(CallArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001825
John McCalla729c622012-02-17 03:33:10 +00001826 // If we're calling a method, use the formal signature.
1827 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001828
Anders Carlsson280e61f12010-06-21 20:59:55 +00001829 if (Method)
1830 assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1831 CGM.getContext().getCanonicalType(ResultType) &&
1832 "Result type mismatch!");
1833
John McCall5880fb82011-05-14 21:12:11 +00001834 NullReturnState nullReturn;
1835
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001836 llvm::Constant *Fn = NULL;
John McCalla729c622012-02-17 03:33:10 +00001837 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
Fariborz Jahanian715fdd52012-01-29 20:27:13 +00001838 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001839 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001840 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001841 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1842 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1843 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlsson2f1a6c32011-10-31 16:27:11 +00001844 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
1845 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
1846 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001847 } else {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001848 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001849 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001850 }
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001851
1852 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001853 if (CGM.getLangOpts().ObjCAutoRefCount && Method)
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001854 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1855 e = Method->param_end(); i != e; ++i) {
1856 const ParmVarDecl *ParamDecl = (*i);
1857 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1858 if (!nullReturn.NullBB)
1859 nullReturn.init(CGF, Arg0);
1860 requiresnullCheck = true;
1861 break;
1862 }
1863 }
1864
John McCalla729c622012-02-17 03:33:10 +00001865 Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
1866 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs);
Fariborz Jahanianf2bda692012-01-30 21:40:37 +00001867 return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
1868 requiresnullCheck ? Method : 0);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001869}
1870
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001871static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1872 if (FQT.isObjCGCStrong())
1873 return Qualifiers::Strong;
1874
John McCall31168b02011-06-15 23:02:42 +00001875 if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001876 return Qualifiers::Weak;
1877
Fariborz Jahanian430b35e2012-02-16 00:15:02 +00001878 // check for __unsafe_unretained
1879 if (FQT.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
1880 return Qualifiers::GCNone;
1881
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001882 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1883 return Qualifiers::Strong;
1884
1885 if (const PointerType *PT = FQT->getAs<PointerType>())
1886 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1887
1888 return Qualifiers::GCNone;
1889}
1890
John McCall351762c2011-02-07 10:33:21 +00001891llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1892 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00001893
Chris Lattnerece04092012-02-07 00:39:47 +00001894 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001895 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
1896 !CGM.getLangOpts().ObjCAutoRefCount)
John McCall351762c2011-02-07 10:33:21 +00001897 return nullPtr;
1898
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001899 bool hasUnion = false;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001900 SkipIvars.clear();
1901 IvarsInfo.clear();
Eli Friedman8cbca202012-11-06 22:15:52 +00001902 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
1903 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001904
Fariborz Jahaniancfddabf2010-09-09 00:21:45 +00001905 // __isa is the first field in block descriptor and must assume by runtime's
1906 // convention that it is GC'able.
Eli Friedman8cbca202012-11-06 22:15:52 +00001907 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall351762c2011-02-07 10:33:21 +00001908
1909 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1910
1911 // Calculate the basic layout of the block structure.
1912 const llvm::StructLayout *layout =
Micah Villmowdd31ca12012-10-08 16:25:52 +00001913 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
John McCall351762c2011-02-07 10:33:21 +00001914
1915 // Ignore the optional 'this' capture: C++ objects are not assumed
1916 // to be GC'ed.
1917
1918 // Walk the captured variables.
1919 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1920 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1921 const VarDecl *variable = ci->getVariable();
1922 QualType type = variable->getType();
1923
1924 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1925
1926 // Ignore constant captures.
1927 if (capture.isConstant()) continue;
1928
Eli Friedman8cbca202012-11-06 22:15:52 +00001929 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
John McCall351762c2011-02-07 10:33:21 +00001930
1931 // __block variables are passed by their descriptor address.
1932 if (ci->isByRef()) {
Eli Friedman8cbca202012-11-06 22:15:52 +00001933 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanian933c6722010-09-11 01:27:29 +00001934 continue;
John McCall351762c2011-02-07 10:33:21 +00001935 }
1936
1937 assert(!type->isArrayType() && "array variable should not be caught");
1938 if (const RecordType *record = type->getAs<RecordType>()) {
1939 BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
Fariborz Jahanian903aba32010-08-05 21:00:25 +00001940 continue;
1941 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001942
John McCall351762c2011-02-07 10:33:21 +00001943 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
Eli Friedman8cbca202012-11-06 22:15:52 +00001944 unsigned fieldSize = CGM.getContext().getTypeSize(type);
John McCall351762c2011-02-07 10:33:21 +00001945
1946 if (GCAttr == Qualifiers::Strong)
Eli Friedman8cbca202012-11-06 22:15:52 +00001947 IvarsInfo.push_back(GC_IVAR(fieldOffset,
1948 fieldSize / WordSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001949 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
Eli Friedman8cbca202012-11-06 22:15:52 +00001950 SkipIvars.push_back(GC_IVAR(fieldOffset,
1951 fieldSize / ByteSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001952 }
1953
1954 if (IvarsInfo.empty())
John McCall351762c2011-02-07 10:33:21 +00001955 return nullPtr;
1956
1957 // Sort on byte position; captures might not be allocated in order,
1958 // and unions can do funny things.
1959 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
1960 llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001961
1962 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00001963 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001964 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001965 printf("\n block variable layout for block: ");
Roman Divackye6377112012-09-06 15:59:27 +00001966 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00001967 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001968 if (!(s[i] & 0xf0))
1969 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1970 else
1971 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
1972 printf("\n");
1973 }
1974
1975 return C;
Fariborz Jahanianc05349e2010-08-04 16:57:49 +00001976}
1977
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00001978/// getBlockCaptureLifetime - This routine returns life time of the captured
1979/// block variable for the purpose of block layout meta-data generation. FQT is
1980/// the type of the variable captured in the block.
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001981Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
1982 bool ByrefLayout) {
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00001983 if (CGM.getLangOpts().ObjCAutoRefCount)
1984 return FQT.getObjCLifetime();
1985
Fariborz Jahanian2c96d302012-11-04 18:19:40 +00001986 // MRR.
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00001987 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00001988 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fariborz Jahanian2dd78192012-11-02 22:51:18 +00001989
1990 return Qualifiers::OCL_None;
1991}
1992
Fariborz Jahanian39319c42012-10-30 20:05:29 +00001993void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
1994 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00001995 CharUnits FieldOffset,
1996 CharUnits FieldSize) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00001997 // __block variables are passed by their descriptor address.
1998 if (IsByref)
1999 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002000 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002001 else if (LifeTime == Qualifiers::OCL_Strong)
2002 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002003 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002004 else if (LifeTime == Qualifiers::OCL_Weak)
2005 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002006 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002007 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2008 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002009 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002010 else
2011 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2012 FieldOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002013 FieldSize));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002014}
2015
2016void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2017 const RecordDecl *RD,
2018 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002019 CharUnits BytePos, bool &HasUnion,
2020 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002021 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002022 CharUnits MaxUnionSize = CharUnits::Zero();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002023 const FieldDecl *MaxField = 0;
2024 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002025 CharUnits MaxFieldOffset = CharUnits::Zero();
2026 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002027
2028 if (RecFields.empty())
2029 return;
2030 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
2031
2032 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2033 const FieldDecl *Field = RecFields[i];
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002034 // Note that 'i' here is actually the field index inside RD of Field,
2035 // although this dependency is hidden.
2036 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002037 CharUnits FieldOffset =
2038 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002039
2040 // Skip over unnamed or bitfields
2041 if (!Field->getIdentifier() || Field->isBitField()) {
2042 LastFieldBitfieldOrUnnamed = Field;
2043 LastBitfieldOrUnnamedOffset = FieldOffset;
2044 continue;
2045 }
2046
2047 LastFieldBitfieldOrUnnamed = 0;
2048 QualType FQT = Field->getType();
2049 if (FQT->isRecordType() || FQT->isUnionType()) {
2050 if (FQT->isUnionType())
2051 HasUnion = true;
2052
2053 BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2054 BytePos + FieldOffset, HasUnion);
2055 continue;
2056 }
2057
2058 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2059 const ConstantArrayType *CArray =
2060 dyn_cast_or_null<ConstantArrayType>(Array);
2061 uint64_t ElCount = CArray->getSize().getZExtValue();
2062 assert(CArray && "only array with known element size is supported");
2063 FQT = CArray->getElementType();
2064 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2065 const ConstantArrayType *CArray =
2066 dyn_cast_or_null<ConstantArrayType>(Array);
2067 ElCount *= CArray->getSize().getZExtValue();
2068 FQT = CArray->getElementType();
2069 }
2070
2071 assert(!FQT->isUnionType() &&
2072 "layout for array of unions not supported");
2073 if (FQT->isRecordType() && ElCount) {
2074 int OldIndex = RunSkipBlockVars.size() - 1;
2075 const RecordType *RT = FQT->getAs<RecordType>();
2076 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2077 HasUnion);
2078
2079 // Replicate layout information for each array element. Note that
2080 // one element is already done.
2081 uint64_t ElIx = 1;
2082 for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002083 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002084 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2085 RunSkipBlockVars.push_back(
2086 RUN_SKIP(RunSkipBlockVars[i].opcode,
2087 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2088 RunSkipBlockVars[i].block_var_size));
2089 }
2090 continue;
2091 }
2092 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002093 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002094 if (IsUnion) {
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002095 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002096 if (UnionIvarSize > MaxUnionSize) {
2097 MaxUnionSize = UnionIvarSize;
2098 MaxField = Field;
2099 MaxFieldOffset = FieldOffset;
2100 }
2101 } else {
2102 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002103 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002104 BytePos + FieldOffset,
2105 FieldSize);
2106 }
2107 }
2108
2109 if (LastFieldBitfieldOrUnnamed) {
2110 if (LastFieldBitfieldOrUnnamed->isBitField()) {
2111 // Last field was a bitfield. Must update the info.
2112 uint64_t BitFieldSize
2113 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002114 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedman8cbca202012-11-06 22:15:52 +00002115 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002116 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002117 Size += LastBitfieldOrUnnamedOffset;
2118 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002119 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2120 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002121 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002122 Size);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002123 } else {
2124 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2125 // Last field was unnamed. Must update skip info.
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002126 CharUnits FieldSize
2127 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002128 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002129 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2130 ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002131 BytePos + LastBitfieldOrUnnamedOffset,
2132 FieldSize);
2133 }
2134 }
2135
2136 if (MaxField)
2137 UpdateRunSkipBlockVars(false,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002138 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002139 BytePos + MaxFieldOffset,
2140 MaxUnionSize);
2141}
2142
2143void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002144 CharUnits BytePos,
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002145 bool &HasUnion,
2146 bool ByrefLayout) {
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002147 const RecordDecl *RD = RT->getDecl();
2148 SmallVector<const FieldDecl*, 16> Fields;
2149 for (RecordDecl::field_iterator i = RD->field_begin(),
2150 e = RD->field_end(); i != e; ++i)
2151 Fields.push_back(*i);
2152 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2153 const llvm::StructLayout *RecLayout =
2154 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2155
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002156 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002157}
2158
Fariborz Jahanian23290b02012-11-01 18:32:55 +00002159/// InlineLayoutInstruction - This routine produce an inline instruction for the
2160/// block variable layout if it can. If not, it returns 0. Rules are as follow:
2161/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2162/// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2163/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2164/// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2165/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2166/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2167/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
2168uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2169 SmallVectorImpl<unsigned char> &Layout) {
2170 uint64_t Result = 0;
2171 if (Layout.size() <= 3) {
2172 unsigned size = Layout.size();
2173 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2174 unsigned char inst;
2175 enum BLOCK_LAYOUT_OPCODE opcode ;
2176 switch (size) {
2177 case 3:
2178 inst = Layout[0];
2179 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2180 if (opcode == BLOCK_LAYOUT_STRONG)
2181 strong_word_count = (inst & 0xF)+1;
2182 else
2183 return 0;
2184 inst = Layout[1];
2185 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2186 if (opcode == BLOCK_LAYOUT_BYREF)
2187 byref_word_count = (inst & 0xF)+1;
2188 else
2189 return 0;
2190 inst = Layout[2];
2191 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2192 if (opcode == BLOCK_LAYOUT_WEAK)
2193 weak_word_count = (inst & 0xF)+1;
2194 else
2195 return 0;
2196 break;
2197
2198 case 2:
2199 inst = Layout[0];
2200 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2201 if (opcode == BLOCK_LAYOUT_STRONG) {
2202 strong_word_count = (inst & 0xF)+1;
2203 inst = Layout[1];
2204 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2205 if (opcode == BLOCK_LAYOUT_BYREF)
2206 byref_word_count = (inst & 0xF)+1;
2207 else if (opcode == BLOCK_LAYOUT_WEAK)
2208 weak_word_count = (inst & 0xF)+1;
2209 else
2210 return 0;
2211 }
2212 else if (opcode == BLOCK_LAYOUT_BYREF) {
2213 byref_word_count = (inst & 0xF)+1;
2214 inst = Layout[1];
2215 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2216 if (opcode == BLOCK_LAYOUT_WEAK)
2217 weak_word_count = (inst & 0xF)+1;
2218 else
2219 return 0;
2220 }
2221 else
2222 return 0;
2223 break;
2224
2225 case 1:
2226 inst = Layout[0];
2227 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2228 if (opcode == BLOCK_LAYOUT_STRONG)
2229 strong_word_count = (inst & 0xF)+1;
2230 else if (opcode == BLOCK_LAYOUT_BYREF)
2231 byref_word_count = (inst & 0xF)+1;
2232 else if (opcode == BLOCK_LAYOUT_WEAK)
2233 weak_word_count = (inst & 0xF)+1;
2234 else
2235 return 0;
2236 break;
2237
2238 default:
2239 return 0;
2240 }
2241
2242 // Cannot inline when any of the word counts is 15. Because this is one less
2243 // than the actual work count (so 15 means 16 actual word counts),
2244 // and we can only display 0 thru 15 word counts.
2245 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2246 return 0;
2247
2248 unsigned count =
2249 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2250
2251 if (size == count) {
2252 if (strong_word_count)
2253 Result = strong_word_count;
2254 Result <<= 4;
2255 if (byref_word_count)
2256 Result += byref_word_count;
2257 Result <<= 4;
2258 if (weak_word_count)
2259 Result += weak_word_count;
2260 }
2261 }
2262 return Result;
2263}
2264
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002265llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2266 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2267 if (RunSkipBlockVars.empty())
2268 return nullPtr;
2269 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
2270 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
2271 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2272
2273 // Sort on byte position; captures might not be allocated in order,
2274 // and unions can do funny things.
2275 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2276 SmallVector<unsigned char, 16> Layout;
2277
2278 unsigned size = RunSkipBlockVars.size();
2279 for (unsigned i = 0; i < size; i++) {
2280 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2281 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2282 CharUnits end_byte_pos = start_byte_pos;
2283 unsigned j = i+1;
2284 while (j < size) {
2285 if (opcode == RunSkipBlockVars[j].opcode) {
2286 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2287 i++;
2288 }
2289 else
2290 break;
2291 }
2292 CharUnits size_in_bytes =
2293 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2294 if (j < size) {
2295 CharUnits gap =
2296 RunSkipBlockVars[j].block_var_bytepos -
2297 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2298 size_in_bytes += gap;
2299 }
2300 CharUnits residue_in_bytes = CharUnits::Zero();
2301 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2302 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2303 size_in_bytes -= residue_in_bytes;
2304 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2305 }
2306
2307 unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2308 while (size_in_words >= 16) {
2309 // Note that value in imm. is one less that the actual
2310 // value. So, 0xf means 16 words follow!
2311 unsigned char inst = (opcode << 4) | 0xf;
2312 Layout.push_back(inst);
2313 size_in_words -= 16;
2314 }
2315 if (size_in_words > 0) {
2316 // Note that value in imm. is one less that the actual
2317 // value. So, we subtract 1 away!
2318 unsigned char inst = (opcode << 4) | (size_in_words-1);
2319 Layout.push_back(inst);
2320 }
2321 if (residue_in_bytes > CharUnits::Zero()) {
2322 unsigned char inst =
2323 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2324 Layout.push_back(inst);
2325 }
2326 }
2327
2328 int e = Layout.size()-1;
2329 while (e >= 0) {
2330 unsigned char inst = Layout[e--];
2331 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2332 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2333 Layout.pop_back();
2334 else
2335 break;
2336 }
2337
2338 uint64_t Result = InlineLayoutInstruction(Layout);
2339 if (Result != 0) {
2340 // Block variable layout instruction has been inlined.
2341 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2342 if (ComputeByrefLayout)
2343 printf("\n Inline instruction for BYREF variable layout: ");
2344 else
2345 printf("\n Inline instruction for block variable layout: ");
2346 printf("0x0%llx\n", (unsigned long long)Result);
2347 }
2348 if (WordSizeInBytes == 8) {
2349 const llvm::APInt Instruction(64, Result);
2350 return llvm::Constant::getIntegerValue(CGM.Int64Ty, Instruction);
2351 }
2352 else {
2353 const llvm::APInt Instruction(32, Result);
2354 return llvm::Constant::getIntegerValue(CGM.Int32Ty, Instruction);
2355 }
2356 }
2357
2358 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2359 Layout.push_back(inst);
2360 std::string BitMap;
2361 for (unsigned i = 0, e = Layout.size(); i != e; i++)
2362 BitMap += Layout[i];
2363
2364 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2365 if (ComputeByrefLayout)
2366 printf("\n BYREF variable layout: ");
2367 else
2368 printf("\n block variable layout: ");
2369 for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2370 unsigned char inst = BitMap[i];
2371 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2372 unsigned delta = 1;
2373 switch (opcode) {
2374 case BLOCK_LAYOUT_OPERATOR:
2375 printf("BL_OPERATOR:");
2376 delta = 0;
2377 break;
2378 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2379 printf("BL_NON_OBJECT_BYTES:");
2380 break;
2381 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2382 printf("BL_NON_OBJECT_WORD:");
2383 break;
2384 case BLOCK_LAYOUT_STRONG:
2385 printf("BL_STRONG:");
2386 break;
2387 case BLOCK_LAYOUT_BYREF:
2388 printf("BL_BYREF:");
2389 break;
2390 case BLOCK_LAYOUT_WEAK:
2391 printf("BL_WEAK:");
2392 break;
2393 case BLOCK_LAYOUT_UNRETAINED:
2394 printf("BL_UNRETAINED:");
2395 break;
2396 }
2397 // Actual value of word count is one more that what is in the imm.
2398 // field of the instruction
2399 printf("%d", (inst & 0xf) + delta);
2400 if (i < e-1)
2401 printf(", ");
2402 else
2403 printf("\n");
2404 }
2405 }
2406
2407 llvm::GlobalVariable * Entry =
2408 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
2409 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
2410 "__TEXT,__objc_classname,cstring_literals", 1, true);
2411 return getConstantGEP(VMContext, Entry, 0, 0);
2412}
2413
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002414llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2415 const CGBlockInfo &blockInfo) {
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002416 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2417
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002418 RunSkipBlockVars.clear();
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002419 bool hasUnion = false;
2420
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002421 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
2422 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
2423 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2424
2425 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2426
2427 // Calculate the basic layout of the block structure.
2428 const llvm::StructLayout *layout =
2429 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
2430
2431 // Ignore the optional 'this' capture: C++ objects are not assumed
2432 // to be GC'ed.
Fariborz Jahanian4cf177e2012-12-04 17:20:57 +00002433 if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2434 UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2435 blockInfo.BlockHeaderForcedGapOffset,
2436 blockInfo.BlockHeaderForcedGapSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002437 // Walk the captured variables.
2438 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
2439 ce = blockDecl->capture_end(); ci != ce; ++ci) {
2440 const VarDecl *variable = ci->getVariable();
2441 QualType type = variable->getType();
2442
2443 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2444
2445 // Ignore constant captures.
2446 if (capture.isConstant()) continue;
2447
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002448 CharUnits fieldOffset =
2449 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002450
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002451 assert(!type->isArrayType() && "array variable should not be caught");
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002452 if (!ci->isByRef())
2453 if (const RecordType *record = type->getAs<RecordType>()) {
2454 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2455 continue;
2456 }
Fariborz Jahanian7778d612012-11-07 20:00:32 +00002457 CharUnits fieldSize;
2458 if (ci->isByRef())
2459 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2460 else
2461 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002462 UpdateRunSkipBlockVars(ci->isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanian39319c42012-10-30 20:05:29 +00002463 fieldOffset, fieldSize);
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002464 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002465 return getBitmapBlockLayout(false);
2466}
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002467
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002468
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002469llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2470 QualType T) {
2471 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2472 assert(!T->isArrayType() && "__block array variable should not be caught");
2473 CharUnits fieldOffset;
2474 RunSkipBlockVars.clear();
2475 bool hasUnion = false;
2476 if (const RecordType *record = T->getAs<RecordType>()) {
2477 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
2478 llvm::Constant *Result = getBitmapBlockLayout(true);
2479 return Result;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002480 }
Fariborz Jahaniana9d44642012-11-14 17:15:51 +00002481 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2482 return nullPtr;
Fariborz Jahanian0c58ce92012-10-27 21:10:38 +00002483}
2484
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002485llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00002486 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00002487 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002488 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00002489 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2490
Owen Andersonade90fd2009-07-29 18:54:39 +00002491 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00002492 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002493}
2494
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002495void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-05-16 07:57:57 +00002496 // FIXME: We shouldn't need this, the protocol decl should contain enough
2497 // information to tell us whether this was a declaration or a definition.
Daniel Dunbarc475d422008-10-29 22:36:39 +00002498 DefinedProtocols.insert(PD->getIdentifier());
2499
2500 // If we have generated a forward reference to this protocol, emit
2501 // it now. Otherwise do nothing, the protocol objects are lazily
2502 // emitted.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002503 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00002504 GetOrEmitProtocol(PD);
2505}
2506
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00002507llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002508 if (DefinedProtocols.count(PD->getIdentifier()))
2509 return GetOrEmitProtocol(PD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002510
Daniel Dunbarc475d422008-10-29 22:36:39 +00002511 return GetOrEmitProtocolRef(PD);
2512}
2513
Daniel Dunbarb036db82008-08-13 03:21:16 +00002514/*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002515// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
2516struct _objc_protocol {
2517struct _objc_protocol_extension *isa;
2518char *protocol_name;
2519struct _objc_protocol_list *protocol_list;
2520struct _objc__method_prototype_list *instance_methods;
2521struct _objc__method_prototype_list *class_methods
2522};
Daniel Dunbarb036db82008-08-13 03:21:16 +00002523
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002524See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00002525*/
Daniel Dunbarc475d422008-10-29 22:36:39 +00002526llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00002527 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbarc475d422008-10-29 22:36:39 +00002528
2529 // Early exit if a defining object has already been generated.
2530 if (Entry && Entry->hasInitializer())
2531 return Entry;
2532
Douglas Gregora715bff2012-01-01 19:51:50 +00002533 // Use the protocol definition, if there is one.
2534 if (const ObjCProtocolDecl *Def = PD->getDefinition())
2535 PD = Def;
2536
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002537 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00002538 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002539 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2540
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002541 // Construct method lists.
2542 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2543 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002544 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002545 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002546 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002547 ObjCMethodDecl *MD = *i;
2548 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002549 if (!C)
2550 return GetOrEmitProtocolRef(PD);
2551
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002552 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2553 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002554 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002555 } else {
2556 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002557 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002558 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002559 }
2560
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002561 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002562 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002563 ObjCMethodDecl *MD = *i;
2564 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00002565 if (!C)
2566 return GetOrEmitProtocolRef(PD);
2567
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002568 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2569 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002570 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002571 } else {
2572 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002573 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002574 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002575 }
2576
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002577 MethodTypesExt.insert(MethodTypesExt.end(),
2578 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
2579
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002580 llvm::Constant *Values[] = {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002581 EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
2582 MethodTypesExt),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002583 GetClassName(PD->getIdentifier()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002584 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00002585 PD->protocol_begin(),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002586 PD->protocol_end()),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002587 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002588 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002589 InstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002590 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002591 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002592 ClassMethods)
2593 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002594 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002595 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002596
Daniel Dunbarb036db82008-08-13 03:21:16 +00002597 if (Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002598 // Already created, fix the linkage and update the initializer.
2599 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002600 Entry->setInitializer(Init);
2601 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002602 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002603 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002604 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002605 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002606 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002607 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002608 // FIXME: Is this necessary? Why only for protocol?
2609 Entry->setAlignment(4);
John McCallf9582a72012-03-30 21:29:05 +00002610
2611 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002612 }
Chris Lattnerf56501c2009-07-17 23:57:13 +00002613 CGM.AddUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00002614
2615 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002616}
2617
Daniel Dunbarc475d422008-10-29 22:36:39 +00002618llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002619 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2620
2621 if (!Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00002622 // We use the initializer as a marker of whether this is a forward
2623 // reference or not. At module finalization we add the empty
2624 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002625 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002626 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarc475d422008-10-29 22:36:39 +00002627 llvm::GlobalValue::ExternalLinkage,
2628 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002629 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00002630 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00002631 // FIXME: Is this necessary? Why only for protocol?
2632 Entry->setAlignment(4);
2633 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002634
Daniel Dunbarb036db82008-08-13 03:21:16 +00002635 return Entry;
2636}
2637
2638/*
2639 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002640 uint32_t size;
2641 struct objc_method_description_list *optional_instance_methods;
2642 struct objc_method_description_list *optional_class_methods;
2643 struct objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002644 const char ** extendedMethodTypes;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002645 };
2646*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002647llvm::Constant *
2648CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002649 ArrayRef<llvm::Constant*> OptInstanceMethods,
2650 ArrayRef<llvm::Constant*> OptClassMethods,
2651 ArrayRef<llvm::Constant*> MethodTypesExt) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002652 uint64_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002653 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002654 llvm::Constant *Values[] = {
2655 llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002656 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002657 + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002658 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002659 OptInstanceMethods),
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002660 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002661 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002662 OptClassMethods),
2663 EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002664 ObjCTypes),
2665 EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
2666 MethodTypesExt, ObjCTypes)
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002667 };
Daniel Dunbarb036db82008-08-13 03:21:16 +00002668
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002669 // Return null if no extension bits are used.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002670 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002671 Values[3]->isNullValue() && Values[4]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002672 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002673
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002674 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002675 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002676
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002677 // No special section, but goes in llvm.used
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002678 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002679 Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002680 0, 0, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002681}
2682
2683/*
2684 struct objc_protocol_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002685 struct objc_protocol_list *next;
2686 long count;
2687 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002688 };
2689*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00002690llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002691CGObjCMac::EmitProtocolList(Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00002692 ObjCProtocolDecl::protocol_iterator begin,
2693 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendlinga515b582012-02-09 22:16:49 +00002694 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbarb036db82008-08-13 03:21:16 +00002695
Daniel Dunbardec75f82008-08-21 21:57:41 +00002696 for (; begin != end; ++begin)
2697 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002698
2699 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002700 if (ProtocolRefs.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002701 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002702
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002703 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00002704 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbarb036db82008-08-13 03:21:16 +00002705
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002706 llvm::Constant *Values[3];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002707 // This field is only used by the runtime.
Owen Anderson0b75f232009-07-31 20:28:54 +00002708 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002709 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002710 ProtocolRefs.size() - 1);
2711 Values[2] =
2712 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
2713 ProtocolRefs.size()),
Daniel Dunbarb036db82008-08-13 03:21:16 +00002714 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002715
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002716 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002717 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002718 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002719 4, false);
Owen Andersonade90fd2009-07-29 18:54:39 +00002720 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002721}
2722
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002723void CGObjCCommonMac::
2724PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
Bill Wendlinga515b582012-02-09 22:16:49 +00002725 llvm::SmallVectorImpl<llvm::Constant*> &Properties,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002726 const Decl *Container,
2727 const ObjCProtocolDecl *PROTO,
2728 const ObjCCommonTypesHelper &ObjCTypes) {
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002729 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
2730 E = PROTO->protocol_end(); P != E; ++P)
2731 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
2732 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
2733 E = PROTO->prop_end(); I != E; ++I) {
David Blaikie40ed2972012-06-06 20:45:41 +00002734 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002735 if (!PropertySet.insert(PD->getIdentifier()))
2736 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002737 llvm::Constant *Prop[] = {
2738 GetPropertyName(PD->getIdentifier()),
2739 GetPropertyTypeString(PD, Container)
2740 };
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002741 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
2742 }
2743}
2744
Daniel Dunbarb036db82008-08-13 03:21:16 +00002745/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002746 struct _objc_property {
Bill Wendlinga515b582012-02-09 22:16:49 +00002747 const char * const name;
2748 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002749 };
2750
2751 struct _objc_property_list {
Bill Wendlinga515b582012-02-09 22:16:49 +00002752 uint32_t entsize; // sizeof (struct _objc_property)
2753 uint32_t prop_count;
2754 struct _objc_property[prop_count];
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002755 };
2756*/
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002757llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002758 const Decl *Container,
2759 const ObjCContainerDecl *OCD,
2760 const ObjCCommonTypesHelper &ObjCTypes) {
Bill Wendlinga515b582012-02-09 22:16:49 +00002761 llvm::SmallVector<llvm::Constant*, 16> Properties;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002762 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002763 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2764 E = OCD->prop_end(); I != E; ++I) {
David Blaikie40ed2972012-06-06 20:45:41 +00002765 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00002766 PropertySet.insert(PD->getIdentifier());
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002767 llvm::Constant *Prop[] = {
2768 GetPropertyName(PD->getIdentifier()),
2769 GetPropertyTypeString(PD, Container)
2770 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00002771 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002772 Prop));
2773 }
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002774 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002775 for (ObjCInterfaceDecl::all_protocol_iterator
2776 P = OID->all_referenced_protocol_begin(),
2777 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00002778 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2779 ObjCTypes);
2780 }
2781 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2782 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
2783 E = CD->protocol_end(); P != E; ++P)
2784 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2785 ObjCTypes);
2786 }
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002787
2788 // Return null for empty list.
2789 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002790 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002791
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002792 unsigned PropertySize =
Micah Villmowdd31ca12012-10-08 16:25:52 +00002793 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002794 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002795 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2796 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002797 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002798 Properties.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002799 Values[2] = llvm::ConstantArray::get(AT, Properties);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002800 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002801
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002802 llvm::GlobalVariable *GV =
2803 CreateMetadataVar(Name, Init,
2804 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002805 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002806 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002807 true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002808 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002809}
2810
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002811llvm::Constant *
2812CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
2813 ArrayRef<llvm::Constant*> MethodTypes,
2814 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilson5f4e3a72011-11-30 01:57:58 +00002815 // Return null for empty list.
2816 if (MethodTypes.empty())
2817 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
2818
2819 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
2820 MethodTypes.size());
2821 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
2822
2823 llvm::GlobalVariable *GV =
2824 CreateMetadataVar(Name, Init,
2825 (ObjCABI == 2) ? "__DATA, __objc_const" : 0,
2826 (ObjCABI == 2) ? 8 : 4,
2827 true);
2828 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
2829}
2830
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002831/*
Daniel Dunbarb036db82008-08-13 03:21:16 +00002832 struct objc_method_description_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002833 int count;
2834 struct objc_method_description list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00002835 };
2836*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002837llvm::Constant *
2838CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002839 llvm::Constant *Desc[] = {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002840 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00002841 ObjCTypes.SelectorPtrTy),
2842 GetMethodVarType(MD)
2843 };
Douglas Gregora9d84932011-05-27 01:19:52 +00002844 if (!Desc[1])
2845 return 0;
2846
Owen Anderson0e0189d2009-07-27 22:29:56 +00002847 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002848 Desc);
2849}
Daniel Dunbarb036db82008-08-13 03:21:16 +00002850
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00002851llvm::Constant *
2852CGObjCMac::EmitMethodDescList(Twine Name, const char *Section,
2853 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002854 // Return null for empty list.
2855 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002856 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002857
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002858 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002859 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002860 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002861 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002862 Values[1] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002863 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002864
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002865 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002866 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002867 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002868}
2869
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002870/*
2871 struct _objc_category {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002872 char *category_name;
2873 char *class_name;
2874 struct _objc_method_list *instance_methods;
2875 struct _objc_method_list *class_methods;
2876 struct _objc_protocol_list *protocols;
2877 uint32_t size; // <rdar://4585769>
2878 struct _objc_property_list *instance_properties;
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002879 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002880*/
Daniel Dunbar92992502008-08-15 22:20:32 +00002881void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00002882 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002883
Mike Stump18bb9282009-05-16 07:57:57 +00002884 // FIXME: This is poor design, the OCD should have a pointer to the category
2885 // decl. Additionally, note that Category can be null for the @implementation
2886 // w/o an @interface case. Sema should just create one for us as it does for
2887 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002888 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002889 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002890 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002891
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002892 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002893 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2894 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002895
Bill Wendlinga515b582012-02-09 22:16:49 +00002896 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002897 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002898 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002899 // Instance methods should always be defined.
2900 InstanceMethods.push_back(GetMethodConstant(*i));
2901 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002902 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002903 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002904 // Class methods should always be defined.
2905 ClassMethods.push_back(GetMethodConstant(*i));
2906 }
2907
Chris Lattnere64d7ba2011-06-20 04:01:35 +00002908 llvm::Constant *Values[7];
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002909 Values[0] = GetClassName(OCD->getIdentifier());
2910 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahaniane55f8662009-04-29 20:40:05 +00002911 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002912 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002913 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002914 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002915 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002916 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002917 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002918 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002919 ClassMethods);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002920 if (Category) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002921 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002922 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002923 Category->protocol_begin(),
2924 Category->protocol_end());
2925 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002926 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002927 }
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002928 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002929
2930 // If there is no category @interface then there can be no properties.
2931 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002932 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002933 OCD, Category, ObjCTypes);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002934 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002935 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002936 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002937
Owen Anderson0e0189d2009-07-27 22:29:56 +00002938 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002939 Values);
2940
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002941 llvm::GlobalVariable *GV =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002942 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002943 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002944 4, true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002945 DefinedCategories.push_back(GV);
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00002946 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002947 // method definition entries must be clear for next implementation.
2948 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002949}
2950
John McCallef19dbb2012-10-17 04:53:23 +00002951enum FragileClassFlags {
2952 FragileABI_Class_Factory = 0x00001,
2953 FragileABI_Class_Meta = 0x00002,
2954 FragileABI_Class_HasCXXStructors = 0x02000,
2955 FragileABI_Class_Hidden = 0x20000
2956};
2957
2958enum NonFragileClassFlags {
2959 /// Is a meta-class.
2960 NonFragileABI_Class_Meta = 0x00001,
2961
2962 /// Is a root class.
2963 NonFragileABI_Class_Root = 0x00002,
2964
2965 /// Has a C++ constructor and destructor.
2966 NonFragileABI_Class_HasCXXStructors = 0x00004,
2967
2968 /// Has hidden visibility.
2969 NonFragileABI_Class_Hidden = 0x00010,
2970
2971 /// Has the exception attribute.
2972 NonFragileABI_Class_Exception = 0x00020,
2973
2974 /// (Obsolete) ARC-specific: this class has a .release_ivars method
2975 NonFragileABI_Class_HasIvarReleaser = 0x00040,
2976
2977 /// Class implementation was compiled under ARC.
John McCall0d54a172012-10-17 04:53:31 +00002978 NonFragileABI_Class_CompiledByARC = 0x00080,
2979
2980 /// Class has non-trivial destructors, but zero-initialization is okay.
2981 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002982};
2983
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002984/*
2985 struct _objc_class {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002986 Class isa;
2987 Class super_class;
2988 const char *name;
2989 long version;
2990 long info;
2991 long instance_size;
2992 struct _objc_ivar_list *ivars;
2993 struct _objc_method_list *methods;
2994 struct _objc_cache *cache;
2995 struct _objc_protocol_list *protocols;
2996 // Objective-C 1.0 extensions (<rdr://4585769>)
2997 const char *ivar_layout;
2998 struct _objc_class_ext *ext;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002999 };
3000
3001 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003002*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003003void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003004 DefinedSymbols.insert(ID->getIdentifier());
3005
Chris Lattner86d7d912008-11-24 03:54:41 +00003006 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003007 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003008 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003009 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003010 llvm::Constant *Protocols =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003011 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003012 Interface->all_referenced_protocol_begin(),
3013 Interface->all_referenced_protocol_end());
John McCallef19dbb2012-10-17 04:53:23 +00003014 unsigned Flags = FragileABI_Class_Factory;
John McCall0d54a172012-10-17 04:53:31 +00003015 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCallef19dbb2012-10-17 04:53:23 +00003016 Flags |= FragileABI_Class_HasCXXStructors;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003017 unsigned Size =
Ken Dyckc8ae5502011-02-09 01:59:34 +00003018 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003019
3020 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00003021 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003022 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003023
Bill Wendlinga515b582012-02-09 22:16:49 +00003024 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003025 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003026 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003027 // Instance methods should always be defined.
3028 InstanceMethods.push_back(GetMethodConstant(*i));
3029 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003030 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003031 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003032 // Class methods should always be defined.
3033 ClassMethods.push_back(GetMethodConstant(*i));
3034 }
3035
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003036 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003037 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie40ed2972012-06-06 20:45:41 +00003038 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003039
3040 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3041 ObjCPropertyDecl *PD = PID->getPropertyDecl();
3042
3043 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
3044 if (llvm::Constant *C = GetMethodConstant(MD))
3045 InstanceMethods.push_back(C);
3046 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
3047 if (llvm::Constant *C = GetMethodConstant(MD))
3048 InstanceMethods.push_back(C);
3049 }
3050 }
3051
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003052 llvm::Constant *Values[12];
Daniel Dunbarccf61832009-05-03 08:56:52 +00003053 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003054 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003055 // Record a reference to the super class.
3056 LazySymbols.insert(Super->getIdentifier());
3057
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003058 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003059 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003060 ObjCTypes.ClassPtrTy);
3061 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00003062 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003063 }
3064 Values[ 2] = GetClassName(ID->getIdentifier());
3065 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003066 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3067 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3068 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003069 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003070 Values[ 7] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003071 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003072 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003073 InstanceMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003074 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003075 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003076 Values[ 9] = Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003077 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003078 Values[11] = EmitClassExtension(ID);
Owen Anderson0e0189d2009-07-27 22:29:56 +00003079 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003080 Values);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003081 std::string Name("\01L_OBJC_CLASS_");
3082 Name += ClassName;
3083 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3084 // Check for a forward reference.
3085 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
3086 if (GV) {
3087 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3088 "Forward metaclass reference has incorrect type.");
3089 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
3090 GV->setInitializer(Init);
3091 GV->setSection(Section);
3092 GV->setAlignment(4);
3093 CGM.AddUsedGlobal(GV);
3094 }
3095 else
3096 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003097 DefinedClasses.push_back(GV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00003098 // method definition entries must be clear for next implementation.
3099 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003100}
3101
3102llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3103 llvm::Constant *Protocols,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003104 ArrayRef<llvm::Constant*> Methods) {
John McCallef19dbb2012-10-17 04:53:23 +00003105 unsigned Flags = FragileABI_Class_Meta;
Micah Villmowdd31ca12012-10-08 16:25:52 +00003106 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003107
John McCall457a04e2010-10-22 21:05:15 +00003108 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCallef19dbb2012-10-17 04:53:23 +00003109 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003110
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003111 llvm::Constant *Values[12];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003112 // The isa for the metaclass is the root of the hierarchy.
3113 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3114 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3115 Root = Super;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003116 Values[ 0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003117 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003118 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003119 // The super class for the metaclass is emitted as the name of the
3120 // super class. The runtime fixes this up to point to the
3121 // *metaclass* for the super class.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003122 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003123 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003124 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003125 ObjCTypes.ClassPtrTy);
3126 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00003127 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003128 }
3129 Values[ 2] = GetClassName(ID->getIdentifier());
3130 // Version is always 0.
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003131 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3132 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3133 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003134 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003135 Values[ 7] =
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00003136 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003137 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003138 Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003139 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003140 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003141 Values[ 9] = Protocols;
3142 // ivar_layout for metaclass is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00003143 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003144 // The class extension is always unused for metaclasses.
Owen Anderson0b75f232009-07-31 20:28:54 +00003145 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00003146 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003147 Values);
3148
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003149 std::string Name("\01L_OBJC_METACLASS_");
Benjamin Kramer1bbcbd02012-07-31 11:45:39 +00003150 Name += ID->getName();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003151
3152 // Check for a forward reference.
3153 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
3154 if (GV) {
3155 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3156 "Forward metaclass reference has incorrect type.");
3157 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
3158 GV->setInitializer(Init);
3159 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00003160 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003161 llvm::GlobalValue::InternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00003162 Init, Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003163 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003164 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbarae333842009-03-09 22:18:41 +00003165 GV->setAlignment(4);
Chris Lattnerf56501c2009-07-17 23:57:13 +00003166 CGM.AddUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003167
3168 return GV;
3169}
3170
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003171llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00003172 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003173
Mike Stump18bb9282009-05-16 07:57:57 +00003174 // FIXME: Should we look these up somewhere other than the module. Its a bit
3175 // silly since we only generate these while processing an implementation, so
3176 // exactly one pointer would work if know when we entered/exitted an
3177 // implementation block.
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003178
3179 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-01-07 20:11:22 +00003180 // Previously, metaclass with internal linkage may have been defined.
3181 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003182 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
3183 true)) {
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003184 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3185 "Forward metaclass reference has incorrect type.");
3186 return GV;
3187 } else {
3188 // Generate as an external reference to keep a consistent
3189 // module. This will be patched up when we emit the metaclass.
Owen Andersonc10c8d32009-07-08 19:05:04 +00003190 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003191 llvm::GlobalValue::ExternalLinkage,
3192 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00003193 Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00003194 }
3195}
3196
Fariborz Jahanianeb80c982009-11-12 20:14:24 +00003197llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
3198 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
3199
3200 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
3201 true)) {
3202 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3203 "Forward class metadata reference has incorrect type.");
3204 return GV;
3205 } else {
3206 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
3207 llvm::GlobalValue::ExternalLinkage,
3208 0,
3209 Name);
3210 }
3211}
3212
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003213/*
3214 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003215 uint32_t size;
3216 const char *weak_ivar_layout;
3217 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003218 };
3219*/
3220llvm::Constant *
3221CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003222 uint64_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00003223 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003224
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003225 llvm::Constant *Values[3];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003226 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian6df69862009-04-22 23:00:43 +00003227 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003228 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00003229 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003230
3231 // Return null if no extension bits are used.
3232 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00003233 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003234
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003235 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00003236 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003237 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003238 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003239 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003240}
3241
3242/*
3243 struct objc_ivar {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003244 char *ivar_name;
3245 char *ivar_type;
3246 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003247 };
3248
3249 struct objc_ivar_list {
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00003250 int ivar_count;
3251 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003252 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003253*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003254llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00003255 bool ForClass) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003256 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003257
3258 // When emitting the root class GCC emits ivar entries for the
3259 // actual class structure. It is not clear if we need to follow this
3260 // behavior; for now lets try and get away with not doing it. If so,
3261 // the cleanest solution would be to make up an ObjCInterfaceDecl
3262 // for the class.
3263 if (ForClass)
Owen Anderson0b75f232009-07-31 20:28:54 +00003264 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003265
Jordy Rosea91768e2011-07-22 02:08:32 +00003266 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003267
Jordy Rosea91768e2011-07-22 02:08:32 +00003268 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00003269 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00003270 // Ignore unnamed bit-fields.
3271 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003272 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003273 llvm::Constant *Ivar[] = {
3274 GetMethodVarName(IVD->getIdentifier()),
3275 GetMethodVarType(IVD),
3276 llvm::ConstantInt::get(ObjCTypes.IntTy,
Eli Friedman8cbca202012-11-06 22:15:52 +00003277 ComputeIvarBaseOffset(CGM, OID, IVD))
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003278 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00003279 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003280 }
3281
3282 // Return null for empty list.
3283 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003284 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003285
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003286 llvm::Constant *Values[2];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003287 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00003288 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003289 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00003290 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003291 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003292
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003293 llvm::GlobalVariable *GV;
3294 if (ForClass)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003295 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003296 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003297 4, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003298 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003299 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003300 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003301 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003302 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003303}
3304
3305/*
3306 struct objc_method {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003307 SEL method_name;
3308 char *method_types;
3309 void *method;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003310 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003311
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003312 struct objc_method_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003313 struct objc_method_list *obsolete;
3314 int count;
3315 struct objc_method methods_list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003316 };
3317*/
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003318
3319/// GetMethodConstant - Return a struct objc_method constant for the
3320/// given method if it has been defined. The result is null if the
3321/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00003322llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00003323 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003324 if (!Fn)
3325 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003326
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003327 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00003328 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00003329 ObjCTypes.SelectorPtrTy),
3330 GetMethodVarType(MD),
3331 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
3332 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00003333 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003334}
3335
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003336llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003337 const char *Section,
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00003338 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003339 // Return null for empty list.
3340 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00003341 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003342
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003343 llvm::Constant *Values[3];
Owen Anderson0b75f232009-07-31 20:28:54 +00003344 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003345 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00003346 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003347 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00003348 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003349 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003350
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003351 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00003352 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003353}
3354
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00003355llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003356 const ObjCContainerDecl *CD) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00003357 SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00003358 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003359
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00003360 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2192fe52011-07-18 04:24:23 +00003361 llvm::FunctionType *MethodTy =
John McCalla729c622012-02-17 03:33:10 +00003362 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003363 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00003364 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003365 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00003366 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003367 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003368 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003369
Daniel Dunbara94ecd22008-08-16 03:19:19 +00003370 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003371}
3372
Daniel Dunbar30c65362009-03-09 20:09:19 +00003373llvm::GlobalVariable *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003374CGObjCCommonMac::CreateMetadataVar(Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00003375 llvm::Constant *Init,
3376 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003377 unsigned Align,
3378 bool AddToUsed) {
Chris Lattner2192fe52011-07-18 04:24:23 +00003379 llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003380 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00003381 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerf56501c2009-07-17 23:57:13 +00003382 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003383 if (Section)
3384 GV->setSection(Section);
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00003385 if (Align)
3386 GV->setAlignment(Align);
3387 if (AddToUsed)
Chris Lattnerf56501c2009-07-17 23:57:13 +00003388 CGM.AddUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00003389 return GV;
3390}
3391
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003392llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003393 // Abuse this interface function as a place to finalize.
3394 FinishModule();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00003395 return NULL;
3396}
3397
Chris Lattnerd4808922009-03-22 21:03:39 +00003398llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003399 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003400}
3401
Chris Lattnerd4808922009-03-22 21:03:39 +00003402llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003403 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00003404}
3405
Ted Kremeneke65b0862012-03-06 20:05:56 +00003406llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3407 bool copy) {
3408 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3409}
3410
David Chisnall168b80f2010-12-26 22:13:16 +00003411llvm::Constant *CGObjCMac::GetGetStructFunction() {
3412 return ObjCTypes.getCopyStructFn();
3413}
3414llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00003415 return ObjCTypes.getCopyStructFn();
3416}
3417
David Chisnall0d75e062012-12-17 18:54:24 +00003418llvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() {
3419 return ObjCTypes.getCppAtomicObjectFunction();
3420}
3421llvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() {
Fariborz Jahanian1e1b5492012-01-06 18:07:23 +00003422 return ObjCTypes.getCppAtomicObjectFunction();
3423}
3424
Chris Lattnerd4808922009-03-22 21:03:39 +00003425llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00003426 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00003427}
3428
John McCallbd309292010-07-06 01:34:17 +00003429void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
3430 return EmitTryOrSynchronizedStmt(CGF, S);
3431}
3432
3433void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
3434 const ObjCAtSynchronizedStmt &S) {
3435 return EmitTryOrSynchronizedStmt(CGF, S);
3436}
3437
John McCall65bea082010-07-21 06:59:36 +00003438namespace {
John McCallcda666c2010-07-21 07:22:38 +00003439 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00003440 const Stmt &S;
John McCall2dd7d442010-08-04 05:59:32 +00003441 llvm::Value *SyncArgSlot;
John McCall65bea082010-07-21 06:59:36 +00003442 llvm::Value *CallTryExitVar;
3443 llvm::Value *ExceptionData;
3444 ObjCTypesHelper &ObjCTypes;
3445 PerformFragileFinally(const Stmt *S,
John McCall2dd7d442010-08-04 05:59:32 +00003446 llvm::Value *SyncArgSlot,
John McCall65bea082010-07-21 06:59:36 +00003447 llvm::Value *CallTryExitVar,
3448 llvm::Value *ExceptionData,
3449 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00003450 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-07-21 06:59:36 +00003451 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
3452
John McCall30317fd2011-07-12 20:27:29 +00003453 void Emit(CodeGenFunction &CGF, Flags flags) {
John McCall65bea082010-07-21 06:59:36 +00003454 // Check whether we need to call objc_exception_try_exit.
3455 // In optimized code, this branch will always be folded.
3456 llvm::BasicBlock *FinallyCallExit =
3457 CGF.createBasicBlock("finally.call_exit");
3458 llvm::BasicBlock *FinallyNoCallExit =
3459 CGF.createBasicBlock("finally.no_call_exit");
3460 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
3461 FinallyCallExit, FinallyNoCallExit);
3462
3463 CGF.EmitBlock(FinallyCallExit);
3464 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
3465 ->setDoesNotThrow();
3466
3467 CGF.EmitBlock(FinallyNoCallExit);
3468
3469 if (isa<ObjCAtTryStmt>(S)) {
3470 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCallcebe0ca2010-08-11 00:16:14 +00003471 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
3472 // Save the current cleanup destination in case there's
3473 // control flow inside the finally statement.
3474 llvm::Value *CurCleanupDest =
3475 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
3476
John McCall65bea082010-07-21 06:59:36 +00003477 CGF.EmitStmt(FinallyStmt->getFinallyBody());
3478
John McCallcebe0ca2010-08-11 00:16:14 +00003479 if (CGF.HaveInsertPoint()) {
3480 CGF.Builder.CreateStore(CurCleanupDest,
3481 CGF.getNormalCleanupDestSlot());
3482 } else {
3483 // Currently, the end of the cleanup must always exist.
3484 CGF.EnsureInsertPoint();
3485 }
3486 }
John McCall65bea082010-07-21 06:59:36 +00003487 } else {
3488 // Emit objc_sync_exit(expr); as finally's sole statement for
3489 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00003490 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall65bea082010-07-21 06:59:36 +00003491 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
3492 ->setDoesNotThrow();
3493 }
3494 }
3495 };
John McCall42227ed2010-07-31 23:20:56 +00003496
3497 class FragileHazards {
3498 CodeGenFunction &CGF;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003499 SmallVector<llvm::Value*, 20> Locals;
John McCall42227ed2010-07-31 23:20:56 +00003500 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
3501
3502 llvm::InlineAsm *ReadHazard;
3503 llvm::InlineAsm *WriteHazard;
3504
3505 llvm::FunctionType *GetAsmFnType();
3506
3507 void collectLocals();
3508 void emitReadHazard(CGBuilderTy &Builder);
3509
3510 public:
3511 FragileHazards(CodeGenFunction &CGF);
John McCall2dd7d442010-08-04 05:59:32 +00003512
John McCall42227ed2010-07-31 23:20:56 +00003513 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00003514 void emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003515 };
3516}
3517
3518/// Create the fragile-ABI read and write hazards based on the current
3519/// state of the function, which is presumed to be immediately prior
3520/// to a @try block. These hazards are used to maintain correct
3521/// semantics in the face of optimization and the fragile ABI's
3522/// cavalier use of setjmp/longjmp.
3523FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
3524 collectLocals();
3525
3526 if (Locals.empty()) return;
3527
3528 // Collect all the blocks in the function.
3529 for (llvm::Function::iterator
3530 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
3531 BlocksBeforeTry.insert(&*I);
3532
3533 llvm::FunctionType *AsmFnTy = GetAsmFnType();
3534
3535 // Create a read hazard for the allocas. This inhibits dead-store
3536 // optimizations and forces the values to memory. This hazard is
3537 // inserted before any 'throwing' calls in the protected scope to
3538 // reflect the possibility that the variables might be read from the
3539 // catch block if the call throws.
3540 {
3541 std::string Constraint;
3542 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3543 if (I) Constraint += ',';
3544 Constraint += "*m";
3545 }
3546
3547 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3548 }
3549
3550 // Create a write hazard for the allocas. This inhibits folding
3551 // loads across the hazard. This hazard is inserted at the
3552 // beginning of the catch path to reflect the possibility that the
3553 // variables might have been written within the protected scope.
3554 {
3555 std::string Constraint;
3556 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3557 if (I) Constraint += ',';
3558 Constraint += "=*m";
3559 }
3560
3561 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3562 }
3563}
3564
3565/// Emit a write hazard at the current location.
3566void FragileHazards::emitWriteHazard() {
3567 if (Locals.empty()) return;
3568
Jay Foad5bd375a2011-07-15 08:37:34 +00003569 CGF.Builder.CreateCall(WriteHazard, Locals)->setDoesNotThrow();
John McCall42227ed2010-07-31 23:20:56 +00003570}
3571
John McCall42227ed2010-07-31 23:20:56 +00003572void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
3573 assert(!Locals.empty());
Jay Foad5bd375a2011-07-15 08:37:34 +00003574 Builder.CreateCall(ReadHazard, Locals)->setDoesNotThrow();
John McCall42227ed2010-07-31 23:20:56 +00003575}
3576
3577/// Emit read hazards in all the protected blocks, i.e. all the blocks
3578/// which have been inserted since the beginning of the try.
John McCall2dd7d442010-08-04 05:59:32 +00003579void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-07-31 23:20:56 +00003580 if (Locals.empty()) return;
3581
3582 CGBuilderTy Builder(CGF.getLLVMContext());
3583
3584 // Iterate through all blocks, skipping those prior to the try.
3585 for (llvm::Function::iterator
3586 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
3587 llvm::BasicBlock &BB = *FI;
3588 if (BlocksBeforeTry.count(&BB)) continue;
3589
3590 // Walk through all the calls in the block.
3591 for (llvm::BasicBlock::iterator
3592 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
3593 llvm::Instruction &I = *BI;
3594
3595 // Ignore instructions that aren't non-intrinsic calls.
3596 // These are the only calls that can possibly call longjmp.
3597 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
3598 if (isa<llvm::IntrinsicInst>(I))
3599 continue;
3600
3601 // Ignore call sites marked nounwind. This may be questionable,
3602 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
3603 llvm::CallSite CS(&I);
3604 if (CS.doesNotThrow()) continue;
3605
John McCall2dd7d442010-08-04 05:59:32 +00003606 // Insert a read hazard before the call. This will ensure that
3607 // any writes to the locals are performed before making the
3608 // call. If the call throws, then this is sufficient to
3609 // guarantee correctness as long as it doesn't also write to any
3610 // locals.
John McCall42227ed2010-07-31 23:20:56 +00003611 Builder.SetInsertPoint(&BB, BI);
3612 emitReadHazard(Builder);
3613 }
3614 }
3615}
3616
3617static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
3618 if (V) S.insert(V);
3619}
3620
3621void FragileHazards::collectLocals() {
3622 // Compute a set of allocas to ignore.
3623 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
3624 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
3625 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall42227ed2010-07-31 23:20:56 +00003626
3627 // Collect all the allocas currently in the function. This is
3628 // probably way too aggressive.
3629 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
3630 for (llvm::BasicBlock::iterator
3631 I = Entry.begin(), E = Entry.end(); I != E; ++I)
3632 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
3633 Locals.push_back(&*I);
3634}
3635
3636llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003637 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall9dc0db22011-05-15 01:53:33 +00003638 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
3639 tys[i] = Locals[i]->getType();
3640 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCall65bea082010-07-21 06:59:36 +00003641}
3642
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003643/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003644
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003645 Objective-C setjmp-longjmp (sjlj) Exception Handling
3646 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003647
John McCallbd309292010-07-06 01:34:17 +00003648 A catch buffer is a setjmp buffer plus:
3649 - a pointer to the exception that was caught
3650 - a pointer to the previous exception data buffer
3651 - two pointers of reserved storage
3652 Therefore catch buffers form a stack, with a pointer to the top
3653 of the stack kept in thread-local storage.
3654
3655 objc_exception_try_enter pushes a catch buffer onto the EH stack.
3656 objc_exception_try_exit pops the given catch buffer, which is
3657 required to be the top of the EH stack.
3658 objc_exception_throw pops the top of the EH stack, writes the
3659 thrown exception into the appropriate field, and longjmps
3660 to the setjmp buffer. It crashes the process (with a printf
3661 and an abort()) if there are no catch buffers on the stack.
3662 objc_exception_extract just reads the exception pointer out of the
3663 catch buffer.
3664
3665 There's no reason an implementation couldn't use a light-weight
3666 setjmp here --- something like __builtin_setjmp, but API-compatible
3667 with the heavyweight setjmp. This will be more important if we ever
3668 want to implement correct ObjC/C++ exception interactions for the
3669 fragile ABI.
3670
3671 Note that for this use of setjmp/longjmp to be correct, we may need
3672 to mark some local variables volatile: if a non-volatile local
3673 variable is modified between the setjmp and the longjmp, it has
3674 indeterminate value. For the purposes of LLVM IR, it may be
3675 sufficient to make loads and stores within the @try (to variables
3676 declared outside the @try) volatile. This is necessary for
3677 optimized correctness, but is not currently being done; this is
3678 being tracked as rdar://problem/8160285
3679
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003680 The basic framework for a @try-catch-finally is as follows:
3681 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003682 objc_exception_data d;
3683 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00003684 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003685
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003686 objc_exception_try_enter(&d);
3687 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003688 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003689 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003690 // exception path
3691 id _caught = objc_exception_extract(&d);
3692
3693 // enter new try scope for handlers
3694 if (!setjmp(d.jmp_buf)) {
3695 ... match exception and execute catch blocks ...
3696
3697 // fell off end, rethrow.
3698 _rethrow = _caught;
3699 ... jump-through-finally to finally_rethrow ...
3700 } else {
3701 // exception in catch block
3702 _rethrow = objc_exception_extract(&d);
3703 _call_try_exit = false;
3704 ... jump-through-finally to finally_rethrow ...
3705 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003706 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003707 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003708
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003709 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00003710 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003711 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00003712
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003713 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003714 ... dispatch to finally destination ...
3715
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003716 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003717 objc_exception_throw(_rethrow);
3718
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003719 finally_end:
3720 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003721
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003722 This framework differs slightly from the one gcc uses, in that gcc
3723 uses _rethrow to determine if objc_exception_try_exit should be called
3724 and if the object should be rethrown. This breaks in the face of
3725 throwing nil and introduces unnecessary branches.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003726
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003727 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003728
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003729 - If there are no catch blocks, then we avoid emitting the second
3730 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003731
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003732 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
3733 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003734
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003735 - FIXME: If there is no @finally block we can do a few more
3736 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003737
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003738 Rethrows and Jumps-Through-Finally
3739 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003740
John McCallbd309292010-07-06 01:34:17 +00003741 '@throw;' is supported by pushing the currently-caught exception
3742 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003743
John McCallbd309292010-07-06 01:34:17 +00003744 Branches through the @finally block are handled with an ordinary
3745 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
3746 exceptions are not compatible with C++ exceptions, and this is
3747 hardly the only place where this will go wrong.
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003748
John McCallbd309292010-07-06 01:34:17 +00003749 @synchronized(expr) { stmt; } is emitted as if it were:
3750 id synch_value = expr;
3751 objc_sync_enter(synch_value);
3752 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003753*/
3754
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00003755void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
3756 const Stmt &S) {
3757 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-07-06 01:34:17 +00003758
3759 // A destination for the fall-through edges of the catch handlers to
3760 // jump to.
3761 CodeGenFunction::JumpDest FinallyEnd =
3762 CGF.getJumpDestInCurrentScope("finally.end");
3763
3764 // A destination for the rethrow edge of the catch handlers to jump
3765 // to.
3766 CodeGenFunction::JumpDest FinallyRethrow =
3767 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003768
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003769 // For @synchronized, call objc_sync_enter(sync.expr). The
3770 // evaluation of the expression must occur before we enter the
John McCall2dd7d442010-08-04 05:59:32 +00003771 // @synchronized. We can't avoid a temp here because we need the
3772 // value to be preserved. If the backend ever does liveness
3773 // correctly after setjmp, this will be unnecessary.
3774 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003775 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00003776 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003777 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
3778 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallbd309292010-07-06 01:34:17 +00003779 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
3780 ->setDoesNotThrow();
John McCall2dd7d442010-08-04 05:59:32 +00003781
3782 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
3783 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00003784 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003785
John McCall2dd7d442010-08-04 05:59:32 +00003786 // Allocate memory for the setjmp buffer. This needs to be kept
3787 // live throughout the try and catch blocks.
3788 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
3789 "exceptiondata.ptr");
3790
John McCall42227ed2010-07-31 23:20:56 +00003791 // Create the fragile hazards. Note that this will not capture any
3792 // of the allocas required for exception processing, but will
3793 // capture the current basic block (which extends all the way to the
3794 // setjmp call) as "before the @try".
3795 FragileHazards Hazards(CGF);
3796
John McCallbd309292010-07-06 01:34:17 +00003797 // Create a flag indicating whether the cleanup needs to call
3798 // objc_exception_try_exit. This is true except when
3799 // - no catches match and we're branching through the cleanup
3800 // just to rethrow the exception, or
3801 // - a catch matched and we're falling out of the catch handler.
John McCall2dd7d442010-08-04 05:59:32 +00003802 // The setjmp-safety rule here is that we should always store to this
3803 // variable in a place that dominates the branch through the cleanup
3804 // without passing through any setjmps.
John McCallbd309292010-07-06 01:34:17 +00003805 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlssonda0e4562009-02-07 21:26:04 +00003806 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003807
John McCall9916e3f2010-10-04 23:42:51 +00003808 // A slot containing the exception to rethrow. Only needed when we
3809 // have both a @catch and a @finally.
3810 llvm::Value *PropagatingExnVar = 0;
3811
John McCallbd309292010-07-06 01:34:17 +00003812 // Push a normal cleanup to leave the try scope.
John McCallcda666c2010-07-21 07:22:38 +00003813 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00003814 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00003815 CallTryExitVar,
3816 ExceptionData,
3817 &ObjCTypes);
John McCallbd309292010-07-06 01:34:17 +00003818
3819 // Enter a try block:
3820 // - Call objc_exception_try_enter to push ExceptionData on top of
3821 // the EH stack.
3822 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3823 ->setDoesNotThrow();
3824
3825 // - Call setjmp on the exception data buffer.
3826 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3827 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3828 llvm::Value *SetJmpBuffer =
Jay Foad040dd822011-07-22 08:16:57 +00003829 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
John McCallbd309292010-07-06 01:34:17 +00003830 llvm::CallInst *SetJmpResult =
3831 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3832 SetJmpResult->setDoesNotThrow();
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003833 SetJmpResult->setCanReturnTwice();
John McCallbd309292010-07-06 01:34:17 +00003834
3835 // If setjmp returned 0, enter the protected block; otherwise,
3836 // branch to the handler.
Daniel Dunbar75283ff2008-11-11 02:29:29 +00003837 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3838 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00003839 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00003840 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3841 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003842
John McCallbd309292010-07-06 01:34:17 +00003843 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003844 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00003845 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003846 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00003847 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00003848
3849 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003850
John McCallbd309292010-07-06 01:34:17 +00003851 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00003852 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003853
John McCall42227ed2010-07-31 23:20:56 +00003854 // Don't optimize loads of the in-scope locals across this point.
3855 Hazards.emitWriteHazard();
3856
John McCallbd309292010-07-06 01:34:17 +00003857 // For a @synchronized (or a @try with no catches), just branch
3858 // through the cleanup to the rethrow block.
3859 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3860 // Tell the cleanup not to re-pop the exit.
John McCall2dd7d442010-08-04 05:59:32 +00003861 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003862 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00003863
3864 // Otherwise, we have to match against the caught exceptions.
3865 } else {
John McCall2dd7d442010-08-04 05:59:32 +00003866 // Retrieve the exception object. We may emit multiple blocks but
3867 // nothing can cross this so the value is already in SSA form.
3868 llvm::CallInst *Caught =
3869 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3870 ExceptionData, "caught");
3871 Caught->setDoesNotThrow();
3872
John McCallbd309292010-07-06 01:34:17 +00003873 // Push the exception to rethrow onto the EH value stack for the
3874 // benefit of any @throws in the handlers.
3875 CGF.ObjCEHValueStack.push_back(Caught);
3876
Douglas Gregor96c79492010-04-23 22:50:49 +00003877 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003878
John McCall2dd7d442010-08-04 05:59:32 +00003879 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallbd309292010-07-06 01:34:17 +00003880
John McCall2dd7d442010-08-04 05:59:32 +00003881 llvm::BasicBlock *CatchBlock = 0;
3882 llvm::BasicBlock *CatchHandler = 0;
3883 if (HasFinally) {
John McCall9916e3f2010-10-04 23:42:51 +00003884 // Save the currently-propagating exception before
3885 // objc_exception_try_enter clears the exception slot.
3886 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3887 "propagating_exception");
3888 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3889
John McCall2dd7d442010-08-04 05:59:32 +00003890 // Enter a new exception try block (in case a @catch block
3891 // throws an exception).
3892 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3893 ->setDoesNotThrow();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003894
John McCall2dd7d442010-08-04 05:59:32 +00003895 llvm::CallInst *SetJmpResult =
3896 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3897 "setjmp.result");
3898 SetJmpResult->setDoesNotThrow();
Bill Wendlingbd26cf92011-12-19 23:53:28 +00003899 SetJmpResult->setCanReturnTwice();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003900
John McCall2dd7d442010-08-04 05:59:32 +00003901 llvm::Value *Threw =
3902 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3903
3904 CatchBlock = CGF.createBasicBlock("catch");
3905 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3906 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3907
3908 CGF.EmitBlock(CatchBlock);
3909 }
3910
3911 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003912
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003913 // Handle catch list. As a special case we check if everything is
3914 // matched and avoid generating code for falling off the end if
3915 // so.
3916 bool AllMatched = false;
Douglas Gregor96c79492010-04-23 22:50:49 +00003917 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3918 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003919
Douglas Gregor46a572b2010-04-26 16:46:50 +00003920 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff7cae42b2009-07-10 23:34:53 +00003921 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar523208f2008-09-27 07:36:24 +00003922
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003923 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003924 if (!CatchParam) {
3925 AllMatched = true;
3926 } else {
John McCall9dd450b2009-09-21 23:43:11 +00003927 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003928
John McCallbd309292010-07-06 01:34:17 +00003929 // catch(id e) always matches under this ABI, since only
3930 // ObjC exceptions end up here in the first place.
Daniel Dunbar86919f42008-09-27 22:21:14 +00003931 // FIXME: For the time being we also match id<X>; this should
3932 // be rejected by Sema instead.
Eli Friedman55179ca2009-07-11 00:57:02 +00003933 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003934 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003935 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003936
John McCallbd309292010-07-06 01:34:17 +00003937 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003938 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00003939 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3940
Anders Carlsson9396a892008-09-11 09:15:33 +00003941 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00003942 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003943 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00003944
3945 // These types work out because ConvertType(id) == i8*.
Steve Naroff371b8fb2009-03-03 19:52:17 +00003946 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson9396a892008-09-11 09:15:33 +00003947 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003948
Anders Carlsson9396a892008-09-11 09:15:33 +00003949 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003950
3951 // The scope of the catch variable ends right here.
3952 CatchVarCleanups.ForceCleanup();
3953
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003954 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003955 break;
3956 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003957
Steve Naroff7cae42b2009-07-10 23:34:53 +00003958 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00003959 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00003960
3961 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00003962 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3963 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003964
3965 // Check if the @catch block matches the exception object.
John McCall96fa4842010-05-17 21:00:27 +00003966 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003967
John McCallbd309292010-07-06 01:34:17 +00003968 llvm::CallInst *Match =
Chris Lattnerc6406db2009-04-22 02:26:14 +00003969 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3970 Class, Caught, "match");
John McCallbd309292010-07-06 01:34:17 +00003971 Match->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003972
John McCallbd309292010-07-06 01:34:17 +00003973 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3974 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003975
3976 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00003977 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003978
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003979 // Emit the @catch block.
3980 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-07-06 01:34:17 +00003981
3982 // Collect any cleanups for the catch variable. The scope lasts until
3983 // the end of the catch body.
John McCall2dd7d442010-08-04 05:59:32 +00003984 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00003985
John McCall1c9c3fd2010-10-15 04:57:14 +00003986 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003987 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003988
John McCallbd309292010-07-06 01:34:17 +00003989 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003990 llvm::Value *Tmp =
3991 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer76399eb2011-09-27 21:06:10 +00003992 CGF.ConvertType(CatchParam->getType()));
Steve Naroff371b8fb2009-03-03 19:52:17 +00003993 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003994
Anders Carlsson9396a892008-09-11 09:15:33 +00003995 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003996
3997 // We're done with the catch variable.
3998 CatchVarCleanups.ForceCleanup();
3999
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004000 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004001
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004002 CGF.EmitBlock(NextCatchBlock);
4003 }
4004
John McCallbd309292010-07-06 01:34:17 +00004005 CGF.ObjCEHValueStack.pop_back();
4006
John McCall2dd7d442010-08-04 05:59:32 +00004007 // If nothing wanted anything to do with the caught exception,
4008 // kill the extract call.
4009 if (Caught->use_empty())
4010 Caught->eraseFromParent();
4011
4012 if (!AllMatched)
4013 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4014
4015 if (HasFinally) {
4016 // Emit the exception handler for the @catch blocks.
4017 CGF.EmitBlock(CatchHandler);
4018
4019 // In theory we might now need a write hazard, but actually it's
4020 // unnecessary because there's no local-accessing code between
4021 // the try's write hazard and here.
4022 //Hazards.emitWriteHazard();
4023
John McCall9916e3f2010-10-04 23:42:51 +00004024 // Extract the new exception and save it to the
4025 // propagating-exception slot.
4026 assert(PropagatingExnVar);
4027 llvm::CallInst *NewCaught =
4028 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
4029 ExceptionData, "caught");
4030 NewCaught->setDoesNotThrow();
4031 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4032
John McCall2dd7d442010-08-04 05:59:32 +00004033 // Don't pop the catch handler; the throw already did.
4034 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004035 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00004036 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004037 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004038
John McCall42227ed2010-07-31 23:20:56 +00004039 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00004040 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00004041
John McCallbd309292010-07-06 01:34:17 +00004042 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00004043 CGF.Builder.restoreIP(TryFallthroughIP);
4044 if (CGF.HaveInsertPoint())
4045 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00004046 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00004047 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00004048
John McCallbd309292010-07-06 01:34:17 +00004049 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00004050 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00004051 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00004052 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-10-04 23:42:51 +00004053 // If we have a propagating-exception variable, check it.
4054 llvm::Value *PropagatingExn;
4055 if (PropagatingExnVar) {
4056 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall2dd7d442010-08-04 05:59:32 +00004057
John McCall9916e3f2010-10-04 23:42:51 +00004058 // Otherwise, just look in the buffer for the exception to throw.
4059 } else {
4060 llvm::CallInst *Caught =
4061 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
4062 ExceptionData);
4063 Caught->setDoesNotThrow();
4064 PropagatingExn = Caught;
4065 }
4066
4067 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallbd309292010-07-06 01:34:17 +00004068 ->setDoesNotThrow();
4069 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00004070 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004071
John McCall42227ed2010-07-31 23:20:56 +00004072 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004073}
4074
4075void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004076 const ObjCAtThrowStmt &S,
4077 bool ClearInsertionPoint) {
Anders Carlssone005aa12008-09-09 16:16:55 +00004078 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004079
Anders Carlssone005aa12008-09-09 16:16:55 +00004080 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00004081 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004082 ExceptionAsObject =
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004083 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlssone005aa12008-09-09 16:16:55 +00004084 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004085 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00004086 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00004087 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00004088 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004089
John McCallbd309292010-07-06 01:34:17 +00004090 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4091 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00004092 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00004093
4094 // Clear the insertion point to indicate we are in unreachable code.
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00004095 if (ClearInsertionPoint)
4096 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00004097}
4098
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004099/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004100/// object: objc_read_weak (id *src)
4101///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004102llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004103 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004104 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004105 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
4106 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4107 ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00004108 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004109 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00004110 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00004111 return read_weak;
4112}
4113
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004114/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4115/// objc_assign_weak (id src, id *dst)
4116///
4117void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004118 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004119 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004120 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004121 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004122 assert(Size <= 8 && "does not support size > 8");
4123 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004124 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004125 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4126 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004127 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4128 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00004129 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00004130 src, dst, "weakassign");
4131 return;
4132}
4133
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004134/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4135/// objc_assign_global (id src, id *dst)
4136///
4137void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00004138 llvm::Value *src, llvm::Value *dst,
4139 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004140 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004141 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004142 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004143 assert(Size <= 8 && "does not support size > 8");
4144 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004145 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004146 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4147 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004148 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4149 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00004150 if (!threadlocal)
4151 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
4152 src, dst, "globalassign");
4153 else
4154 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
4155 src, dst, "threadlocalassign");
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004156 return;
4157}
4158
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004159/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004160/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004161///
4162void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004163 llvm::Value *src, llvm::Value *dst,
4164 llvm::Value *ivarOffset) {
4165 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2192fe52011-07-18 04:24:23 +00004166 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004167 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004168 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004169 assert(Size <= 8 && "does not support size > 8");
4170 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004171 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004172 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4173 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004174 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4175 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00004176 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
4177 src, dst, ivarOffset);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00004178 return;
4179}
4180
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004181/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4182/// objc_assign_strongCast (id src, id *dst)
4183///
4184void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00004185 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00004186 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004187 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004188 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004189 assert(Size <= 8 && "does not support size > 8");
4190 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004191 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00004192 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4193 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00004194 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4195 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00004196 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00004197 src, dst, "weakassign");
4198 return;
4199}
4200
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004201void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004202 llvm::Value *DestPtr,
4203 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004204 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004205 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4206 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004207 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00004208 DestPtr, SrcPtr, size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00004209 return;
4210}
4211
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004212/// EmitObjCValueForIvar - Code Gen for ivar reference.
4213///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004214LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4215 QualType ObjectTy,
4216 llvm::Value *BaseValue,
4217 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00004218 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00004219 const ObjCInterfaceDecl *ID =
4220 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00004221 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4222 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00004223}
4224
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004225llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00004226 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004227 const ObjCIvarDecl *Ivar) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004228 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4229 return llvm::ConstantInt::get(
4230 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
4231 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00004232}
4233
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004234/* *** Private Interface *** */
4235
4236/// EmitImageInfo - Emit the image info marker used to encode some module
4237/// level information.
4238///
4239/// See: <rdr://4810609&4810587&4810587>
4240/// struct IMAGE_INFO {
4241/// unsigned version;
4242/// unsigned flags;
4243/// };
4244enum ImageInfoFlags {
Daniel Dunbar5e639272010-04-25 20:39:01 +00004245 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004246 eImageInfo_GarbageCollected = (1 << 1),
4247 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbar75e909f2009-04-20 07:11:47 +00004248 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
4249
Daniel Dunbar5e639272010-04-25 20:39:01 +00004250 // A flag indicating that the module has no instances of a @synthesize of a
4251 // superclass variable. <rdar://problem/6803242>
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004252 eImageInfo_CorrectedSynthesize = (1 << 4),
4253 eImageInfo_ImageIsSimulated = (1 << 5)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004254};
4255
Daniel Dunbar5e639272010-04-25 20:39:01 +00004256void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004257 unsigned version = 0; // Version is unused?
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004258 const char *Section = (ObjCABI == 1) ?
4259 "__OBJC, __image_info,regular" :
4260 "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004261
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004262 // Generate module-level named metadata to convey this information to the
4263 // linker and code-gen.
4264 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004265
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004266 // Add the ObjC ABI version to the module flags.
4267 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
4268 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
4269 version);
4270 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
4271 llvm::MDString::get(VMContext,Section));
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004272
David Blaikiebbafb8a2012-03-11 07:00:24 +00004273 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004274 // Non-GC overrides those files which specify GC.
4275 Mod.addModuleFlag(llvm::Module::Override,
4276 "Objective-C Garbage Collection", (uint32_t)0);
4277 } else {
4278 // Add the ObjC garbage collection value.
4279 Mod.addModuleFlag(llvm::Module::Error,
4280 "Objective-C Garbage Collection",
4281 eImageInfo_GarbageCollected);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004282
David Blaikiebbafb8a2012-03-11 07:00:24 +00004283 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendlingb6f795e2012-02-16 01:13:30 +00004284 // Add the ObjC GC Only value.
4285 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
4286 eImageInfo_GCOnly);
4287
4288 // Require that GC be specified and set to eImageInfo_GarbageCollected.
4289 llvm::Value *Ops[2] = {
4290 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
4291 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
4292 eImageInfo_GarbageCollected)
4293 };
4294 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
4295 llvm::MDNode::get(VMContext, Ops));
4296 }
4297 }
Bill Wendling1e60a2c2012-04-24 11:04:57 +00004298
4299 // Indicate whether we're compiling this to run on a simulator.
4300 const llvm::Triple &Triple = CGM.getTarget().getTriple();
4301 if (Triple.getOS() == llvm::Triple::IOS &&
4302 (Triple.getArch() == llvm::Triple::x86 ||
4303 Triple.getArch() == llvm::Triple::x86_64))
4304 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
4305 eImageInfo_ImageIsSimulated);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004306}
4307
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004308// struct objc_module {
4309// unsigned long version;
4310// unsigned long size;
4311// const char *name;
4312// Symtab symtab;
4313// };
4314
4315// FIXME: Get from somewhere
4316static const int ModuleVersion = 7;
4317
4318void CGObjCMac::EmitModuleInfo() {
Micah Villmowdd31ca12012-10-08 16:25:52 +00004319 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004320
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004321 llvm::Constant *Values[] = {
4322 llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion),
4323 llvm::ConstantInt::get(ObjCTypes.LongTy, Size),
4324 // This used to be the filename, now it is unused. <rdr://4327263>
4325 GetClassName(&CGM.getContext().Idents.get("")),
4326 EmitModuleSymbols()
4327 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004328 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson0e0189d2009-07-27 22:29:56 +00004329 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004330 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00004331 4, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004332}
4333
4334llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004335 unsigned NumClasses = DefinedClasses.size();
4336 unsigned NumCategories = DefinedCategories.size();
4337
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004338 // Return null if no symbols were defined.
4339 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00004340 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004341
Chris Lattnere64d7ba2011-06-20 04:01:35 +00004342 llvm::Constant *Values[5];
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004343 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Anderson0b75f232009-07-31 20:28:54 +00004344 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00004345 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
4346 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004347
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004348 // The runtime expects exactly the list of defined classes followed
4349 // by the list of defined categories, in a single array.
Chris Lattner3def9ae2012-02-06 22:16:34 +00004350 SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004351 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00004352 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004353 ObjCTypes.Int8PtrTy);
4354 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004355 Symbols[NumClasses + i] =
Owen Andersonade90fd2009-07-29 18:54:39 +00004356 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00004357 ObjCTypes.Int8PtrTy);
4358
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004359 Values[4] =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004360 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00004361 Symbols.size()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004362 Symbols);
4363
Chris Lattnere64d7ba2011-06-20 04:01:35 +00004364 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004365
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004366 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004367 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
4368 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00004369 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00004370 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004371}
4372
John McCall31168b02011-06-15 23:02:42 +00004373llvm::Value *CGObjCMac::EmitClassRefFromId(CGBuilderTy &Builder,
4374 IdentifierInfo *II) {
4375 LazySymbols.insert(II);
4376
4377 llvm::GlobalVariable *&Entry = ClassReferences[II];
4378
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004379 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004380 llvm::Constant *Casted =
John McCall31168b02011-06-15 23:02:42 +00004381 llvm::ConstantExpr::getBitCast(GetClassName(II),
4382 ObjCTypes.ClassPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004383 Entry =
John McCall31168b02011-06-15 23:02:42 +00004384 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
4385 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
4386 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004387 }
John McCall31168b02011-06-15 23:02:42 +00004388
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004389 return Builder.CreateLoad(Entry);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004390}
4391
John McCall31168b02011-06-15 23:02:42 +00004392llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
4393 const ObjCInterfaceDecl *ID) {
4394 return EmitClassRefFromId(Builder, ID->getIdentifier());
4395}
4396
4397llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder) {
4398 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
4399 return EmitClassRefFromId(Builder, II);
4400}
4401
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00004402llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
4403 bool lvalue) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004404 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004405
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004406 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004407 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00004408 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004409 ObjCTypes.SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004410 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004411 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
4412 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00004413 4, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004414 }
4415
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00004416 if (lvalue)
4417 return Entry;
Benjamin Kramer76399eb2011-09-27 21:06:10 +00004418 return Builder.CreateLoad(Entry);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004419}
4420
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004421llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00004422 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004423
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004424 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004425 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004426 llvm::ConstantDataArray::getString(VMContext,
4427 Ident->getNameStart()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004428 ((ObjCABI == 2) ?
4429 "__TEXT,__objc_classname,cstring_literals" :
4430 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004431 1, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004432
Owen Anderson170229f2009-07-14 23:10:40 +00004433 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004434}
4435
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004436llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
4437 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
4438 I = MethodDefinitions.find(MD);
4439 if (I != MethodDefinitions.end())
4440 return I->second;
4441
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00004442 return NULL;
4443}
4444
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004445/// GetIvarLayoutName - Returns a unique constant for the given
4446/// ivar layout bitmap.
4447llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004448 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00004449 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00004450}
4451
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004452void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Eli Friedman8cbca202012-11-06 22:15:52 +00004453 unsigned int BytePos,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004454 bool ForStrongLayout,
4455 bool &HasUnion) {
4456 const RecordDecl *RD = RT->getDecl();
4457 // FIXME - Use iterator.
David Blaikie2d7c57e2012-04-30 02:36:29 +00004458 SmallVector<const FieldDecl*, 16> Fields;
4459 for (RecordDecl::field_iterator i = RD->field_begin(),
4460 e = RD->field_end(); i != e; ++i)
David Blaikie40ed2972012-06-06 20:45:41 +00004461 Fields.push_back(*i);
Chris Lattner2192fe52011-07-18 04:24:23 +00004462 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004463 const llvm::StructLayout *RecLayout =
Micah Villmowdd31ca12012-10-08 16:25:52 +00004464 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004465
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004466 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
4467 ForStrongLayout, HasUnion);
4468}
4469
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +00004470void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004471 const llvm::StructLayout *Layout,
4472 const RecordDecl *RD,
Bill Wendlingf1a3fca2012-02-22 09:30:11 +00004473 ArrayRef<const FieldDecl*> RecFields,
Eli Friedman8cbca202012-11-06 22:15:52 +00004474 unsigned int BytePos, bool ForStrongLayout,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004475 bool &HasUnion) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004476 bool IsUnion = (RD && RD->isUnion());
Eli Friedman8cbca202012-11-06 22:15:52 +00004477 uint64_t MaxUnionIvarSize = 0;
4478 uint64_t MaxSkippedUnionIvarSize = 0;
Jordy Rosea91768e2011-07-22 02:08:32 +00004479 const FieldDecl *MaxField = 0;
4480 const FieldDecl *MaxSkippedField = 0;
4481 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Eli Friedman8cbca202012-11-06 22:15:52 +00004482 uint64_t MaxFieldOffset = 0;
4483 uint64_t MaxSkippedFieldOffset = 0;
4484 uint64_t LastBitfieldOrUnnamedOffset = 0;
4485 uint64_t FirstFieldDelta = 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004486
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004487 if (RecFields.empty())
4488 return;
Eli Friedman8cbca202012-11-06 22:15:52 +00004489 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
Douglas Gregore8bbc122011-09-02 00:18:52 +00004490 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
David Blaikiebbafb8a2012-03-11 07:00:24 +00004491 if (!RD && CGM.getLangOpts().ObjCAutoRefCount) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004492 const FieldDecl *FirstField = RecFields[0];
4493 FirstFieldDelta =
4494 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
John McCall31168b02011-06-15 23:02:42 +00004495 }
4496
Chris Lattner5b36ddb2009-03-31 08:48:01 +00004497 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004498 const FieldDecl *Field = RecFields[i];
Eli Friedman8cbca202012-11-06 22:15:52 +00004499 uint64_t FieldOffset;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00004500 if (RD) {
Daniel Dunbard51c1a62010-04-14 17:02:21 +00004501 // Note that 'i' here is actually the field index inside RD of Field,
4502 // although this dependency is hidden.
4503 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Eli Friedman8cbca202012-11-06 22:15:52 +00004504 FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00004505 } else
John McCall31168b02011-06-15 23:02:42 +00004506 FieldOffset =
4507 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004508
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004509 // Skip over unnamed or bitfields
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004510 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004511 LastFieldBitfieldOrUnnamed = Field;
4512 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004513 continue;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004514 }
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004515
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004516 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004517 QualType FQT = Field->getType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004518 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004519 if (FQT->isUnionType())
4520 HasUnion = true;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004521
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004522 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004523 BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004524 ForStrongLayout, HasUnion);
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004525 continue;
4526 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004527
Chris Lattner5b36ddb2009-03-31 08:48:01 +00004528 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004529 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004530 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004531 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004532 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004533 FQT = CArray->getElementType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004534 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
4535 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004536 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004537 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004538 FQT = CArray->getElementType();
4539 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004540
4541 assert(!FQT->isUnionType() &&
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004542 "layout for array of unions not supported");
Fariborz Jahanian9a7d57d2011-01-03 19:23:18 +00004543 if (FQT->isRecordType() && ElCount) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004544 int OldIndex = IvarsInfo.size() - 1;
4545 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004546
Ted Kremenekc23c7e62009-07-29 21:53:49 +00004547 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00004548 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004549 ForStrongLayout, HasUnion);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004550
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004551 // Replicate layout information for each array element. Note that
4552 // one element is already done.
4553 uint64_t ElIx = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004554 for (int FirstIndex = IvarsInfo.size() - 1,
4555 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004556 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004557 for (int i = OldIndex+1; i <= FirstIndex; ++i)
4558 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
4559 IvarsInfo[i].ivar_size));
4560 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
4561 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
4562 SkipIvars[i].ivar_size));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004563 }
4564 continue;
4565 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +00004566 }
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004567 // At this point, we are done with Record/Union and array there of.
4568 // For other arrays we are down to its element type.
John McCall8ccfcb52009-09-24 19:53:00 +00004569 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00004570
Eli Friedman8cbca202012-11-06 22:15:52 +00004571 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall8ccfcb52009-09-24 19:53:00 +00004572 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
4573 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00004574 if (IsUnion) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004575 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00004576 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004577 MaxUnionIvarSize = UnionIvarSize;
4578 MaxField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004579 MaxFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004580 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00004581 } else {
Eli Friedman8cbca202012-11-06 22:15:52 +00004582 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
4583 FieldSize / WordSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004584 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004585 } else if ((ForStrongLayout &&
John McCall8ccfcb52009-09-24 19:53:00 +00004586 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
4587 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00004588 if (IsUnion) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004589 // FIXME: Why the asymmetry? We divide by word size in bits on other
4590 // side.
4591 uint64_t UnionIvarSize = FieldSize / ByteSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00004592 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004593 MaxSkippedUnionIvarSize = UnionIvarSize;
4594 MaxSkippedField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00004595 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004596 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00004597 } else {
Eli Friedman8cbca202012-11-06 22:15:52 +00004598 // FIXME: Why the asymmetry, we divide by byte size in bits here?
4599 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
4600 FieldSize / ByteSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00004601 }
4602 }
4603 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00004604
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004605 if (LastFieldBitfieldOrUnnamed) {
4606 if (LastFieldBitfieldOrUnnamed->isBitField()) {
4607 // Last field was a bitfield. Must update skip info.
Richard Smithcaf33902011-10-10 18:28:20 +00004608 uint64_t BitFieldSize
4609 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004610 GC_IVAR skivar;
4611 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
Eli Friedman8cbca202012-11-06 22:15:52 +00004612 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
4613 + ((BitFieldSize % ByteSizeInBits) != 0);
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004614 SkipIvars.push_back(skivar);
4615 } else {
4616 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
4617 // Last field was unnamed. Must update skip info.
Eli Friedman8cbca202012-11-06 22:15:52 +00004618 unsigned FieldSize
4619 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004620 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
Eli Friedman8cbca202012-11-06 22:15:52 +00004621 FieldSize / ByteSizeInBits));
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00004622 }
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00004623 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004624
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004625 if (MaxField)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004626 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004627 MaxUnionIvarSize));
4628 if (MaxSkippedField)
Daniel Dunbar5b743912009-05-03 23:31:46 +00004629 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00004630 MaxSkippedUnionIvarSize));
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004631}
4632
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004633/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
4634/// the computations and returning the layout bitmap (for ivar or blocks) in
4635/// the given argument BitMap string container. Routine reads
4636/// two containers, IvarsInfo and SkipIvars which are assumed to be
4637/// filled already by the caller.
Chris Lattner9c818332012-02-05 02:30:40 +00004638llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004639 unsigned int WordsToScan, WordsToSkip;
Chris Lattnerece04092012-02-07 00:39:47 +00004640 llvm::Type *PtrTy = CGM.Int8PtrTy;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004641
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004642 // Build the string of skip/scan nibbles
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004643 SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Eli Friedman8cbca202012-11-06 22:15:52 +00004644 unsigned int WordSize =
4645 CGM.getTypes().getDataLayout().getTypeAllocSize(PtrTy);
4646 if (IvarsInfo[0].ivar_bytepos == 0) {
4647 WordsToSkip = 0;
4648 WordsToScan = IvarsInfo[0].ivar_size;
4649 } else {
4650 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
4651 WordsToScan = IvarsInfo[0].ivar_size;
4652 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004653 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004654 unsigned int TailPrevGCObjC =
4655 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004656 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004657 // consecutive 'scanned' object pointers.
Eli Friedman8cbca202012-11-06 22:15:52 +00004658 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004659 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004660 // Skip over 'gc'able object pointer which lay over each other.
4661 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
4662 continue;
4663 // Must skip over 1 or more words. We save current skip/scan values
4664 // and start a new pair.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004665 SKIP_SCAN SkScan;
4666 SkScan.skip = WordsToSkip;
4667 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004668 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004669
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004670 // Skip the hole.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004671 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
4672 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004673 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004674 WordsToSkip = 0;
Eli Friedman8cbca202012-11-06 22:15:52 +00004675 WordsToScan = IvarsInfo[i].ivar_size;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004676 }
4677 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004678 if (WordsToScan > 0) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004679 SKIP_SCAN SkScan;
4680 SkScan.skip = WordsToSkip;
4681 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004682 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004683 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004684
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004685 if (!SkipIvars.empty()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004686 unsigned int LastIndex = SkipIvars.size()-1;
Eli Friedman8cbca202012-11-06 22:15:52 +00004687 int LastByteSkipped =
4688 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004689 LastIndex = IvarsInfo.size()-1;
Eli Friedman8cbca202012-11-06 22:15:52 +00004690 int LastByteScanned =
4691 IvarsInfo[LastIndex].ivar_bytepos +
4692 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004693 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramerd20ef752009-12-25 15:43:36 +00004694 if (LastByteSkipped > LastByteScanned) {
Eli Friedman8cbca202012-11-06 22:15:52 +00004695 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004696 SKIP_SCAN SkScan;
Eli Friedman8cbca202012-11-06 22:15:52 +00004697 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00004698 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004699 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004700 }
4701 }
4702 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
4703 // as 0xMN.
Fariborz Jahaniana123b642009-04-24 16:17:09 +00004704 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004705 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004706 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
4707 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
4708 // 0xM0 followed by 0x0N detected.
4709 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
4710 for (int j = i+1; j < SkipScan; j++)
4711 SkipScanIvars[j] = SkipScanIvars[j+1];
4712 --SkipScan;
4713 }
4714 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004715
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004716 // Generate the string.
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004717 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004718 unsigned char byte;
4719 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
4720 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
4721 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
4722 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004723
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004724 // first skip big.
4725 for (unsigned int ix = 0; ix < skip_big; ix++)
4726 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004727
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004728 // next (skip small, scan)
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004729 if (skip_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004730 byte = skip_small << 4;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004731 if (scan_big > 0) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004732 byte |= 0xf;
4733 --scan_big;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004734 } else if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004735 byte |= scan_small;
4736 scan_small = 0;
4737 }
4738 BitMap += byte;
4739 }
4740 // next scan big
4741 for (unsigned int ix = 0; ix < scan_big; ix++)
4742 BitMap += (unsigned char)(0x0f);
4743 // last scan small
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00004744 if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00004745 byte = scan_small;
4746 BitMap += byte;
4747 }
4748 }
4749 // null terminate string.
Fariborz Jahanianf909f922009-03-25 22:36:49 +00004750 unsigned char zero = 0;
4751 BitMap += zero;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004752
4753 llvm::GlobalVariable * Entry =
4754 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004755 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004756 ((ObjCABI == 2) ?
4757 "__TEXT,__objc_classname,cstring_literals" :
4758 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004759 1, true);
4760 return getConstantGEP(VMContext, Entry, 0, 0);
4761}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004762
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004763/// BuildIvarLayout - Builds ivar layout bitmap for the class
4764/// implementation for the __strong or __weak case.
4765/// The layout map displays which words in ivar list must be skipped
4766/// and which must be scanned by GC (see below). String is built of bytes.
4767/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
4768/// of words to skip and right nibble is count of words to scan. So, each
4769/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
4770/// represented by a 0x00 byte which also ends the string.
4771/// 1. when ForStrongLayout is true, following ivars are scanned:
4772/// - id, Class
4773/// - object *
4774/// - __strong anything
4775///
4776/// 2. When ForStrongLayout is false, following ivars are scanned:
4777/// - __weak anything
4778///
4779llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
4780 const ObjCImplementationDecl *OMD,
4781 bool ForStrongLayout) {
4782 bool hasUnion = false;
4783
Chris Lattnerece04092012-02-07 00:39:47 +00004784 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikiebbafb8a2012-03-11 07:00:24 +00004785 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
4786 !CGM.getLangOpts().ObjCAutoRefCount)
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004787 return llvm::Constant::getNullValue(PtrTy);
4788
Jordy Rosea91768e2011-07-22 02:08:32 +00004789 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
4790 SmallVector<const FieldDecl*, 32> RecFields;
David Blaikiebbafb8a2012-03-11 07:00:24 +00004791 if (CGM.getLangOpts().ObjCAutoRefCount) {
Jordy Rosea91768e2011-07-22 02:08:32 +00004792 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004793 IVD; IVD = IVD->getNextIvar())
4794 RecFields.push_back(cast<FieldDecl>(IVD));
4795 }
4796 else {
Jordy Rosea91768e2011-07-22 02:08:32 +00004797 SmallVector<const ObjCIvarDecl*, 32> Ivars;
John McCall31168b02011-06-15 23:02:42 +00004798 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004799
Jordy Rosea91768e2011-07-22 02:08:32 +00004800 // FIXME: This is not ideal; we shouldn't have to do this copy.
4801 RecFields.append(Ivars.begin(), Ivars.end());
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00004802 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004803
4804 if (RecFields.empty())
4805 return llvm::Constant::getNullValue(PtrTy);
4806
4807 SkipIvars.clear();
4808 IvarsInfo.clear();
4809
Eli Friedman8cbca202012-11-06 22:15:52 +00004810 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004811 if (IvarsInfo.empty())
4812 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004813 // Sort on byte position in case we encounterred a union nested in
4814 // the ivar list.
4815 if (hasUnion && !IvarsInfo.empty())
4816 std::sort(IvarsInfo.begin(), IvarsInfo.end());
4817 if (hasUnion && !SkipIvars.empty())
4818 std::sort(SkipIvars.begin(), SkipIvars.end());
4819
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004820 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00004821 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004822
David Blaikiebbafb8a2012-03-11 07:00:24 +00004823 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004824 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004825 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar56df9772010-08-17 22:39:59 +00004826 OMD->getClassInterface()->getName().data());
Roman Divackye6377112012-09-06 15:59:27 +00004827 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling53136852012-02-07 09:06:01 +00004828 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00004829 if (!(s[i] & 0xf0))
4830 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
4831 else
4832 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
4833 printf("\n");
4834 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00004835 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00004836}
4837
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004838llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004839 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
4840
Chris Lattner3def9ae2012-02-06 22:16:34 +00004841 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004842 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004843 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Chris Lattner9c818332012-02-05 02:30:40 +00004844 llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004845 ((ObjCABI == 2) ?
4846 "__TEXT,__objc_methname,cstring_literals" :
4847 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004848 1, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004849
Owen Anderson170229f2009-07-14 23:10:40 +00004850 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004851}
4852
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004853// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004854llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004855 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4856}
4857
Daniel Dunbarf5c18462009-04-20 06:54:31 +00004858llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004859 std::string TypeStr;
4860 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
4861
4862 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarb036db82008-08-13 03:21:16 +00004863
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004864 if (!Entry)
4865 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004866 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004867 ((ObjCABI == 2) ?
4868 "__TEXT,__objc_methtype,cstring_literals" :
4869 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004870 1, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004871
Owen Anderson170229f2009-07-14 23:10:40 +00004872 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00004873}
4874
Bob Wilson5f4e3a72011-11-30 01:57:58 +00004875llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
4876 bool Extended) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004877 std::string TypeStr;
Bill Wendlinge22bef72012-02-09 22:45:21 +00004878 if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
Douglas Gregora9d84932011-05-27 01:19:52 +00004879 return 0;
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004880
4881 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4882
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004883 if (!Entry)
4884 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner9c818332012-02-05 02:30:40 +00004885 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00004886 ((ObjCABI == 2) ?
4887 "__TEXT,__objc_methtype,cstring_literals" :
4888 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004889 1, true);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00004890
Owen Anderson170229f2009-07-14 23:10:40 +00004891 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004892}
4893
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004894// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004895llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004896 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004897
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004898 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004899 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Chris Lattner9c818332012-02-05 02:30:40 +00004900 llvm::ConstantDataArray::getString(VMContext,
4901 Ident->getNameStart()),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004902 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00004903 1, true);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004904
Owen Anderson170229f2009-07-14 23:10:40 +00004905 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004906}
4907
4908// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00004909// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004910llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004911CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4912 const Decl *Container) {
Daniel Dunbar4932b362008-08-28 04:38:10 +00004913 std::string TypeStr;
4914 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004915 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4916}
4917
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004918void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004919 const ObjCContainerDecl *CD,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004920 SmallVectorImpl<char> &Name) {
Daniel Dunbard2386812009-10-19 01:21:19 +00004921 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00004922 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00004923 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4924 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004925 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00004926 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer2f569922012-02-07 11:57:45 +00004927 OS << '(' << *CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00004928 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004929}
4930
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004931void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004932 EmitModuleInfo();
4933
Daniel Dunbarc475d422008-10-29 22:36:39 +00004934 // Emit the dummy bodies for any protocols which were referenced but
4935 // never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004936 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerf56501c2009-07-17 23:57:13 +00004937 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4938 if (I->second->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00004939 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004940
Benjamin Kramer22d24c22011-10-15 12:20:02 +00004941 llvm::Constant *Values[5];
Owen Anderson0b75f232009-07-31 20:28:54 +00004942 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004943 Values[1] = GetClassName(I->first);
Owen Anderson0b75f232009-07-31 20:28:54 +00004944 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004945 Values[3] = Values[4] =
Owen Anderson0b75f232009-07-31 20:28:54 +00004946 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004947 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004948 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarc475d422008-10-29 22:36:39 +00004949 Values));
Chris Lattnerf56501c2009-07-17 23:57:13 +00004950 CGM.AddUsedGlobal(I->second);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004951 }
4952
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004953 // Add assembler directives to add lazy undefined symbol references
4954 // for classes which are referenced but not defined. This is
4955 // important for correct linker interaction.
Daniel Dunbard027a922009-09-07 00:20:42 +00004956 //
4957 // FIXME: It would be nice if we had an LLVM construct for this.
4958 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00004959 SmallString<256> Asm;
Daniel Dunbard027a922009-09-07 00:20:42 +00004960 Asm += CGM.getModule().getModuleInlineAsm();
4961 if (!Asm.empty() && Asm.back() != '\n')
4962 Asm += '\n';
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004963
Daniel Dunbard027a922009-09-07 00:20:42 +00004964 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbard027a922009-09-07 00:20:42 +00004965 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4966 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar07d07852009-10-18 21:17:35 +00004967 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4968 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnera299f2c2010-04-17 18:26:20 +00004969 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004970 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnera299f2c2010-04-17 18:26:20 +00004971 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004972 }
4973
Bill Wendling53136852012-02-07 09:06:01 +00004974 for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) {
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004975 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4976 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4977 }
Chris Lattnera299f2c2010-04-17 18:26:20 +00004978
Daniel Dunbard027a922009-09-07 00:20:42 +00004979 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004980 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004981}
4982
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004983CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004984 : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00004985 ObjCTypes(cgm) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004986 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004987 ObjCABI = 2;
4988}
4989
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004990/* *** */
4991
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004992ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Douglas Gregora95f9aa2012-01-17 23:38:32 +00004993 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(0)
4994{
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004995 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4996 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004997
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004998 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004999 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005000 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005001 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Chris Lattnerece04092012-02-07 00:39:47 +00005002 Int8PtrTy = CGM.Int8PtrTy;
5003 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005004
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005005 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005006 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005007 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005008
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005009 // I'm not sure I like this. The implicit coordination is a bit
5010 // gross. We should solve this in a reasonable fashion because this
5011 // is a pretty common task (match some runtime data structure with
5012 // an LLVM data structure).
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005013
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005014 // FIXME: This is leaked.
5015 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005016
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005017 // struct _objc_super {
5018 // id self;
5019 // Class cls;
5020 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00005021 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005022 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005023 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005024 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005025 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005026 Ctx.getObjCIdType(), 0, 0, false, ICIS_NoInit));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005027 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005028 Ctx.getObjCClassType(), 0, 0, false,
5029 ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005030 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005031
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005032 SuperCTy = Ctx.getTagDeclType(RD);
5033 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005034
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005035 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005036 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5037
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005038 // struct _prop_t {
5039 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005040 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005041 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005042 PropertyTy = llvm::StructType::create("struct._prop_t",
5043 Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005044
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005045 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005046 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005047 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005048 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005049 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005050 PropertyListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005051 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
5052 llvm::ArrayType::get(PropertyTy, 0), NULL);
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005053 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005054 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005055
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005056 // struct _objc_method {
5057 // SEL _cmd;
5058 // char *method_type;
5059 // char *_imp;
5060 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005061 MethodTy = llvm::StructType::create("struct._objc_method",
5062 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
5063 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005064
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005065 // struct _objc_cache *
Chris Lattner5ec04a52011-08-12 17:43:31 +00005066 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005067 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005068
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005069}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00005070
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005071ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005072 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005073 // struct _objc_method_description {
5074 // SEL name;
5075 // char *types;
5076 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005077 MethodDescriptionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005078 llvm::StructType::create("struct._objc_method_description",
5079 SelectorPtrTy, Int8PtrTy, NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005080
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005081 // struct _objc_method_description_list {
5082 // int count;
5083 // struct _objc_method_description[1];
5084 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005085 MethodDescriptionListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005086 llvm::StructType::create("struct._objc_method_description_list",
5087 IntTy,
5088 llvm::ArrayType::get(MethodDescriptionTy, 0),NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005089
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005090 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005091 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005092 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005093
Daniel Dunbarb036db82008-08-13 03:21:16 +00005094 // Protocol description structures
5095
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005096 // struct _objc_protocol_extension {
5097 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5098 // struct _objc_method_description_list *optional_instance_methods;
5099 // struct _objc_method_description_list *optional_class_methods;
5100 // struct _objc_property_list *instance_properties;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005101 // const char ** extendedMethodTypes;
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005102 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005103 ProtocolExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005104 llvm::StructType::create("struct._objc_protocol_extension",
5105 IntTy, MethodDescriptionListPtrTy,
5106 MethodDescriptionListPtrTy, PropertyListPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005107 Int8PtrPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005108
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005109 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005110 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005111
Daniel Dunbarc475d422008-10-29 22:36:39 +00005112 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00005113
Chris Lattnera5f58b02011-07-09 17:41:47 +00005114 ProtocolTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005115 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbarb036db82008-08-13 03:21:16 +00005116
Chris Lattnera5f58b02011-07-09 17:41:47 +00005117 ProtocolListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005118 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005119 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005120 LongTy,
Chris Lattnera5f58b02011-07-09 17:41:47 +00005121 llvm::ArrayType::get(ProtocolTy, 0),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00005122 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005123
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005124 // struct _objc_protocol {
5125 // struct _objc_protocol_extension *isa;
5126 // char *protocol_name;
5127 // struct _objc_protocol **_objc_protocol_list;
5128 // struct _objc_method_description_list *instance_methods;
5129 // struct _objc_method_description_list *class_methods;
5130 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005131 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5132 llvm::PointerType::getUnqual(ProtocolListTy),
5133 MethodDescriptionListPtrTy,
5134 MethodDescriptionListPtrTy,
5135 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005136
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005137 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005138 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00005139
Owen Anderson9793f0e2009-07-29 22:16:19 +00005140 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005141
5142 // Class description structures
5143
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005144 // struct _objc_ivar {
5145 // char *ivar_name;
5146 // char *ivar_type;
5147 // int ivar_offset;
5148 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005149 IvarTy = llvm::StructType::create("struct._objc_ivar",
5150 Int8PtrTy, Int8PtrTy, IntTy, NULL);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005151
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005152 // struct _objc_ivar_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005153 IvarListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005154 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005155 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005156
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005157 // struct _objc_method_list *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005158 MethodListTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005159 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson9793f0e2009-07-29 22:16:19 +00005160 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005161
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005162 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005163 ClassExtensionTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005164 llvm::StructType::create("struct._objc_class_extension",
5165 IntTy, Int8PtrTy, PropertyListPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005166 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005167
Chris Lattner5ec04a52011-08-12 17:43:31 +00005168 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005169
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005170 // struct _objc_class {
5171 // Class isa;
5172 // Class super_class;
5173 // char *name;
5174 // long version;
5175 // long info;
5176 // long instance_size;
5177 // struct _objc_ivar_list *ivars;
5178 // struct _objc_method_list *methods;
5179 // struct _objc_cache *cache;
5180 // struct _objc_protocol_list *protocols;
5181 // char *ivar_layout;
5182 // struct _objc_class_ext *ext;
5183 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005184 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5185 llvm::PointerType::getUnqual(ClassTy),
5186 Int8PtrTy,
5187 LongTy,
5188 LongTy,
5189 LongTy,
5190 IvarListPtrTy,
5191 MethodListPtrTy,
5192 CachePtrTy,
5193 ProtocolListPtrTy,
5194 Int8PtrTy,
5195 ClassExtensionPtrTy,
5196 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005197
Owen Anderson9793f0e2009-07-29 22:16:19 +00005198 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005199
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005200 // struct _objc_category {
5201 // char *category_name;
5202 // char *class_name;
5203 // struct _objc_method_list *instance_method;
5204 // struct _objc_method_list *class_method;
5205 // uint32_t size; // sizeof(struct _objc_category)
5206 // struct _objc_property_list *instance_properties;// category's @property
5207 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005208 CategoryTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005209 llvm::StructType::create("struct._objc_category",
5210 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5211 MethodListPtrTy, ProtocolListPtrTy,
5212 IntTy, PropertyListPtrTy, NULL);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00005213
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005214 // Global metadata structures
5215
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00005216 // struct _objc_symtab {
5217 // long sel_ref_cnt;
5218 // SEL *refs;
5219 // short cls_def_cnt;
5220 // short cat_def_cnt;
5221 // char *defs[cls_def_cnt + cat_def_cnt];
5222 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005223 SymtabTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005224 llvm::StructType::create("struct._objc_symtab",
5225 LongTy, SelectorPtrTy, ShortTy, ShortTy,
5226 llvm::ArrayType::get(Int8PtrTy, 0), NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005227 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00005228
Fariborz Jahanianeee54df2009-01-22 00:37:21 +00005229 // struct _objc_module {
5230 // long version;
5231 // long size; // sizeof(struct _objc_module)
5232 // char *name;
5233 // struct _objc_symtab* symtab;
5234 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005235 ModuleTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005236 llvm::StructType::create("struct._objc_module",
5237 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00005238
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005239
Mike Stump18bb9282009-05-16 07:57:57 +00005240 // FIXME: This is the size of the setjmp buffer and should be target
5241 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson9ff22482008-09-09 10:10:21 +00005242 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005243
Anders Carlsson9ff22482008-09-09 10:10:21 +00005244 // Exceptions
Chris Lattnerece04092012-02-07 00:39:47 +00005245 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005246
5247 ExceptionDataTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005248 llvm::StructType::create("struct._objc_exception_data",
Chris Lattnerece04092012-02-07 00:39:47 +00005249 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
5250 StackPtrTy, NULL);
Anders Carlsson9ff22482008-09-09 10:10:21 +00005251
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005252}
5253
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005254ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00005255 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005256 // struct _method_list_t {
5257 // uint32_t entsize; // sizeof(struct _objc_method)
5258 // uint32_t method_count;
5259 // struct _objc_method method_list[method_count];
5260 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005261 MethodListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005262 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
5263 llvm::ArrayType::get(MethodTy, 0), NULL);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005264 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005265 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005266
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005267 // struct _protocol_t {
5268 // id isa; // NULL
5269 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005270 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005271 // const struct method_list_t * const instance_methods;
5272 // const struct method_list_t * const class_methods;
5273 // const struct method_list_t *optionalInstanceMethods;
5274 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005275 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005276 // const uint32_t size; // sizeof(struct _protocol_t)
5277 // const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005278 // const char ** extendedMethodTypes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005279 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005280
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005281 // Holder for struct _protocol_list_t *
Chris Lattnera5f58b02011-07-09 17:41:47 +00005282 ProtocolListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005283 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005284
Chris Lattnera5f58b02011-07-09 17:41:47 +00005285 ProtocolnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005286 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
5287 llvm::PointerType::getUnqual(ProtocolListnfABITy),
5288 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5289 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
Bob Wilson5f4e3a72011-11-30 01:57:58 +00005290 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
5291 NULL);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005292
5293 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005294 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005295
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005296 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005297 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005298 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005299 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005300 ProtocolListnfABITy->setBody(LongTy,
5301 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
5302 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005303
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005304 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005305 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005306
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005307 // struct _ivar_t {
5308 // unsigned long int *offset; // pointer to ivar offset location
5309 // char *name;
5310 // char *type;
5311 // uint32_t alignment;
5312 // uint32_t size;
5313 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005314 IvarnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005315 llvm::StructType::create("struct._ivar_t",
5316 llvm::PointerType::getUnqual(LongTy),
5317 Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005318
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005319 // struct _ivar_list_t {
5320 // uint32 entsize; // sizeof(struct _ivar_t)
5321 // uint32 count;
5322 // struct _iver_t list[count];
5323 // }
Chris Lattnera5f58b02011-07-09 17:41:47 +00005324 IvarListnfABITy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005325 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
5326 llvm::ArrayType::get(IvarnfABITy, 0), NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005327
Owen Anderson9793f0e2009-07-29 22:16:19 +00005328 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005329
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005330 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00005331 // uint32_t const flags;
5332 // uint32_t const instanceStart;
5333 // uint32_t const instanceSize;
5334 // uint32_t const reserved; // only when building for 64bit targets
5335 // const uint8_t * const ivarLayout;
5336 // const char *const name;
5337 // const struct _method_list_t * const baseMethods;
5338 // const struct _objc_protocol_list *const baseProtocols;
5339 // const struct _ivar_list_t *const ivars;
5340 // const uint8_t * const weakIvarLayout;
5341 // const struct _prop_list_t * const properties;
5342 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005343
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005344 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattner5ec04a52011-08-12 17:43:31 +00005345 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
5346 IntTy, IntTy, IntTy, Int8PtrTy,
5347 Int8PtrTy, MethodListnfABIPtrTy,
5348 ProtocolListnfABIPtrTy,
5349 IvarListnfABIPtrTy,
5350 Int8PtrTy, PropertyListPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005351
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005352 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattnera5f58b02011-07-09 17:41:47 +00005353 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall9dc0db22011-05-15 01:53:33 +00005354 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5355 ->getPointerTo();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005356
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005357 // struct _class_t {
5358 // struct _class_t *isa;
5359 // struct _class_t * const superclass;
5360 // void *cache;
5361 // IMP *vtable;
5362 // struct class_ro_t *ro;
5363 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005364
Chris Lattner5ec04a52011-08-12 17:43:31 +00005365 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattnera5f58b02011-07-09 17:41:47 +00005366 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
5367 llvm::PointerType::getUnqual(ClassnfABITy),
5368 CachePtrTy,
5369 llvm::PointerType::getUnqual(ImpnfABITy),
5370 llvm::PointerType::getUnqual(ClassRonfABITy),
5371 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005372
Fariborz Jahanian71394042009-01-23 23:53:38 +00005373 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00005374 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005375
Fariborz Jahanian0232c052009-01-23 01:46:23 +00005376 // struct _category_t {
5377 // const char * const name;
5378 // struct _class_t *const cls;
5379 // const struct _method_list_t * const instance_methods;
5380 // const struct _method_list_t * const class_methods;
5381 // const struct _protocol_list_t * const protocols;
5382 // const struct _prop_list_t * const properties;
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00005383 // }
Chris Lattner5ec04a52011-08-12 17:43:31 +00005384 CategorynfABITy = llvm::StructType::create("struct._category_t",
5385 Int8PtrTy, ClassnfABIPtrTy,
5386 MethodListnfABIPtrTy,
5387 MethodListnfABIPtrTy,
5388 ProtocolListnfABIPtrTy,
5389 PropertyListPtrTy,
5390 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005391
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005392 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005393 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5394 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005395
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005396 // MessageRefTy - LLVM for:
5397 // struct _message_ref_t {
5398 // IMP messenger;
5399 // SEL name;
5400 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005401
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005402 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00005403 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00005404 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00005405 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005406 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005407 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005408 Ctx.VoidPtrTy, 0, 0, false, ICIS_NoInit));
Abramo Bagnaradff19302011-03-08 08:55:46 +00005409 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith2b013182012-06-10 03:12:00 +00005410 Ctx.getObjCSelType(), 0, 0, false,
5411 ICIS_NoInit));
Douglas Gregord5058122010-02-11 01:19:42 +00005412 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005413
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005414 MessageRefCTy = Ctx.getTagDeclType(RD);
5415 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5416 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005417
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005418 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00005419 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005420
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005421 // SuperMessageRefTy - LLVM for:
5422 // struct _super_message_ref_t {
5423 // SUPER_IMP messenger;
5424 // SEL name;
5425 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005426 SuperMessageRefTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005427 llvm::StructType::create("struct._super_message_ref_t",
5428 ImpnfABITy, SelectorPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005429
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00005430 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005431 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian0a3cfcc2011-06-22 20:21:51 +00005432
Daniel Dunbarb1559a42009-03-01 04:46:24 +00005433
5434 // struct objc_typeinfo {
5435 // const void** vtable; // objc_ehtype_vtable + 2
5436 // const char* name; // c++ typeinfo string
5437 // Class cls;
5438 // };
Chris Lattnera5f58b02011-07-09 17:41:47 +00005439 EHTypeTy =
Chris Lattner5ec04a52011-08-12 17:43:31 +00005440 llvm::StructType::create("struct._objc_typeinfo",
5441 llvm::PointerType::getUnqual(Int8PtrTy),
5442 Int8PtrTy, ClassnfABIPtrTy, NULL);
Owen Anderson9793f0e2009-07-29 22:16:19 +00005443 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00005444}
5445
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005446llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00005447 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005448
Fariborz Jahanian71394042009-01-23 23:53:38 +00005449 return NULL;
5450}
5451
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00005452void CGObjCNonFragileABIMac::
5453AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
5454 const char *SymbolName,
5455 const char *SectionName) {
Daniel Dunbar19573e72009-05-15 21:48:48 +00005456 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005457
Daniel Dunbar19573e72009-05-15 21:48:48 +00005458 if (!NumClasses)
5459 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005460
Chris Lattner3def9ae2012-02-06 22:16:34 +00005461 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005462 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00005463 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00005464 ObjCTypes.Int8PtrTy);
Chris Lattner3def9ae2012-02-06 22:16:34 +00005465 llvm::Constant *Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00005466 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner3def9ae2012-02-06 22:16:34 +00005467 Symbols.size()),
Daniel Dunbar19573e72009-05-15 21:48:48 +00005468 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005469
Daniel Dunbar19573e72009-05-15 21:48:48 +00005470 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005471 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005472 llvm::GlobalValue::InternalLinkage,
5473 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005474 SymbolName);
Micah Villmowdd31ca12012-10-08 16:25:52 +00005475 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00005476 GV->setSection(SectionName);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005477 CGM.AddUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00005478}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005479
Fariborz Jahanian71394042009-01-23 23:53:38 +00005480void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5481 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005482
Daniel Dunbar19573e72009-05-15 21:48:48 +00005483 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005484 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005485 AddModuleClassList(DefinedClasses,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005486 "\01L_OBJC_LABEL_CLASS_$",
5487 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahanian67260552009-11-17 21:37:35 +00005488
Bill Wendling53136852012-02-07 09:06:01 +00005489 for (unsigned i = 0, e = DefinedClasses.size(); i < e; i++) {
Fariborz Jahanian67260552009-11-17 21:37:35 +00005490 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
5491 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
5492 continue;
5493 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahanian67260552009-11-17 21:37:35 +00005494 }
5495
Bill Wendling53136852012-02-07 09:06:01 +00005496 for (unsigned i = 0, e = DefinedMetaClasses.size(); i < e; i++) {
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005497 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
5498 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
5499 continue;
5500 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
5501 }
Fariborz Jahanian67260552009-11-17 21:37:35 +00005502
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005503 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005504 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
5505 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005506
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005507 // Build list of all implemented category addresses in array
5508 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005509 AddModuleClassList(DefinedCategories,
Daniel Dunbar19573e72009-05-15 21:48:48 +00005510 "\01L_OBJC_LABEL_CATEGORY_$",
5511 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005512 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005513 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
5514 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005515
Daniel Dunbar5e639272010-04-25 20:39:01 +00005516 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005517}
5518
John McCall9e8bb002011-05-14 03:10:52 +00005519/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
5520/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005521/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005522/// message dispatch call for all the rest.
John McCall9e8bb002011-05-14 03:10:52 +00005523bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
5524 // At various points we've experimented with using vtable-based
5525 // dispatch for all methods.
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005526 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005527 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00005528 return false;
John McCall9e8bb002011-05-14 03:10:52 +00005529 case CodeGenOptions::NonLegacy:
5530 return true;
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005531 case CodeGenOptions::Mixed:
5532 break;
5533 }
5534
5535 // If so, see whether this selector is in the white-list of things which must
5536 // use the new dispatch convention. We lazily build a dense set for this.
John McCall9e8bb002011-05-14 03:10:52 +00005537 if (VTableDispatchMethods.empty()) {
5538 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
5539 VTableDispatchMethods.insert(GetNullarySelector("class"));
5540 VTableDispatchMethods.insert(GetNullarySelector("self"));
5541 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
5542 VTableDispatchMethods.insert(GetNullarySelector("length"));
5543 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005544
John McCall9e8bb002011-05-14 03:10:52 +00005545 // These are vtable-based if GC is disabled.
5546 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005547 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall9e8bb002011-05-14 03:10:52 +00005548 VTableDispatchMethods.insert(GetNullarySelector("retain"));
5549 VTableDispatchMethods.insert(GetNullarySelector("release"));
5550 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
5551 }
5552
5553 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
5554 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
5555 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
5556 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
5557 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
5558 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
5559 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
5560
5561 // These are vtable-based if GC is enabled.
5562 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikiebbafb8a2012-03-11 07:00:24 +00005563 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall9e8bb002011-05-14 03:10:52 +00005564 VTableDispatchMethods.insert(GetNullarySelector("hash"));
5565 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
5566
5567 // "countByEnumeratingWithState:objects:count"
5568 IdentifierInfo *KeyIdents[] = {
5569 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
5570 &CGM.getContext().Idents.get("objects"),
5571 &CGM.getContext().Idents.get("count")
5572 };
5573 VTableDispatchMethods.insert(
5574 CGM.getContext().Selectors.getSelector(3, KeyIdents));
5575 }
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005576 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00005577
John McCall9e8bb002011-05-14 03:10:52 +00005578 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00005579}
5580
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005581/// BuildClassRoTInitializer - generate meta-data for:
5582/// struct _class_ro_t {
5583/// uint32_t const flags;
5584/// uint32_t const instanceStart;
5585/// uint32_t const instanceSize;
5586/// uint32_t const reserved; // only when building for 64bit targets
5587/// const uint8_t * const ivarLayout;
5588/// const char *const name;
5589/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005590/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005591/// const struct _ivar_list_t *const ivars;
5592/// const uint8_t * const weakIvarLayout;
5593/// const struct _prop_list_t * const properties;
5594/// }
5595///
5596llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005597 unsigned flags,
5598 unsigned InstanceStart,
5599 unsigned InstanceSize,
5600 const ObjCImplementationDecl *ID) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005601 std::string ClassName = ID->getNameAsString();
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005602 llvm::Constant *Values[10]; // 11 for 64bit targets!
John McCall31168b02011-06-15 23:02:42 +00005603
David Blaikiebbafb8a2012-03-11 07:00:24 +00005604 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCallef19dbb2012-10-17 04:53:23 +00005605 flags |= NonFragileABI_Class_CompiledByARC;
John McCall31168b02011-06-15 23:02:42 +00005606
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005607 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
5608 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
5609 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005610 // FIXME. For 64bit targets add 0 here.
John McCallef19dbb2012-10-17 04:53:23 +00005611 Values[ 3] = (flags & NonFragileABI_Class_Meta)
5612 ? GetIvarLayoutName(0, ObjCTypes)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005613 : BuildIvarLayout(ID, true);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005614 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005615 // const struct _method_list_t * const baseMethods;
5616 std::vector<llvm::Constant*> Methods;
5617 std::string MethodListName("\01l_OBJC_$_");
John McCallef19dbb2012-10-17 04:53:23 +00005618 if (flags & NonFragileABI_Class_Meta) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005619 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005620 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005621 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005622 // Class methods should always be defined.
5623 Methods.push_back(GetMethodConstant(*i));
5624 }
5625 } else {
5626 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005627 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005628 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005629 // Instance methods should always be defined.
5630 Methods.push_back(GetMethodConstant(*i));
5631 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005632 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005633 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie40ed2972012-06-06 20:45:41 +00005634 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005635
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005636 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
5637 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005638
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00005639 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
5640 if (llvm::Constant *C = GetMethodConstant(MD))
5641 Methods.push_back(C);
5642 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
5643 if (llvm::Constant *C = GetMethodConstant(MD))
5644 Methods.push_back(C);
5645 }
5646 }
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005647 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005648 Values[ 5] = EmitMethodList(MethodListName,
5649 "__DATA, __objc_const", Methods);
5650
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005651 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5652 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005653 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005654 + OID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00005655 OID->all_referenced_protocol_begin(),
5656 OID->all_referenced_protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005657
John McCallef19dbb2012-10-17 04:53:23 +00005658 if (flags & NonFragileABI_Class_Meta) {
Owen Anderson0b75f232009-07-31 20:28:54 +00005659 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCallef19dbb2012-10-17 04:53:23 +00005660 Values[ 8] = GetIvarLayoutName(0, ObjCTypes);
Owen Anderson0b75f232009-07-31 20:28:54 +00005661 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
John McCallef19dbb2012-10-17 04:53:23 +00005662 } else {
5663 Values[ 7] = EmitIvarList(ID);
5664 Values[ 8] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005665 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
5666 ID, ID->getClassInterface(), ObjCTypes);
John McCallef19dbb2012-10-17 04:53:23 +00005667 }
Owen Anderson0e0189d2009-07-27 22:29:56 +00005668 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005669 Values);
5670 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005671 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
5672 llvm::GlobalValue::InternalLinkage,
5673 Init,
John McCallef19dbb2012-10-17 04:53:23 +00005674 (flags & NonFragileABI_Class_Meta) ?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005675 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
5676 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005677 CLASS_RO_GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005678 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005679 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005680 return CLASS_RO_GV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005681
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005682}
5683
5684/// BuildClassMetaData - This routine defines that to-level meta-data
5685/// for the given ClassName for:
5686/// struct _class_t {
5687/// struct _class_t *isa;
5688/// struct _class_t * const superclass;
5689/// void *cache;
5690/// IMP *vtable;
5691/// struct class_ro_t *ro;
5692/// }
5693///
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005694llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005695 std::string &ClassName,
5696 llvm::Constant *IsAGV,
5697 llvm::Constant *SuperClassGV,
5698 llvm::Constant *ClassRoGV,
5699 bool HiddenVisibility) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005700 llvm::Constant *Values[] = {
5701 IsAGV,
5702 SuperClassGV,
5703 ObjCEmptyCacheVar, // &ObjCEmptyCacheVar
5704 ObjCEmptyVtableVar, // &ObjCEmptyVtableVar
5705 ClassRoGV // &CLASS_RO_GV
5706 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005707 if (!Values[1])
5708 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005709 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005710 Values);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005711 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
5712 GV->setInitializer(Init);
Fariborz Jahanian04087232009-01-31 01:07:39 +00005713 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005714 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005715 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian82208252009-01-31 00:59:10 +00005716 if (HiddenVisibility)
5717 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005718 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005719}
5720
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005721bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00005722CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005723 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005724}
5725
Daniel Dunbar961202372009-05-03 12:57:56 +00005726void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00005727 uint32_t &InstanceStart,
5728 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005729 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00005730 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005731
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005732 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00005733 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-05-04 23:23:09 +00005734
5735 // If there are no fields, the start is the same as the end.
5736 if (!RL.getFieldCount())
5737 InstanceStart = InstanceSize;
5738 else
Ken Dyckc5ca8762011-04-14 00:43:09 +00005739 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00005740}
5741
Fariborz Jahanian71394042009-01-23 23:53:38 +00005742void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
5743 std::string ClassName = ID->getNameAsString();
5744 if (!ObjCEmptyCacheVar) {
5745 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005746 CGM.getModule(),
5747 ObjCTypes.CacheTy,
5748 false,
5749 llvm::GlobalValue::ExternalLinkage,
5750 0,
5751 "_objc_empty_cache");
5752
Fariborz Jahanian71394042009-01-23 23:53:38 +00005753 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005754 CGM.getModule(),
5755 ObjCTypes.ImpnfABITy,
5756 false,
5757 llvm::GlobalValue::ExternalLinkage,
5758 0,
5759 "_objc_empty_vtable");
Fariborz Jahanian71394042009-01-23 23:53:38 +00005760 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005761 assert(ID->getClassInterface() &&
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005762 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00005763 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005764 uint32_t InstanceStart =
Micah Villmowdd31ca12012-10-08 16:25:52 +00005765 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005766 uint32_t InstanceSize = InstanceStart;
John McCallef19dbb2012-10-17 04:53:23 +00005767 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar15894b72009-04-07 05:48:37 +00005768 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
5769 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005770
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005771 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005772
John McCall0d54a172012-10-17 04:53:31 +00005773 // Build the flags for the metaclass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005774 bool classIsHidden =
John McCall457a04e2010-10-22 21:05:15 +00005775 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005776 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00005777 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00005778
5779 // FIXME: why is this flag set on the metaclass?
5780 // ObjC metaclasses have no fields and don't really get constructed.
5781 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00005782 flags |= NonFragileABI_Class_HasCXXStructors;
John McCall0d54a172012-10-17 04:53:31 +00005783 if (!ID->hasNonZeroConstructors())
5784 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5785 }
5786
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005787 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005788 // class is root
John McCallef19dbb2012-10-17 04:53:23 +00005789 flags |= NonFragileABI_Class_Root;
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005790 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005791 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005792 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005793 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005794 const ObjCInterfaceDecl *Root = ID->getClassInterface();
5795 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
5796 Root = Super;
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005797 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005798 if (Root->isWeakImported())
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005799 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005800 // work on super class metadata symbol.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005801 std::string SuperClassName =
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00005802 ObjCMetaClassName +
5803 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005804 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005805 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005806 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00005807 }
5808 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
5809 InstanceStart,
5810 InstanceSize,ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005811 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005812 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005813 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
5814 classIsHidden);
Fariborz Jahanian67260552009-11-17 21:37:35 +00005815 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00005816
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005817 // Metadata for the class
John McCallef19dbb2012-10-17 04:53:23 +00005818 flags = 0;
Fariborz Jahanian82208252009-01-31 00:59:10 +00005819 if (classIsHidden)
John McCallef19dbb2012-10-17 04:53:23 +00005820 flags |= NonFragileABI_Class_Hidden;
John McCall0d54a172012-10-17 04:53:31 +00005821
5822 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCallef19dbb2012-10-17 04:53:23 +00005823 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005824
John McCall0d54a172012-10-17 04:53:31 +00005825 // Set a flag to enable a runtime optimization when a class has
5826 // fields that require destruction but which don't require
5827 // anything except zero-initialization during construction. This
5828 // is most notably true of __strong and __weak types, but you can
5829 // also imagine there being C++ types with non-trivial default
5830 // constructors that merely set all fields to null.
5831 if (!ID->hasNonZeroConstructors())
5832 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5833 }
5834
Douglas Gregor78bd61f2009-06-18 16:11:24 +00005835 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
John McCallef19dbb2012-10-17 04:53:23 +00005836 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005837
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005838 if (!ID->getClassInterface()->getSuperClass()) {
John McCallef19dbb2012-10-17 04:53:23 +00005839 flags |= NonFragileABI_Class_Root;
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005840 SuperClassGV = 0;
Chris Lattnerb433b272009-04-19 06:02:28 +00005841 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005842 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005843 std::string RootClassName =
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005844 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005845 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005846 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005847 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005848 }
Daniel Dunbar961202372009-05-03 12:57:56 +00005849 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005850 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005851 InstanceStart,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005852 InstanceSize,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005853 ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005854
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005855 TClassName = ObjCClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005856 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005857 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5858 classIsHidden);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005859 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005860
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005861 // Determine if this class is also "non-lazy".
5862 if (ImplementationIsNonLazy(ID))
5863 DefinedNonLazyClasses.push_back(ClassMD);
5864
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005865 // Force the definition of the EHType if necessary.
John McCallef19dbb2012-10-17 04:53:23 +00005866 if (flags & NonFragileABI_Class_Exception)
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005867 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005868 // Make sure method definition entries are all clear for next implementation.
5869 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005870}
5871
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005872/// GenerateProtocolRef - This routine is called to generate code for
5873/// a protocol reference expression; as in:
5874/// @code
5875/// @protocol(Proto1);
5876/// @endcode
5877/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5878/// which will hold address of the protocol meta-data.
5879///
5880llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005881 const ObjCProtocolDecl *PD) {
5882
Fariborz Jahanian464423d2009-04-10 18:47:34 +00005883 // This routine is called for @protocol only. So, we must build definition
5884 // of protocol's meta-data (not a reference to it!)
5885 //
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005886 llvm::Constant *Init =
5887 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor020de322012-01-17 18:36:30 +00005888 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005889
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005890 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar56df9772010-08-17 22:39:59 +00005891 ProtocolName += PD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005892
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005893 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5894 if (PTGV)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005895 return Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005896 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005897 CGM.getModule(),
5898 Init->getType(), false,
5899 llvm::GlobalValue::WeakAnyLinkage,
5900 Init,
5901 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005902 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5903 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005904 CGM.AddUsedGlobal(PTGV);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00005905 return Builder.CreateLoad(PTGV);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005906}
5907
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005908/// GenerateCategory - Build metadata for a category implementation.
5909/// struct _category_t {
5910/// const char * const name;
5911/// struct _class_t *const cls;
5912/// const struct _method_list_t * const instance_methods;
5913/// const struct _method_list_t * const class_methods;
5914/// const struct _protocol_list_t * const protocols;
5915/// const struct _prop_list_t * const properties;
5916/// }
5917///
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005918void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005919 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005920 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005921 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5922 "_$_" + OCD->getNameAsString());
5923 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar15894b72009-04-07 05:48:37 +00005924 Interface->getNameAsString());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005925
Benjamin Kramer22d24c22011-10-15 12:20:02 +00005926 llvm::Constant *Values[6];
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005927 Values[0] = GetClassName(OCD->getIdentifier());
5928 // meta-class entry symbol
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005929 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005930 if (Interface->isWeakImported())
Fariborz Jahanian3ad8dcf2009-11-17 22:02:21 +00005931 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5932
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005933 Values[1] = ClassGV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005934 std::vector<llvm::Constant*> Methods;
5935 std::string MethodListName(Prefix);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005936 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005937 "_$_" + OCD->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005938
5939 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005940 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005941 // Instance methods should always be defined.
5942 Methods.push_back(GetMethodConstant(*i));
5943 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005944
5945 Values[2] = EmitMethodList(MethodListName,
5946 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005947 Methods);
5948
5949 MethodListName = Prefix;
5950 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5951 OCD->getNameAsString();
5952 Methods.clear();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005953 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005954 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005955 // Class methods should always be defined.
5956 Methods.push_back(GetMethodConstant(*i));
5957 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005958
5959 Values[3] = EmitMethodList(MethodListName,
5960 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005961 Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005962 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00005963 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005964 if (Category) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00005965 SmallString<256> ExtName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005966 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5967 << OCD->getName();
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005968 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005969 + Interface->getName() + "_$_"
5970 + Category->getName(),
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005971 Category->protocol_begin(),
5972 Category->protocol_end());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005973 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5974 OCD, Category, ObjCTypes);
Mike Stump658fe022009-07-30 22:28:39 +00005975 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00005976 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5977 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005978 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005979
5980 llvm::Constant *Init =
5981 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005982 Values);
5983 llvm::GlobalVariable *GCATV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005984 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005985 false,
5986 llvm::GlobalValue::InternalLinkage,
5987 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005988 ExtCatName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005989 GCATV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00005990 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005991 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005992 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005993 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-05-15 22:33:15 +00005994
5995 // Determine if this category is also "non-lazy".
5996 if (ImplementationIsNonLazy(OCD))
5997 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00005998 // method definition entries must be clear for next implementation.
5999 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00006000}
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006001
6002/// GetMethodConstant - Return a struct objc_method constant for the
6003/// given method if it has been defined. The result is null if the
6004/// method has not been defined. The return value has type MethodPtrTy.
6005llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006006 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00006007 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006008 if (!Fn)
6009 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006010
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006011 llvm::Constant *Method[] = {
Owen Andersonade90fd2009-07-29 18:54:39 +00006012 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006013 ObjCTypes.SelectorPtrTy),
6014 GetMethodVarType(MD),
6015 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
6016 };
Owen Anderson0e0189d2009-07-27 22:29:56 +00006017 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006018}
6019
6020/// EmitMethodList - Build meta-data for method declarations
6021/// struct _method_list_t {
6022/// uint32_t entsize; // sizeof(struct _objc_method)
6023/// uint32_t method_count;
6024/// struct _objc_method method_list[method_count];
6025/// }
6026///
Bill Wendlingcb5b5ff2012-02-07 09:25:09 +00006027llvm::Constant *
6028CGObjCNonFragileABIMac::EmitMethodList(Twine Name,
6029 const char *Section,
6030 ArrayRef<llvm::Constant*> Methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006031 // Return null for empty list.
6032 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006033 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006034
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006035 llvm::Constant *Values[3];
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006036 // sizeof(struct _objc_method)
Micah Villmowdd31ca12012-10-08 16:25:52 +00006037 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006038 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006039 // method_count
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006040 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00006041 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006042 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00006043 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006044 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006045
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006046 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006047 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006048 llvm::GlobalValue::InternalLinkage, Init, Name);
Micah Villmowdd31ca12012-10-08 16:25:52 +00006049 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006050 GV->setSection(Section);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006051 CGM.AddUsedGlobal(GV);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006052 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00006053}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006054
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006055/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6056/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006057llvm::GlobalVariable *
6058CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6059 const ObjCIvarDecl *Ivar) {
6060 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar3f86b9c2009-05-05 00:36:57 +00006061 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregorbcced4e2009-04-09 21:40:53 +00006062 '.' + Ivar->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006063 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006064 CGM.getModule().getGlobalVariable(Name);
6065 if (!IvarOffsetGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006066 IvarOffsetGV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006067 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006068 false,
6069 llvm::GlobalValue::ExternalLinkage,
6070 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006071 Name);
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00006072 return IvarOffsetGV;
6073}
6074
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00006075llvm::Constant *
6076CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6077 const ObjCIvarDecl *Ivar,
Eli Friedman8cbca202012-11-06 22:15:52 +00006078 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006079 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006080 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Eli Friedman8cbca202012-11-06 22:15:52 +00006081 Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006082 IvarOffsetGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006083 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006084
Mike Stump18bb9282009-05-16 07:57:57 +00006085 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
6086 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbarbf90b332009-04-19 00:44:02 +00006087 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6088 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall457a04e2010-10-22 21:05:15 +00006089 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00006090 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00006091 else
Fariborz Jahanianbc3c77b2009-04-06 18:30:00 +00006092 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendlingf7d45982011-05-04 21:37:25 +00006093 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006094 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006095}
6096
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006097/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006098/// implementation. The return value has type
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006099/// IvarListnfABIPtrTy.
6100/// struct _ivar_t {
6101/// unsigned long int *offset; // pointer to ivar offset location
6102/// char *name;
6103/// char *type;
6104/// uint32_t alignment;
6105/// uint32_t size;
6106/// }
6107/// struct _ivar_list_t {
6108/// uint32 entsize; // sizeof(struct _ivar_t)
6109/// uint32 count;
6110/// struct _iver_t list[count];
6111/// }
6112///
Daniel Dunbarf5c18462009-04-20 06:54:31 +00006113
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006114llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006115 const ObjCImplementationDecl *ID) {
6116
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006117 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006118
Jordy Rosea91768e2011-07-22 02:08:32 +00006119 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006120 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006121
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006122 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006123
Jordy Rosea91768e2011-07-22 02:08:32 +00006124 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianb26d5782011-06-28 18:05:25 +00006125 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian7c809592009-06-04 01:19:09 +00006126 // Ignore unnamed bit-fields.
6127 if (!IVD->getDeclName())
6128 continue;
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006129 llvm::Constant *Ivar[5];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006130 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar961202372009-05-03 12:57:56 +00006131 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006132 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
6133 Ivar[2] = GetMethodVarType(IVD);
Chris Lattner2192fe52011-07-18 04:24:23 +00006134 llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00006135 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmowdd31ca12012-10-08 16:25:52 +00006136 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006137 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006138 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006139 Align = llvm::Log2_32(Align);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006140 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-04-20 00:33:43 +00006141 // NOTE. Size of a bitfield does not match gcc's, because of the
6142 // way bitfields are treated special in each. But I am told that
6143 // 'size' for bitfield ivars is ignored by the runtime so it does
6144 // not matter. If it matters, there is enough info to get the
6145 // bitfield right!
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006146 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006147 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006148 }
6149 // Return null for empty list.
6150 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00006151 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006152
6153 llvm::Constant *Values[3];
Micah Villmowdd31ca12012-10-08 16:25:52 +00006154 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006155 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
6156 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00006157 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006158 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00006159 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006160 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006161 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
6162 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006163 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00006164 llvm::GlobalValue::InternalLinkage,
6165 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006166 Prefix + OID->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006167 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006168 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00006169 GV->setSection("__DATA, __objc_const");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006170
Chris Lattnerf56501c2009-07-17 23:57:13 +00006171 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00006172 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006173}
6174
6175llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006176 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006177 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006178
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006179 if (!Entry) {
6180 // We use the initializer as a marker of whether this is a forward
6181 // reference or not. At module finalization we add the empty
6182 // contents for protocols which were referenced but never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006183 Entry =
6184 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
6185 llvm::GlobalValue::ExternalLinkage,
6186 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006187 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006188 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006189 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006190
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006191 return Entry;
6192}
6193
6194/// GetOrEmitProtocol - Generate the protocol meta-data:
6195/// @code
6196/// struct _protocol_t {
6197/// id isa; // NULL
6198/// const char * const protocol_name;
6199/// const struct _protocol_list_t * protocol_list; // super protocols
6200/// const struct method_list_t * const instance_methods;
6201/// const struct method_list_t * const class_methods;
6202/// const struct method_list_t *optionalInstanceMethods;
6203/// const struct method_list_t *optionalClassMethods;
6204/// const struct _prop_list_t * properties;
6205/// const uint32_t size; // sizeof(struct _protocol_t)
6206/// const uint32_t flags; // = 0
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006207/// const char ** extendedMethodTypes;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006208/// }
6209/// @endcode
6210///
6211
6212llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006213 const ObjCProtocolDecl *PD) {
John McCallf9582a72012-03-30 21:29:05 +00006214 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006215
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006216 // Early exit if a defining object has already been generated.
6217 if (Entry && Entry->hasInitializer())
6218 return Entry;
6219
Douglas Gregora715bff2012-01-01 19:51:50 +00006220 // Use the protocol definition, if there is one.
6221 if (const ObjCProtocolDecl *Def = PD->getDefinition())
6222 PD = Def;
6223
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006224 // Construct method lists.
6225 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
6226 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006227 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006228 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00006229 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006230 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006231 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006232 if (!C)
6233 return GetOrEmitProtocolRef(PD);
6234
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006235 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6236 OptInstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006237 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006238 } else {
6239 InstanceMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006240 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006241 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006242 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006243
6244 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00006245 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006246 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006247 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006248 if (!C)
6249 return GetOrEmitProtocolRef(PD);
6250
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006251 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6252 OptClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006253 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006254 } else {
6255 ClassMethods.push_back(C);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006256 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006257 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006258 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006259
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006260 MethodTypesExt.insert(MethodTypesExt.end(),
6261 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
6262
6263 llvm::Constant *Values[11];
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006264 // isa is NULL
Owen Anderson0b75f232009-07-31 20:28:54 +00006265 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006266 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006267 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
6268 PD->protocol_begin(),
6269 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006270
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006271 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006272 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006273 "__DATA, __objc_const",
6274 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006275 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006276 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006277 "__DATA, __objc_const",
6278 ClassMethods);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006279 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006280 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006281 "__DATA, __objc_const",
6282 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006283 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006284 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006285 "__DATA, __objc_const",
6286 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006287 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006288 0, PD, ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006289 uint32_t Size =
Micah Villmowdd31ca12012-10-08 16:25:52 +00006290 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006291 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0b75f232009-07-31 20:28:54 +00006292 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Bob Wilson5f4e3a72011-11-30 01:57:58 +00006293 Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
6294 + PD->getName(),
6295 MethodTypesExt, ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006296 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006297 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006298
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006299 if (Entry) {
6300 // Already created, fix the linkage and update the initializer.
Mike Stumpa6ca3342009-03-07 16:33:28 +00006301 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006302 Entry->setInitializer(Init);
6303 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006304 Entry =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006305 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6306 false, llvm::GlobalValue::WeakAnyLinkage, Init,
6307 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006308 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006309 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006310 Entry->setSection("__DATA,__datacoal_nt,coalesced");
John McCallf9582a72012-03-30 21:29:05 +00006311
6312 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006313 }
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006314 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006315 CGM.AddUsedGlobal(Entry);
6316
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006317 // Use this protocol meta-data to build protocol list table in section
6318 // __DATA, __objc_protolist
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006319 llvm::GlobalVariable *PTGV =
6320 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
6321 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
6322 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006323 PTGV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006324 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbarb25452a2009-04-15 02:56:18 +00006325 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00006326 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00006327 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006328 return Entry;
6329}
6330
6331/// EmitProtocolList - Generate protocol list meta-data:
6332/// @code
6333/// struct _protocol_list_t {
6334/// long protocol_count; // Note, this is 32/64 bit
6335/// struct _protocol_t[protocol_count];
6336/// }
6337/// @endcode
6338///
6339llvm::Constant *
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006340CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006341 ObjCProtocolDecl::protocol_iterator begin,
6342 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendlinga515b582012-02-09 22:16:49 +00006343 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006344
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006345 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006346 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00006347 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006348
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006349 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00006350 SmallString<256> TmpName;
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006351 Name.toVector(TmpName);
6352 llvm::GlobalVariable *GV =
6353 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006354 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006355 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006356
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006357 for (; begin != end; ++begin)
6358 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
6359
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006360 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00006361 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006362 ObjCTypes.ProtocolnfABIPtrTy));
6363
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006364 llvm::Constant *Values[2];
Owen Anderson170229f2009-07-14 23:10:40 +00006365 Values[0] =
Owen Andersonb7a2fe62009-07-24 23:12:58 +00006366 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006367 Values[1] =
Bill Wendlinga515b582012-02-09 22:16:49 +00006368 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
6369 ProtocolRefs.size()),
6370 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006371
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006372 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Owen Andersonc10c8d32009-07-08 19:05:04 +00006373 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006374 llvm::GlobalValue::InternalLinkage,
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006375 Init, Name);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006376 GV->setSection("__DATA, __objc_const");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00006377 GV->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006378 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Chris Lattnerf56501c2009-07-17 23:57:13 +00006379 CGM.AddUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006380 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00006381 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00006382}
6383
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006384/// GetMethodDescriptionConstant - This routine build following meta-data:
6385/// struct _objc_method {
6386/// SEL _cmd;
6387/// char *method_type;
6388/// char *_imp;
6389/// }
6390
6391llvm::Constant *
6392CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006393 llvm::Constant *Desc[3];
Owen Anderson170229f2009-07-14 23:10:40 +00006394 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006395 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
6396 ObjCTypes.SelectorPtrTy);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006397 Desc[1] = GetMethodVarType(MD);
Douglas Gregora9d84932011-05-27 01:19:52 +00006398 if (!Desc[1])
6399 return 0;
6400
Fariborz Jahanian097feda2009-01-30 18:58:59 +00006401 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00006402 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00006403 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00006404}
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006405
6406/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
6407/// This code gen. amounts to generating code for:
6408/// @code
6409/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
6410/// @encode
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006411///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00006412LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-05-17 21:00:27 +00006413 CodeGen::CodeGenFunction &CGF,
6414 QualType ObjectTy,
6415 llvm::Value *BaseValue,
6416 const ObjCIvarDecl *Ivar,
6417 unsigned CVRQualifiers) {
6418 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006419 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
6420 if (llvm::LoadInst *LI = dyn_cast<llvm::LoadInst>(Offset))
6421 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6422 llvm::MDNode::get(VMContext,
6423 ArrayRef<llvm::Value*>()));
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00006424 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancaabf1b2012-02-20 22:42:22 +00006425 Offset);
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00006426}
6427
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006428llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006429 CodeGen::CodeGenFunction &CGF,
6430 const ObjCInterfaceDecl *Interface,
6431 const ObjCIvarDecl *Ivar) {
Daniel Dunbarc76493a2009-11-29 21:23:36 +00006432 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00006433}
6434
John McCall234eac82011-05-13 23:16:18 +00006435static void appendSelectorForMessageRefTable(std::string &buffer,
6436 Selector selector) {
6437 if (selector.isUnarySelector()) {
6438 buffer += selector.getNameForSlot(0);
6439 return;
6440 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006441
John McCall234eac82011-05-13 23:16:18 +00006442 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
6443 buffer += selector.getNameForSlot(i);
6444 buffer += '_';
6445 }
6446}
6447
John McCall9e8bb002011-05-14 03:10:52 +00006448/// Emit a "v-table" message send. We emit a weak hidden-visibility
6449/// struct, initially containing the selector pointer and a pointer to
6450/// a "fixup" variant of the appropriate objc_msgSend. To call, we
6451/// load and call the function pointer, passing the address of the
6452/// struct as the second parameter. The runtime determines whether
6453/// the selector is currently emitted using vtable dispatch; if so, it
6454/// substitutes a stub function which simply tail-calls through the
6455/// appropriate vtable slot, and if not, it substitues a stub function
6456/// which tail-calls objc_msgSend. Both stubs adjust the selector
6457/// argument to correctly point to the selector.
6458RValue
6459CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
6460 ReturnValueSlot returnSlot,
6461 QualType resultType,
6462 Selector selector,
6463 llvm::Value *arg0,
6464 QualType arg0Type,
6465 bool isSuper,
6466 const CallArgList &formalArgs,
6467 const ObjCMethodDecl *method) {
John McCall234eac82011-05-13 23:16:18 +00006468 // Compute the actual arguments.
6469 CallArgList args;
6470
John McCall9e8bb002011-05-14 03:10:52 +00006471 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00006472 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00006473 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
6474 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00006475
John McCall9e8bb002011-05-14 03:10:52 +00006476 // Second argument: a pointer to the message ref structure. Leave
6477 // the actual argument value blank for now.
John McCall234eac82011-05-13 23:16:18 +00006478 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
6479
6480 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
6481
John McCalla729c622012-02-17 03:33:10 +00006482 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCall234eac82011-05-13 23:16:18 +00006483
John McCall5880fb82011-05-14 21:12:11 +00006484 NullReturnState nullReturn;
6485
John McCall9e8bb002011-05-14 03:10:52 +00006486 // Find the function to call and the mangled name for the message
6487 // ref structure. Using a different mangled name wouldn't actually
6488 // be a problem; it would just be a waste.
6489 //
6490 // The runtime currently never uses vtable dispatch for anything
6491 // except normal, non-super message-sends.
6492 // FIXME: don't use this for that.
John McCall234eac82011-05-13 23:16:18 +00006493 llvm::Constant *fn = 0;
6494 std::string messageRefName("\01l_");
John McCalla729c622012-02-17 03:33:10 +00006495 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
John McCall234eac82011-05-13 23:16:18 +00006496 if (isSuper) {
6497 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
6498 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006499 } else {
John McCall5880fb82011-05-14 21:12:11 +00006500 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00006501 fn = ObjCTypes.getMessageSendStretFixupFn();
6502 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006503 }
John McCall234eac82011-05-13 23:16:18 +00006504 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
6505 fn = ObjCTypes.getMessageSendFpretFixupFn();
6506 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00006507 } else {
John McCall234eac82011-05-13 23:16:18 +00006508 if (isSuper) {
6509 fn = ObjCTypes.getMessageSendSuper2FixupFn();
6510 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006511 } else {
John McCall234eac82011-05-13 23:16:18 +00006512 fn = ObjCTypes.getMessageSendFixupFn();
6513 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00006514 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00006515 }
John McCall234eac82011-05-13 23:16:18 +00006516 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
6517 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006518
John McCall234eac82011-05-13 23:16:18 +00006519 // Append the selector name, except use underscores anywhere we
6520 // would have used colons.
6521 appendSelectorForMessageRefTable(messageRefName, selector);
6522
6523 llvm::GlobalVariable *messageRef
6524 = CGM.getModule().getGlobalVariable(messageRefName);
6525 if (!messageRef) {
John McCall9e8bb002011-05-14 03:10:52 +00006526 // Build the message ref structure.
John McCall234eac82011-05-13 23:16:18 +00006527 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
Chris Lattnere64d7ba2011-06-20 04:01:35 +00006528 llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
John McCall234eac82011-05-13 23:16:18 +00006529 messageRef = new llvm::GlobalVariable(CGM.getModule(),
6530 init->getType(),
6531 /*constant*/ false,
6532 llvm::GlobalValue::WeakAnyLinkage,
6533 init,
6534 messageRefName);
6535 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
6536 messageRef->setAlignment(16);
6537 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
6538 }
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006539
6540 bool requiresnullCheck = false;
David Blaikiebbafb8a2012-03-11 07:00:24 +00006541 if (CGM.getLangOpts().ObjCAutoRefCount && method)
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006542 for (ObjCMethodDecl::param_const_iterator i = method->param_begin(),
6543 e = method->param_end(); i != e; ++i) {
6544 const ParmVarDecl *ParamDecl = (*i);
6545 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
6546 if (!nullReturn.NullBB)
6547 nullReturn.init(CGF, arg0);
6548 requiresnullCheck = true;
6549 break;
6550 }
6551 }
6552
John McCall234eac82011-05-13 23:16:18 +00006553 llvm::Value *mref =
6554 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
6555
John McCall9e8bb002011-05-14 03:10:52 +00006556 // Update the message ref argument.
John McCall234eac82011-05-13 23:16:18 +00006557 args[1].RV = RValue::get(mref);
6558
6559 // Load the function to call from the message ref table.
6560 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
6561 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
6562
John McCalla729c622012-02-17 03:33:10 +00006563 callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
John McCall234eac82011-05-13 23:16:18 +00006564
John McCalla729c622012-02-17 03:33:10 +00006565 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Fariborz Jahanianc93fa982012-01-30 23:39:30 +00006566 return nullReturn.complete(CGF, result, resultType, formalArgs,
6567 requiresnullCheck ? method : 0);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00006568}
6569
6570/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006571CodeGen::RValue
6572CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00006573 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006574 QualType ResultType,
6575 Selector Sel,
6576 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006577 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00006578 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006579 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00006580 return isVTableDispatchedSelector(Sel)
6581 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006582 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00006583 false, CallArgs, Method)
6584 : EmitMessageSend(CGF, Return, ResultType,
6585 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006586 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00006587 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00006588}
6589
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006590llvm::GlobalVariable *
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006591CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006592 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
6593
Daniel Dunbara6468342009-03-02 05:18:14 +00006594 if (!GV) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006595 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006596 false, llvm::GlobalValue::ExternalLinkage,
6597 0, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006598 }
6599
6600 return GV;
6601}
6602
John McCall31168b02011-06-15 23:02:42 +00006603llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CGBuilderTy &Builder,
6604 IdentifierInfo *II) {
6605 llvm::GlobalVariable *&Entry = ClassReferences[II];
6606
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006607 if (!Entry) {
John McCall31168b02011-06-15 23:02:42 +00006608 std::string ClassName(getClassSymbolPrefix() + II->getName().str());
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00006609 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006610 Entry =
John McCall31168b02011-06-15 23:02:42 +00006611 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
6612 false, llvm::GlobalValue::InternalLinkage,
6613 ClassGV,
6614 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006615 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006616 CGM.getDataLayout().getABITypeAlignment(
John McCall31168b02011-06-15 23:02:42 +00006617 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006618 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006619 CGM.AddUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006620 }
John McCall31168b02011-06-15 23:02:42 +00006621
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006622 return Builder.CreateLoad(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006623}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006624
John McCall31168b02011-06-15 23:02:42 +00006625llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
6626 const ObjCInterfaceDecl *ID) {
6627 return EmitClassRefFromId(Builder, ID->getIdentifier());
6628}
6629
6630llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
6631 CGBuilderTy &Builder) {
6632 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
6633 return EmitClassRefFromId(Builder, II);
6634}
6635
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006636llvm::Value *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006637CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006638 const ObjCInterfaceDecl *ID) {
6639 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006640
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006641 if (!Entry) {
6642 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6643 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006644 Entry =
6645 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006646 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006647 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006648 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006649 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006650 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006651 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006652 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006653 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006654 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006655
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006656 return Builder.CreateLoad(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006657}
6658
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006659/// EmitMetaClassRef - Return a Value * of the address of _class_t
6660/// meta-data
6661///
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006662llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
6663 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006664 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
6665 if (Entry)
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006666 return Builder.CreateLoad(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006667
Daniel Dunbar15894b72009-04-07 05:48:37 +00006668 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006669 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006670 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006671 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006672 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006673 MetaClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006674 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006675 Entry->setAlignment(
Micah Villmowdd31ca12012-10-08 16:25:52 +00006676 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006677 ObjCTypes.ClassnfABIPtrTy));
6678
Daniel Dunbare60aa052009-04-15 19:03:14 +00006679 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006680 CGM.AddUsedGlobal(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006681
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006682 return Builder.CreateLoad(Entry);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006683}
6684
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006685/// GetClass - Return a reference to the class for the given interface
6686/// decl.
6687llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
6688 const ObjCInterfaceDecl *ID) {
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00006689 if (ID->isWeakImported()) {
Fariborz Jahanian95ace552009-11-17 22:42:00 +00006690 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6691 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
6692 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
6693 }
6694
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00006695 return EmitClassRef(Builder, ID);
6696}
6697
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006698/// Generates a message send where the super is the receiver. This is
6699/// a message send to self with special delivery semantics indicating
6700/// which class's method should be called.
6701CodeGen::RValue
6702CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00006703 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006704 QualType ResultType,
6705 Selector Sel,
6706 const ObjCInterfaceDecl *Class,
6707 bool isCategoryImpl,
6708 llvm::Value *Receiver,
6709 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00006710 const CodeGen::CallArgList &CallArgs,
6711 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006712 // ...
6713 // Create and init a super structure; this is a (receiver, class)
6714 // pair we will pass to objc_msgSendSuper.
6715 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00006716 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006717
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006718 llvm::Value *ReceiverAsObject =
6719 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
6720 CGF.Builder.CreateStore(ReceiverAsObject,
6721 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006722
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006723 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006724 llvm::Value *Target;
Fariborz Jahanian27678b02012-10-10 23:11:18 +00006725 if (IsClassMessage)
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00006726 Target = EmitMetaClassRef(CGF.Builder, Class);
Fariborz Jahanian27678b02012-10-10 23:11:18 +00006727 else
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00006728 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006729
Mike Stump18bb9282009-05-16 07:57:57 +00006730 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
6731 // ObjCTypes types.
Chris Lattner2192fe52011-07-18 04:24:23 +00006732 llvm::Type *ClassTy =
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006733 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
6734 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
6735 CGF.Builder.CreateStore(Target,
6736 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006737
John McCall9e8bb002011-05-14 03:10:52 +00006738 return (isVTableDispatchedSelector(Sel))
6739 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006740 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006741 true, CallArgs, Method)
6742 : EmitMessageSend(CGF, Return, ResultType,
6743 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006744 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00006745 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00006746}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006747
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006748llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006749 Selector Sel, bool lval) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006750 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006751
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006752 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006753 llvm::Constant *Casted =
6754 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
6755 ObjCTypes.SelectorPtrTy);
6756 Entry =
6757 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
6758 llvm::GlobalValue::InternalLinkage,
6759 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00006760 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00006761 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006762 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006763
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00006764 if (lval)
6765 return Entry;
Pete Cooper9d605512011-11-10 21:45:06 +00006766 llvm::LoadInst* LI = Builder.CreateLoad(Entry);
6767
6768 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6769 llvm::MDNode::get(VMContext,
6770 ArrayRef<llvm::Value*>()));
6771 return LI;
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006772}
Fariborz Jahanian06292952009-02-16 22:52:32 +00006773/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006774/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00006775///
6776void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006777 llvm::Value *src,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006778 llvm::Value *dst,
6779 llvm::Value *ivarOffset) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006780 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006781 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006782 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006783 assert(Size <= 8 && "does not support size > 8");
6784 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6785 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006786 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6787 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006788 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6789 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00006790 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
6791 src, dst, ivarOffset);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006792 return;
6793}
6794
6795/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
6796/// objc_assign_strongCast (id src, id *dst)
6797///
6798void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006799 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006800 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006801 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006802 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006803 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006804 assert(Size <= 8 && "does not support size > 8");
6805 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006806 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006807 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6808 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006809 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6810 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00006811 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006812 src, dst, "weakassign");
6813 return;
6814}
6815
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006816void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006817 CodeGen::CodeGenFunction &CGF,
6818 llvm::Value *DestPtr,
6819 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006820 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006821 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
6822 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006823 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00006824 DestPtr, SrcPtr, Size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00006825 return;
6826}
6827
Fariborz Jahanian06292952009-02-16 22:52:32 +00006828/// EmitObjCWeakRead - Code gen for loading value of a __weak
6829/// object: objc_read_weak (id *src)
6830///
6831llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006832 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006833 llvm::Value *AddrWeakObj) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006834 llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006835 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
6836 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00006837 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006838 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00006839 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-02-16 22:52:32 +00006840 return read_weak;
6841}
6842
6843/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
6844/// objc_assign_weak (id src, id *dst)
6845///
6846void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00006847 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006848 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006849 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006850 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006851 assert(Size <= 8 && "does not support size > 8");
6852 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6853 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006854 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6855 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006856 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6857 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00006858 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00006859 src, dst, "weakassign");
6860 return;
6861}
6862
6863/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
6864/// objc_assign_global (id src, id *dst)
6865///
6866void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00006867 llvm::Value *src, llvm::Value *dst,
6868 bool threadlocal) {
Chris Lattner2192fe52011-07-18 04:24:23 +00006869 llvm::Type * SrcTy = src->getType();
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006870 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmowdd31ca12012-10-08 16:25:52 +00006871 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00006872 assert(Size <= 8 && "does not support size > 8");
6873 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6874 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00006875 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6876 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00006877 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6878 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-07-20 20:30:03 +00006879 if (!threadlocal)
6880 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
6881 src, dst, "globalassign");
6882 else
6883 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
6884 src, dst, "threadlocalassign");
Fariborz Jahanian06292952009-02-16 22:52:32 +00006885 return;
6886}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006887
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006888void
John McCallbd309292010-07-06 01:34:17 +00006889CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6890 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006891 EmitAtSynchronizedStmt(CGF, S,
6892 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6893 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00006894}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006895
John McCall2ca705e2010-07-24 00:37:23 +00006896llvm::Constant *
Fariborz Jahanian831f0fc2011-06-23 19:00:08 +00006897CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall2ca705e2010-07-24 00:37:23 +00006898 // There's a particular fixed type info for 'id'.
6899 if (T->isObjCIdType() ||
6900 T->isObjCQualifiedIdType()) {
6901 llvm::Constant *IDEHType =
6902 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6903 if (!IDEHType)
6904 IDEHType =
6905 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6906 false,
6907 llvm::GlobalValue::ExternalLinkage,
6908 0, "OBJC_EHTYPE_id");
6909 return IDEHType;
6910 }
6911
6912 // All other types should be Objective-C interface pointer types.
6913 const ObjCObjectPointerType *PT =
6914 T->getAs<ObjCObjectPointerType>();
6915 assert(PT && "Invalid @catch type.");
6916 const ObjCInterfaceType *IT = PT->getInterfaceType();
6917 assert(IT && "Invalid @catch type.");
6918 return GetInterfaceEHType(IT->getDecl(), false);
6919}
6920
John McCallbd309292010-07-06 01:34:17 +00006921void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6922 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006923 EmitTryCatchStmt(CGF, S,
6924 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6925 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6926 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +00006927}
6928
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006929/// EmitThrowStmt - Generate code for a throw statement.
6930void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00006931 const ObjCAtThrowStmt &S,
6932 bool ClearInsertionPoint) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006933 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall248512a2011-10-01 10:32:24 +00006934 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer76399eb2011-09-27 21:06:10 +00006935 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Jay Foad5bd375a2011-07-15 08:37:34 +00006936 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall17afe452010-10-16 08:21:07 +00006937 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006938 } else {
Jay Foad5bd375a2011-07-15 08:37:34 +00006939 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall17afe452010-10-16 08:21:07 +00006940 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006941 }
6942
John McCall17afe452010-10-16 08:21:07 +00006943 CGF.Builder.CreateUnreachable();
Fariborz Jahanian1eab0522013-01-10 19:02:56 +00006944 if (ClearInsertionPoint)
6945 CGF.Builder.ClearInsertionPoint();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006946}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006947
John McCall2ca705e2010-07-24 00:37:23 +00006948llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006949CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006950 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006951 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006952
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006953 // If we don't need a definition, return the entry if found or check
6954 // if we use an external reference.
6955 if (!ForDefinition) {
6956 if (Entry)
6957 return Entry;
Daniel Dunbard7beeea2009-04-07 06:43:45 +00006958
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006959 // If this type (or a super class) has the __objc_exception__
6960 // attribute, emit an external reference.
Douglas Gregor78bd61f2009-06-18 16:11:24 +00006961 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006962 return Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006963 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006964 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006965 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006966 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006967 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006968 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006969
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006970 // Otherwise we need to either make a new entry or fill in the
6971 // initializer.
6972 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar15894b72009-04-07 05:48:37 +00006973 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006974 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006975 llvm::GlobalVariable *VTableGV =
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006976 CGM.getModule().getGlobalVariable(VTableName);
6977 if (!VTableGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006978 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6979 false,
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006980 llvm::GlobalValue::ExternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006981 0, VTableName);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006982
Chris Lattnerece04092012-02-07 00:39:47 +00006983 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006984
Benjamin Kramer22d24c22011-10-15 12:20:02 +00006985 llvm::Constant *Values[] = {
6986 llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
6987 GetClassName(ID->getIdentifier()),
6988 GetClassGlobal(ClassName)
6989 };
Owen Anderson170229f2009-07-14 23:10:40 +00006990 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00006991 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006992
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006993 if (Entry) {
6994 Entry->setInitializer(Init);
6995 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00006996 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006997 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006998 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006999 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00007000 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007001 }
7002
David Blaikiebbafb8a2012-03-11 07:00:24 +00007003 if (CGM.getLangOpts().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar15894b72009-04-07 05:48:37 +00007004 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Micah Villmowdd31ca12012-10-08 16:25:52 +00007005 Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00007006 ObjCTypes.EHTypeTy));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00007007
7008 if (ForDefinition) {
7009 Entry->setSection("__DATA,__objc_const");
7010 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
7011 } else {
7012 Entry->setSection("__DATA,__datacoal_nt,coalesced");
7013 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +00007014
7015 return Entry;
7016}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00007017
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00007018/* *** */
7019
Daniel Dunbarb036db82008-08-13 03:21:16 +00007020CodeGen::CGObjCRuntime *
7021CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall5fb5df92012-06-20 06:18:46 +00007022 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7023 case ObjCRuntime::FragileMacOSX:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007024 return new CGObjCMac(CGM);
John McCall5fb5df92012-06-20 06:18:46 +00007025
7026 case ObjCRuntime::MacOSX:
7027 case ObjCRuntime::iOS:
7028 return new CGObjCNonFragileABIMac(CGM);
7029
David Chisnallb601c962012-07-03 20:49:52 +00007030 case ObjCRuntime::GNUstep:
7031 case ObjCRuntime::GCC:
John McCall775086e2012-07-12 02:07:58 +00007032 case ObjCRuntime::ObjFW:
John McCall5fb5df92012-06-20 06:18:46 +00007033 llvm_unreachable("these runtimes are not Mac runtimes");
7034 }
7035 llvm_unreachable("bad runtime");
Daniel Dunbar303e2c22008-08-11 02:45:11 +00007036}