blob: 91fa1d597f2d1c58834c4a9a27fe307fd272c4b4 [file] [log] [blame]
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattnerfc8f0e12011-04-15 05:22:18 +000010// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
John McCalld16c2cf2011-02-08 08:22:06 +000015#include "CGBlocks.h"
John McCall36f893c2011-01-28 11:13:47 +000016#include "CGCleanup.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000017#include "CGRecordLayout.h"
18#include "CodeGenFunction.h"
19#include "CodeGenModule.h"
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000020#include "clang/AST/ASTContext.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000021#include "clang/AST/Decl.h"
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000022#include "clang/AST/DeclObjC.h"
Anders Carlsson19cc4ab2009-07-18 19:43:29 +000023#include "clang/AST/RecordLayout.h"
Chris Lattner16f00492009-04-26 01:32:48 +000024#include "clang/AST/StmtObjC.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000025#include "clang/Basic/LangOptions.h"
Chandler Carruth06057ce2010-06-15 23:19:56 +000026#include "clang/Frontend/CodeGenOptions.h"
Chandler Carruth55fc8732012-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 Carruth3b844ba2013-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 McCall8e3f8612010-07-13 22:12:14 +000036#include "llvm/Support/CallSite.h"
Daniel Dunbar33063492009-09-07 00:20:42 +000037#include "llvm/Support/raw_ostream.h"
Torok Edwinf42e4a62009-08-24 13:25:12 +000038#include <cstdio>
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000039
40using namespace clang;
Daniel Dunbar46f45b92008-09-09 01:06:48 +000041using namespace CodeGen;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000042
43namespace {
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000044
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +000047
Fariborz Jahanianee0af742009-01-21 22:04:16 +000048class ObjCCommonTypesHelper {
Owen Andersona1cf15f2009-07-14 23:10:40 +000049protected:
50 llvm::LLVMContext &VMContext;
Daniel Dunbar6bff2512009-08-03 17:06:42 +000051
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000052private:
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +000060 llvm::Constant *getMessageSendFn() const {
John McCallf85e1932011-06-15 23:02:42 +000061 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
62 // be called a lot.
Chris Lattner9cbe4f02011-07-09 17:41:47 +000063 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall0774cb82011-05-15 01:53:33 +000064 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
65 params, true),
John McCallf85e1932011-06-15 23:02:42 +000066 "objc_msgSend",
Bill Wendling72390b32012-12-20 19:27:06 +000067 llvm::Attribute::get(CGM.getLLVMContext(),
68 llvm::Attribute::NonLazyBind));
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000069 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000070
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +000076 llvm::Constant *getMessageSendStretFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +000077 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall0774cb82011-05-15 01:53:33 +000078 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
79 params, true),
80 "objc_msgSend_stret");
Daniel Dunbar6bff2512009-08-03 17:06:42 +000081
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000082 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000083
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +000089 llvm::Constant *getMessageSendFpretFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +000090 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Chris Lattner8b418682012-02-07 00:39:47 +000091 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
92 params, true),
John McCall0774cb82011-05-15 01:53:33 +000093 "objc_msgSend_fpret");
Daniel Dunbar6bff2512009-08-03 17:06:42 +000094
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000095 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000096
Anders Carlssoneea64802011-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 McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +0000118 llvm::Constant *getMessageSendSuperFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000119 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000120 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000121 params, true),
122 "objc_msgSendSuper");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000123 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000124
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +0000129 llvm::Constant *getMessageSendSuperFn2() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000130 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000131 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000132 params, true),
133 "objc_msgSendSuper2");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000134 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000135
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +0000140 llvm::Constant *getMessageSendSuperStretFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000141 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000142 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000143 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000144 "objc_msgSendSuper_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000145 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000146
John McCall0774cb82011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +0000151 llvm::Constant *getMessageSendSuperStretFn2() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000152 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000153 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000154 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000155 "objc_msgSendSuper2_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000156 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000157
Fariborz Jahaniand0f8a8d2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000162
Fariborz Jahaniand0f8a8d2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000167
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000168protected:
169 CodeGen::CodeGenModule &CGM;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000170
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000171public:
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000172 llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Bob Wilsondc8dab62011-11-30 01:57:58 +0000173 llvm::Type *Int8PtrTy, *Int8PtrPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000174
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000175 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000176 llvm::Type *ObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000177
Fariborz Jahanian6d657c42008-11-18 20:18:11 +0000178 /// PtrObjectPtrTy - LLVM type for id *
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000179 llvm::Type *PtrObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000180
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000181 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000182 llvm::Type *SelectorPtrTy;
Douglas Gregor4c86fdb2012-01-17 18:36:30 +0000183
184private:
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000185 /// ProtocolPtrTy - LLVM type for external protocol handles
186 /// (typeof(Protocol))
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000187 llvm::Type *ExternalProtocolPtrTy;
Douglas Gregor4c86fdb2012-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 Dunbar19cd87e2008-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 Dunbar6bff2512009-08-03 17:06:42 +0000207
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000208 /// SuperTy - LLVM type for struct objc_super.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000209 llvm::StructType *SuperTy;
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000210 /// SuperPtrTy - LLVM type for struct objc_super *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000211 llvm::Type *SuperPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000212
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000213 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
214 /// in GCC parlance).
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000215 llvm::StructType *PropertyTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000216
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000217 /// PropertyListTy - LLVM type for struct objc_property_list
218 /// (_prop_list_t in GCC parlance).
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000219 llvm::StructType *PropertyListTy;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000220 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000221 llvm::Type *PropertyListPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000222
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000223 // MethodTy - LLVM type for struct objc_method.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000224 llvm::StructType *MethodTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000225
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000226 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000227 llvm::Type *CacheTy;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000228 /// CachePtrTy - LLVM type for struct objc_cache *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000229 llvm::Type *CachePtrTy;
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +0000230
Chris Lattner72db6c32009-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 Lattner5f9e2722011-07-23 10:55:15 +0000235 SmallVector<CanQualType,4> Params;
John McCallead608a2010-02-26 00:48:12 +0000236 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
237 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattner72db6c32009-04-22 02:44:54 +0000238 Params.push_back(IdType);
239 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000240 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000241 Params.push_back(Ctx.BoolTy);
Chris Lattner2acc6e32011-07-18 04:24:23 +0000242 llvm::FunctionType *FTy =
John McCall0f3d0972012-07-07 06:41:13 +0000243 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(IdType, Params,
244 FunctionType::ExtInfo(),
245 RequiredArgs::All));
Chris Lattner72db6c32009-04-22 02:44:54 +0000246 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
247 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000248
Chris Lattner72db6c32009-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 Lattner5f9e2722011-07-23 10:55:15 +0000253 SmallVector<CanQualType,6> Params;
John McCallead608a2010-02-26 00:48:12 +0000254 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
255 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattner72db6c32009-04-22 02:44:54 +0000256 Params.push_back(IdType);
257 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000258 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000259 Params.push_back(IdType);
260 Params.push_back(Ctx.BoolTy);
261 Params.push_back(Ctx.BoolTy);
Chris Lattner2acc6e32011-07-18 04:24:23 +0000262 llvm::FunctionType *FTy =
John McCall0f3d0972012-07-07 06:41:13 +0000263 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
264 FunctionType::ExtInfo(),
265 RequiredArgs::All));
Chris Lattner72db6c32009-04-22 02:44:54 +0000266 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
267 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000268
Ted Kremenekebcb57a2012-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 McCall0f3d0972012-07-07 06:41:13 +0000289 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
290 FunctionType::ExtInfo(),
291 RequiredArgs::All));
Ted Kremenekebcb57a2012-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 Jahanian6cc59062010-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 Lattner5f9e2722011-07-23 10:55:15 +0000309 SmallVector<CanQualType,5> Params;
Fariborz Jahanian6cc59062010-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 Lattner2acc6e32011-07-18 04:24:23 +0000315 llvm::FunctionType *FTy =
John McCall0f3d0972012-07-07 06:41:13 +0000316 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
317 FunctionType::ExtInfo(),
318 RequiredArgs::All));
Fariborz Jahanian6cc59062010-04-12 18:18:10 +0000319 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
320 }
321
Fariborz Jahaniane3173022012-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 McCall0f3d0972012-07-07 06:41:13 +0000335 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
336 FunctionType::ExtInfo(),
337 RequiredArgs::All));
Fariborz Jahaniane3173022012-01-06 18:07:23 +0000338 return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
339 }
340
Chris Lattner72db6c32009-04-22 02:44:54 +0000341 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000342 CodeGen::CodeGenTypes &Types = CGM.getTypes();
343 ASTContext &Ctx = CGM.getContext();
Chris Lattner72db6c32009-04-22 02:44:54 +0000344 // void objc_enumerationMutation (id)
Chris Lattner5f9e2722011-07-23 10:55:15 +0000345 SmallVector<CanQualType,1> Params;
John McCallead608a2010-02-26 00:48:12 +0000346 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2acc6e32011-07-18 04:24:23 +0000347 llvm::FunctionType *FTy =
John McCall0f3d0972012-07-07 06:41:13 +0000348 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
John McCallde5d3c72012-02-17 03:33:10 +0000349 FunctionType::ExtInfo(),
350 RequiredArgs::All));
Chris Lattner72db6c32009-04-22 02:44:54 +0000351 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
352 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000353
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000354 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattner72db6c32009-04-22 02:44:54 +0000355 llvm::Constant *getGcReadWeakFn() {
356 // id objc_read_weak (id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000357 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000358 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000359 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000360 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000361 }
362
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000363 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner96508e12009-04-17 22:12:36 +0000364 llvm::Constant *getGcAssignWeakFn() {
365 // id objc_assign_weak (id, id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000366 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner96508e12009-04-17 22:12:36 +0000367 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000368 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner96508e12009-04-17 22:12:36 +0000369 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
370 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000371
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000372 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000373 llvm::Constant *getGcAssignGlobalFn() {
374 // id objc_assign_global(id, id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000375 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000376 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000377 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000378 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
379 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000380
Fariborz Jahanian021a7a62010-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 Lattner9cbe4f02011-07-09 17:41:47 +0000384 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000385 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000386 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000387 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
388 }
389
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000390 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000391 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +0000392 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000393 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
394 CGM.PtrDiffTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000395 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000396 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000397 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
398 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000399
Fariborz Jahanian082b02e2009-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 Lattner9cbe4f02011-07-09 17:41:47 +0000403 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall0774cb82011-05-15 01:53:33 +0000404 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000405 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
406 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000407
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000408 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000409 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000410 // id objc_assign_strongCast(id, id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000411 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000412 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000413 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000414 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
415 }
Anders Carlssonf57c5b22009-02-16 22:59:18 +0000416
417 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000418 llvm::Constant *getExceptionThrowFn() {
419 // void objc_exception_throw(id)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000420 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerbbccd612009-04-22 02:38:11 +0000421 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000422 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000423 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
424 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000425
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000426 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
427 llvm::Constant *getExceptionRethrowFn() {
428 // void objc_exception_rethrow(void)
John McCall0774cb82011-05-15 01:53:33 +0000429 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000430 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
431 }
432
Daniel Dunbar1c566672009-02-24 01:43:46 +0000433 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000434 llvm::Constant *getSyncEnterFn() {
Aaron Ballman2d234d732012-09-06 16:44:16 +0000435 // int objc_sync_enter (id)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000436 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000437 llvm::FunctionType *FTy =
Aaron Ballman2d234d732012-09-06 16:44:16 +0000438 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000439 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
440 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000441
Daniel Dunbar1c566672009-02-24 01:43:46 +0000442 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000443 llvm::Constant *getSyncExitFn() {
Aaron Ballman2d234d732012-09-06 16:44:16 +0000444 // int objc_sync_exit (id)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000445 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerbbccd612009-04-22 02:38:11 +0000446 llvm::FunctionType *FTy =
Aaron Ballman2d234d732012-09-06 16:44:16 +0000447 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000448 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
449 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000450
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000451 llvm::Constant *getSendFn(bool IsSuper) const {
452 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
453 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000454
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000455 llvm::Constant *getSendFn2(bool IsSuper) const {
456 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
457 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000458
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000459 llvm::Constant *getSendStretFn(bool IsSuper) const {
460 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
461 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000462
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000463 llvm::Constant *getSendStretFn2(bool IsSuper) const {
464 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
465 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000466
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000467 llvm::Constant *getSendFpretFn(bool IsSuper) const {
468 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
469 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000470
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000471 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
472 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
473 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000474
Anders Carlssoneea64802011-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 Jahanianee0af742009-01-21 22:04:16 +0000483 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
484 ~ObjCCommonTypesHelper(){}
485};
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000486
Fariborz Jahanianee0af742009-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 Jahanianee0af742009-01-21 22:04:16 +0000490public:
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000491 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000492 llvm::StructType *SymtabTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000493 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000494 llvm::Type *SymtabPtrTy;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000495 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000496 llvm::StructType *ModuleTy;
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000497
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000498 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000499 llvm::StructType *ProtocolTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000500 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000501 llvm::Type *ProtocolPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000502 /// ProtocolExtensionTy - LLVM type for struct
503 /// objc_protocol_extension.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000504 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000505 /// ProtocolExtensionTy - LLVM type for struct
506 /// objc_protocol_extension *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000507 llvm::Type *ProtocolExtensionPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000508 /// MethodDescriptionTy - LLVM type for struct
509 /// objc_method_description.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000510 llvm::StructType *MethodDescriptionTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000511 /// MethodDescriptionListTy - LLVM type for struct
512 /// objc_method_description_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000513 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000514 /// MethodDescriptionListPtrTy - LLVM type for struct
515 /// objc_method_description_list *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000516 llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000517 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000518 llvm::StructType *ProtocolListTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000519 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000520 llvm::Type *ProtocolListPtrTy;
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000521 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000522 llvm::StructType *CategoryTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000523 /// ClassTy - LLVM type for struct objc_class.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000524 llvm::StructType *ClassTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000525 /// ClassPtrTy - LLVM type for struct objc_class *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000526 llvm::Type *ClassPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000527 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000528 llvm::StructType *ClassExtensionTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000529 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000530 llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000531 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000532 llvm::StructType *IvarTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000533 /// IvarListTy - LLVM type for struct objc_ivar_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000534 llvm::Type *IvarListTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000535 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000536 llvm::Type *IvarListPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000537 /// MethodListTy - LLVM type for struct objc_method_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000538 llvm::Type *MethodListTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000539 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000540 llvm::Type *MethodListPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000541
Anders Carlsson124526b2008-09-09 10:10:21 +0000542 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000543 llvm::Type *ExceptionDataTy;
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +0000544
Anders Carlsson124526b2008-09-09 10:10:21 +0000545 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000546 llvm::Constant *getExceptionTryEnterFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000547 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000548 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000549 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000550 "objc_exception_try_enter");
Chris Lattner34b02a12009-04-22 02:26:14 +0000551 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000552
553 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000554 llvm::Constant *getExceptionTryExitFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000555 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000556 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000557 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000558 "objc_exception_try_exit");
Chris Lattner34b02a12009-04-22 02:26:14 +0000559 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000560
561 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000562 llvm::Constant *getExceptionExtractFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000563 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000564 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000565 params, false),
Chris Lattner34b02a12009-04-22 02:26:14 +0000566 "objc_exception_extract");
Chris Lattner34b02a12009-04-22 02:26:14 +0000567 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000568
Anders Carlsson124526b2008-09-09 10:10:21 +0000569 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000570 llvm::Constant *getExceptionMatchFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000571 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000572 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000573 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000574 "objc_exception_match");
575
Chris Lattner34b02a12009-04-22 02:26:14 +0000576 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000577
Anders Carlsson124526b2008-09-09 10:10:21 +0000578 /// SetJmpFn - LLVM _setjmp function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000579 llvm::Constant *getSetJmpFn() {
John McCall0774cb82011-05-15 01:53:33 +0000580 // This is specifically the prototype for x86.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000581 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
John McCall0774cb82011-05-15 01:53:33 +0000582 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
583 params, false),
Bill Wendlinga9e269e2011-11-29 00:10:10 +0000584 "_setjmp",
Bill Wendling72390b32012-12-20 19:27:06 +0000585 llvm::Attribute::get(CGM.getLLVMContext(),
586 llvm::Attribute::NonLazyBind));
Chris Lattner34b02a12009-04-22 02:26:14 +0000587 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000588
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000589public:
590 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000591 ~ObjCTypesHelper() {}
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000592};
593
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000594/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000595/// modern abi
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000596class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000597public:
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000598
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000599 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000600 llvm::StructType *MethodListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000601
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000602 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000603 llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000604
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000605 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000606 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000607
Daniel Dunbar948e2582009-02-15 07:36:20 +0000608 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000609 llvm::Type *ProtocolnfABIPtrTy;
Daniel Dunbar948e2582009-02-15 07:36:20 +0000610
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000611 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000612 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000613
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000614 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000615 llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000616
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000617 // ClassnfABITy - LLVM for struct _class_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000618 llvm::StructType *ClassnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000619
Fariborz Jahanianaa23b572009-01-23 23:53:38 +0000620 // ClassnfABIPtrTy - LLVM for struct _class_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000621 llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000622
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000623 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000624 llvm::StructType *IvarnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000625
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000626 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000627 llvm::StructType *IvarListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000628
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000629 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000630 llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000631
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000632 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000633 llvm::StructType *ClassRonfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000634
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000635 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000636 llvm::Type *ImpnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000637
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000638 // CategorynfABITy - LLVM for struct _category_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000639 llvm::StructType *CategorynfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000640
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000641 // New types for nonfragile abi messaging.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000642
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000643 // MessageRefTy - LLVM for:
644 // struct _message_ref_t {
645 // IMP messenger;
646 // SEL name;
647 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000648 llvm::StructType *MessageRefTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000649 // MessageRefCTy - clang type for struct _message_ref_t
650 QualType MessageRefCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000651
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000652 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000653 llvm::Type *MessageRefPtrTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000654 // MessageRefCPtrTy - clang type for struct _message_ref_t*
655 QualType MessageRefCPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000656
Fariborz Jahanianef163782009-02-05 01:13:09 +0000657 // MessengerTy - Type of the messenger (shown as IMP above)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000658 llvm::FunctionType *MessengerTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000659
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000660 // SuperMessageRefTy - LLVM for:
661 // struct _super_message_ref_t {
662 // SUPER_IMP messenger;
663 // SEL name;
664 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000665 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000666
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000667 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000668 llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000669
Chris Lattner1c02f862009-04-22 02:53:24 +0000670 llvm::Constant *getMessageSendFixupFn() {
671 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000672 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000673 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000674 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000675 "objc_msgSend_fixup");
676 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000677
Chris Lattner1c02f862009-04-22 02:53:24 +0000678 llvm::Constant *getMessageSendFpretFixupFn() {
679 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000680 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000681 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000682 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000683 "objc_msgSend_fpret_fixup");
684 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000685
Chris Lattner1c02f862009-04-22 02:53:24 +0000686 llvm::Constant *getMessageSendStretFixupFn() {
687 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000688 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000689 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000690 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000691 "objc_msgSend_stret_fixup");
692 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000693
Chris Lattner1c02f862009-04-22 02:53:24 +0000694 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000695 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000696 // struct _super_message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000697 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000698 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000699 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000700 "objc_msgSendSuper2_fixup");
701 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000702
Chris Lattner1c02f862009-04-22 02:53:24 +0000703 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000704 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000705 // struct _super_message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000706 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000707 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000708 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000709 "objc_msgSendSuper2_stret_fixup");
710 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000711
Chris Lattner8a569112009-04-22 02:15:23 +0000712 llvm::Constant *getObjCEndCatchFn() {
John McCall0774cb82011-05-15 01:53:33 +0000713 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattner8a569112009-04-22 02:15:23 +0000714 "objc_end_catch");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000715
Chris Lattner8a569112009-04-22 02:15:23 +0000716 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000717
Chris Lattner8a569112009-04-22 02:15:23 +0000718 llvm::Constant *getObjCBeginCatchFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000719 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000720 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000721 params, false),
Chris Lattner8a569112009-04-22 02:15:23 +0000722 "objc_begin_catch");
723 }
Daniel Dunbare588b992009-03-01 04:46:24 +0000724
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000725 llvm::StructType *EHTypeTy;
726 llvm::Type *EHTypePtrTy;
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +0000727
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000728 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
729 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000730};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000731
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000732class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000733public:
734 // FIXME - accessibility
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000735 class GC_IVAR {
Fariborz Jahanian820e0202009-03-11 00:07:04 +0000736 public:
Eli Friedmane5b46662012-11-06 22:15:52 +0000737 unsigned ivar_bytepos;
738 unsigned ivar_size;
739 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000740 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar0941b492009-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 Jahaniana5a10c32009-03-10 16:22:08 +0000746 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000747
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000748 class SKIP_SCAN {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000749 public:
750 unsigned skip;
751 unsigned scan;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000752 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000753 : skip(_skip), scan(_scan) {}
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000754 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000755
Fariborz Jahaniane11dba82012-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 Jahanian1da01d62012-11-07 20:00:32 +0000811 CharUnits block_var_bytepos;
812 CharUnits block_var_size;
Fariborz Jahaniane11dba82012-10-25 21:15:04 +0000813 RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +0000814 CharUnits BytePos = CharUnits::Zero(),
815 CharUnits Size = CharUnits::Zero())
Fariborz Jahanianc46b4352012-10-27 21:10:38 +0000816 : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
Fariborz Jahaniane11dba82012-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 Jahanianee0af742009-01-21 22:04:16 +0000824protected:
Owen Anderson69243822009-07-13 04:10:07 +0000825 llvm::LLVMContext &VMContext;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000826 // FIXME! May not be needing this after all.
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000827 unsigned ObjCABI;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000828
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000829 // gc ivar layout bitmap calculation helper caches.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000830 SmallVector<GC_IVAR, 16> SkipIvars;
831 SmallVector<GC_IVAR, 16> IvarsInfo;
Fariborz Jahaniane11dba82012-10-25 21:15:04 +0000832
833 // arc/mrr layout of captured block literal variables.
834 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000835
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000836 /// LazySymbols - Symbols to generate a lazy reference for. See
837 /// DefinedSymbols and FinishModule().
Daniel Dunbar33063492009-09-07 00:20:42 +0000838 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000839
Daniel Dunbar242d4dc2008-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 Dunbar33063492009-09-07 00:20:42 +0000844 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000845
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000846 /// ClassNames - uniqued class names.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000847 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000848
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000849 /// MethodVarNames - uniqued method variable names.
850 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000851
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +0000852 /// DefinedCategoryNames - list of category names in form Class_Category.
853 llvm::SetVector<std::string> DefinedCategoryNames;
854
Daniel Dunbar6efc0c52008-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 Dunbar6bff2512009-08-03 17:06:42 +0000858
Daniel Dunbarc45ef602008-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 Dunbar6bff2512009-08-03 17:06:42 +0000862
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000863 /// PropertyNames - uniqued method variable names.
864 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000865
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000866 /// ClassReferences - uniqued class references.
867 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000868
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000869 /// SelectorReferences - uniqued selector references.
870 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000871
Daniel Dunbar6efc0c52008-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 Dunbar6bff2512009-08-03 17:06:42 +0000876
Daniel Dunbar0c0e7a62008-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 Dunbar6bff2512009-08-03 17:06:42 +0000880
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000881 /// DefinedClasses - List of defined classes.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000882 SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000883
884 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000885 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000886
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000887 /// DefinedCategories - List of defined categories.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000888 SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000889
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000890 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000891 SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000892
Fariborz Jahanian56210f72009-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 Lattner5f9e2722011-07-23 10:55:15 +0000897 SmallVectorImpl<char> &NameOut);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000898
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000903
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000904 /// GetMethodVarType - Return a unique constant for the given
Bob Wilsondc8dab62011-11-30 01:57:58 +0000905 /// method's type encoding string. The return value has type char *.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000906
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000907 // FIXME: This is a horrible name.
Bob Wilsondc8dab62011-11-30 01:57:58 +0000908 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
909 bool Extended = false);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +0000910 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000911
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000915
Fariborz Jahanian56210f72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000919
Fariborz Jahanian058a1b72009-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 Dunbar6bff2512009-08-03 17:06:42 +0000923
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +0000924 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
925
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000926 /// BuildIvarLayout - Builds ivar layout bitmap for the class
927 /// implementation for the __strong or __weak case.
928 ///
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000929 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
930 bool ForStrongLayout);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +0000931
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +0000932 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000933
Daniel Dunbard58edcb2009-05-03 14:10:34 +0000934 void BuildAggrIvarRecordLayout(const RecordType *RT,
Eli Friedmane5b46662012-11-06 22:15:52 +0000935 unsigned int BytePos, bool ForStrongLayout,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000936 bool &HasUnion);
Daniel Dunbar5a5a8032009-05-03 21:05:10 +0000937 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000938 const llvm::StructLayout *Layout,
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000939 const RecordDecl *RD,
Bill Wendling795b1002012-02-22 09:30:11 +0000940 ArrayRef<const FieldDecl*> RecFields,
Eli Friedmane5b46662012-11-06 22:15:52 +0000941 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahanian81adc052009-04-24 16:17:09 +0000942 bool &HasUnion);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +0000943
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +0000944 Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
Fariborz Jahanian44fcff92012-11-02 22:51:18 +0000945
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +0000946 void UpdateRunSkipBlockVars(bool IsByref,
947 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +0000948 CharUnits FieldOffset,
949 CharUnits FieldSize);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +0000950
951 void BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +0000952 CharUnits BytePos, bool &HasUnion,
953 bool ByrefLayout=false);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +0000954
955 void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
956 const RecordDecl *RD,
957 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +0000958 CharUnits BytePos, bool &HasUnion,
959 bool ByrefLayout);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +0000960
Fariborz Jahanianf22ae652012-11-01 18:32:55 +0000961 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
962
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +0000963 llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
964
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000965
Fariborz Jahaniand80d81b2009-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 Dunbar6bff2512009-08-03 17:06:42 +0000970
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000971 /// EmitPropertyList - Emit the given property list. The return
972 /// value has type PropertyListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000973 llvm::Constant *EmitPropertyList(Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000974 const Decl *Container,
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000975 const ObjCContainerDecl *OCD,
976 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000977
Bob Wilsondc8dab62011-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 Wendlingbb028552012-02-07 09:25:09 +0000981 ArrayRef<llvm::Constant*> MethodTypes,
Bob Wilsondc8dab62011-11-30 01:57:58 +0000982 const ObjCCommonTypesHelper &ObjCTypes);
983
Fariborz Jahanian191dcd72009-12-12 21:26:21 +0000984 /// PushProtocolProperties - Push protocol's property on the input stack.
Bill Wendling3964e622012-02-09 22:16:49 +0000985 void PushProtocolProperties(
986 llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000987 SmallVectorImpl<llvm::Constant*> &Properties,
Bill Wendling3964e622012-02-09 22:16:49 +0000988 const Decl *Container,
989 const ObjCProtocolDecl *PROTO,
990 const ObjCCommonTypesHelper &ObjCTypes);
Fariborz Jahanian191dcd72009-12-12 21:26:21 +0000991
Fariborz Jahanianda320092009-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 Jahanianb21f07e2009-03-08 20:18:37 +0000996
Daniel Dunbarfd65d372009-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 Lattnerad64e022009-07-17 23:57:13 +00001002 /// global to the "llvm.used" list.
Daniel Dunbar35bd7632009-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 Dunbarc1583062009-04-14 17:42:51 +00001010 /// "llvm.used".
Chris Lattner5f9e2722011-07-23 10:55:15 +00001011 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +00001012 llvm::Constant *Init,
1013 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +00001014 unsigned Align,
1015 bool AddToUsed);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00001016
John McCall944c8432011-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 Dunbar3e5f0d82009-04-20 06:54:31 +00001027
Daniel Dunbarfce176b2010-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 Jahanianee0af742009-01-21 22:04:16 +00001032public:
Owen Anderson69243822009-07-13 04:10:07 +00001033 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCallde5d3c72012-02-17 03:33:10 +00001034 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001035
David Chisnall0d13f6f2010-01-23 02:40:42 +00001036 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001037
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001038 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
1039 const ObjCContainerDecl *CD=0);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001040
Fariborz Jahanianda320092009-01-29 19:24:30 +00001041 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001042
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00001047
Fariborz Jahanianda320092009-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 McCall6b5a61b2011-02-07 10:33:21 +00001053 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1054 const CGBlockInfo &blockInfo);
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00001055 virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1056 const CGBlockInfo &blockInfo);
Fariborz Jahanian89ecd412010-08-04 16:57:49 +00001057
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00001058 virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1059 QualType T);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001060};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001061
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001062class CGObjCMac : public CGObjCCommonMac {
1063private:
1064 ObjCTypesHelper ObjCTypes;
Daniel Dunbarf77ac862008-08-11 21:35:06 +00001065
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001066 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001067 /// information.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001068 void EmitModuleInfo();
1069
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001070 /// EmitModuleSymols - Emit module symbols, the list of defined
1071 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001072 llvm::Constant *EmitModuleSymbols();
1073
Daniel Dunbarf77ac862008-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 Dunbar6efc0c52008-08-13 03:21:16 +00001077
Daniel Dunbar27f9d772008-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 Dunbar6bff2512009-08-03 17:06:42 +00001085 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001086 const ObjCInterfaceDecl *ID);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00001087
John McCallf85e1932011-06-15 23:02:42 +00001088 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
1089 IdentifierInfo *II);
1090
1091 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
1092
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00001093 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1094 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar27f9d772008-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 Jahanian46b86c62009-01-28 19:12:34 +00001102 bool ForClass);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001103
Daniel Dunbarf56f1912008-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 Dunbar27f9d772008-08-21 04:36:09 +00001109 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001110 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001111 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1112 llvm::Constant *Protocols,
Bill Wendlingbb028552012-02-07 09:25:09 +00001113 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001114
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001115 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001116
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001117 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001118
1119 /// EmitMethodList - Emit the method list for the given
Daniel Dunbaraf05bb92008-08-26 08:29:31 +00001120 /// implementation. The return value has type MethodListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +00001121 llvm::Constant *EmitMethodList(Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001122 const char *Section,
Bill Wendlingbb028552012-02-07 09:25:09 +00001123 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001124
1125 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001126 /// method declarations.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001127 /// - TypeName: The name for the type containing the methods.
Sylvestre Ledruf3477c12012-09-27 10:16:10 +00001128 /// - IsProtocol: True iff these methods are for a protocol.
1129 /// - ClassMethds: True iff these are class methods.
Daniel Dunbar6efc0c52008-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 Lattner5f9e2722011-07-23 10:55:15 +00001136 llvm::Constant *EmitMethodDescList(Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001137 const char *Section,
Bill Wendlingbb028552012-02-07 09:25:09 +00001138 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001139
Daniel Dunbar0c0e7a62008-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 Jahanianda320092009-01-29 19:24:30 +00001143 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-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 Jahanianda320092009-01-29 19:24:30 +00001149 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001150
Daniel Dunbar6efc0c52008-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 Dunbarae226fa2008-08-27 02:31:56 +00001155 llvm::Constant *
1156 EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingbb028552012-02-07 09:25:09 +00001157 ArrayRef<llvm::Constant*> OptInstanceMethods,
1158 ArrayRef<llvm::Constant*> OptClassMethods,
1159 ArrayRef<llvm::Constant*> MethodTypesExt);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001160
1161 /// EmitProtocolList - Generate the list of referenced
1162 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +00001163 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardbc93372008-08-21 21:57:41 +00001164 ObjCProtocolDecl::protocol_iterator begin,
1165 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001166
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001167 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1168 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001169 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1170 bool lval=false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001171
1172public:
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001173 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001174
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001175 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001176
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001177 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001178 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001179 QualType ResultType,
1180 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001181 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001182 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001183 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001184 const ObjCMethodDecl *Method);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001185
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001186 virtual CodeGen::RValue
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001187 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001188 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001189 QualType ResultType,
1190 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001191 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001192 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001193 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001194 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001195 const CallArgList &CallArgs,
1196 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001197
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001198 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001199 const ObjCInterfaceDecl *ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001200
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001201 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1202 bool lval = false);
Fariborz Jahaniandf9ccc62009-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 Jahaniancf5abc72011-06-23 19:00:08 +00001209 virtual llvm::Constant *GetEHType(QualType T);
John McCall5a180392010-07-24 00:37:23 +00001210
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001211 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001212
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001213 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001214
Daniel Dunbar85fdea02012-02-28 15:36:15 +00001215 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}
David Chisnall29254f42012-01-31 18:59:20 +00001216
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001217 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001218 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001219
Chris Lattner74391b42009-03-22 21:03:39 +00001220 virtual llvm::Constant *GetPropertyGetFunction();
1221 virtual llvm::Constant *GetPropertySetFunction();
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001222 virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1223 bool copy);
David Chisnall8fac25d2010-12-26 22:13:16 +00001224 virtual llvm::Constant *GetGetStructFunction();
1225 virtual llvm::Constant *GetSetStructFunction();
David Chisnalld397cfe2012-12-17 18:54:24 +00001226 virtual llvm::Constant *GetCppAtomicObjectGetFunction();
1227 virtual llvm::Constant *GetCppAtomicObjectSetFunction();
Chris Lattner74391b42009-03-22 21:03:39 +00001228 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001229
John McCallf1549f62010-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 Carlsson64d5d6c2008-09-09 10:04:29 +00001235 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6a3c70e2013-01-10 19:02:56 +00001236 const ObjCAtThrowStmt &S,
1237 bool ClearInsertionPoint=true);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001238 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001239 llvm::Value *AddrWeakObj);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001240 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001241 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001242 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001243 llvm::Value *src, llvm::Value *dest,
1244 bool threadlocal = false);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00001245 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001246 llvm::Value *src, llvm::Value *dest,
1247 llvm::Value *ivarOffset);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001248 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1249 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001250 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1251 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001252 llvm::Value *size);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001253
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001254 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1255 QualType ObjectTy,
1256 llvm::Value *BaseValue,
1257 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001258 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001259 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001260 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001261 const ObjCIvarDecl *Ivar);
Fariborz Jahanian6f40e222011-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 Blaikieb219cfc2011-09-23 05:06:16 +00001266 llvm_unreachable("CGObjCMac::GetClassGlobal");
Fariborz Jahanian6f40e222011-05-17 22:21:16 +00001267 }
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001268};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001269
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001270class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001271private:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001272 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001273 llvm::GlobalVariable* ObjCEmptyCacheVar;
1274 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001275
Daniel Dunbar11394522009-04-18 08:51:00 +00001276 /// SuperClassReferences - uniqued super class references.
1277 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001278
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001279 /// MetaClassReferences - uniqued meta class references.
1280 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbare588b992009-03-01 04:46:24 +00001281
1282 /// EHTypeReferences - uniqued class ehtype references.
1283 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001284
John McCall944c8432011-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 Dunbar6bff2512009-08-03 17:06:42 +00001288
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00001289 /// DefinedMetaClasses - List of defined meta-classes.
1290 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1291
John McCall944c8432011-05-14 03:10:52 +00001292 /// isVTableDispatchedSelector - Returns true if SEL is a
1293 /// vtable-based selector.
1294 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001295
Fariborz Jahanianaa23b572009-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 Dunbar8158a2f2009-04-08 04:21:03 +00001299
Daniel Dunbar463b8762009-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 Wendlingbb028552012-02-07 09:25:09 +00001302 void AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
Daniel Dunbar463b8762009-05-15 21:48:48 +00001303 const char *SymbolName,
1304 const char *SectionName);
1305
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001306 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1307 unsigned InstanceStart,
1308 unsigned InstanceSize,
1309 const ObjCImplementationDecl *ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001310 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001311 llvm::Constant *IsAGV,
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001312 llvm::Constant *SuperClassGV,
Fariborz Jahaniancf555162009-01-31 00:59:10 +00001313 llvm::Constant *ClassRoGV,
1314 bool HiddenVisibility);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001315
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001316 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001317
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00001318 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001319
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001320 /// EmitMethodList - Emit the method list for the given
1321 /// implementation. The return value has type MethodListnfABITy.
Chris Lattner5f9e2722011-07-23 10:55:15 +00001322 llvm::Constant *EmitMethodList(Twine Name,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001323 const char *Section,
Bill Wendlingbb028552012-02-07 09:25:09 +00001324 ArrayRef<llvm::Constant*> Methods);
Fariborz Jahanian98abf4b2009-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 Dunbar6bff2512009-08-03 17:06:42 +00001331
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001332 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00001333 const ObjCIvarDecl *Ivar,
Eli Friedmane5b46662012-11-06 22:15:52 +00001334 unsigned long int offset);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001335
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00001340
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00001346
Fariborz Jahanianda320092009-01-29 19:24:30 +00001347 /// EmitProtocolList - Generate the list of referenced
1348 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +00001349 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanianda320092009-01-29 19:24:30 +00001350 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian46551122009-02-04 00:22:57 +00001351 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001352
John McCall944c8432011-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 Jahanian6f40e222011-05-17 22:21:16 +00001362
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00001363 /// GetClassGlobal - Return the global variable for the Objective-C
1364 /// class of the given name.
Fariborz Jahanian0f902942009-04-14 18:41:56 +00001365 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Fariborz Jahanian6f40e222011-05-17 22:21:16 +00001366
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001367 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar11394522009-04-18 08:51:00 +00001368 /// for the given class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001369 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00001370 const ObjCInterfaceDecl *ID);
John McCallf85e1932011-06-15 23:02:42 +00001371
1372 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
1373 IdentifierInfo *II);
1374
1375 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001376
Daniel Dunbar11394522009-04-18 08:51:00 +00001377 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1378 /// for the given super class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001379 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1380 const ObjCInterfaceDecl *ID);
1381
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001382 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1383 /// meta-data
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001384 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001385 const ObjCInterfaceDecl *ID);
1386
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001387 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1388 /// the given ivar.
1389 ///
Daniel Dunbar5e88bea2009-04-19 00:31:15 +00001390 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001391 const ObjCInterfaceDecl *ID,
1392 const ObjCIvarDecl *Ivar);
1393
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00001394 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1395 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001396 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1397 bool lval=false);
Daniel Dunbare588b992009-03-01 04:46:24 +00001398
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001399 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbare588b992009-03-01 04:46:24 +00001400 /// interface. The return value has type EHTypePtrTy.
John McCall5a180392010-07-24 00:37:23 +00001401 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001402 bool ForDefinition);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001403
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001404 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001405 return "OBJC_METACLASS_$_";
1406 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001407
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001408 const char *getClassSymbolPrefix() const {
1409 return "OBJC_CLASS_$_";
1410 }
1411
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00001412 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001413 uint32_t &InstanceStart,
1414 uint32_t &InstanceSize);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001415
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001416 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001417 Selector GetNullarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001418 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1419 return CGM.getContext().Selectors.getSelector(0, &II);
1420 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001421
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001422 Selector GetUnarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001423 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1424 return CGM.getContext().Selectors.getSelector(1, &II);
1425 }
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001426
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001427 /// ImplementationIsNonLazy - Check whether the given category or
1428 /// class implementation is "non-lazy".
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00001429 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001430
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001431public:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001432 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001433 // FIXME. All stubs for now!
1434 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001435
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001436 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001437 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001438 QualType ResultType,
1439 Selector Sel,
1440 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001441 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001442 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001443 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001444
1445 virtual CodeGen::RValue
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001446 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001447 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001448 QualType ResultType,
1449 Selector Sel,
1450 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001451 bool isCategoryImpl,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001452 llvm::Value *Receiver,
1453 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001454 const CallArgList &CallArgs,
1455 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001456
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001457 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001458 const ObjCInterfaceDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001459
Fariborz Jahanian03b29602010-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 Jahaniandf9ccc62009-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 Dunbar6bff2512009-08-03 17:06:42 +00001469
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00001470 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001471
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001472 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
David Chisnall29254f42012-01-31 18:59:20 +00001473
Daniel Dunbar85fdea02012-02-28 15:36:15 +00001474 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}
David Chisnall29254f42012-01-31 18:59:20 +00001475
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001476 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00001477 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001478
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001479 virtual llvm::Constant *GetEHType(QualType T);
John McCall5a180392010-07-24 00:37:23 +00001480
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001481 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001482 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001483 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001484 virtual llvm::Constant *GetPropertySetFunction() {
1485 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001486 }
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001487
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001488 virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1489 bool copy) {
1490 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
1491 }
1492
David Chisnall8fac25d2010-12-26 22:13:16 +00001493 virtual llvm::Constant *GetSetStructFunction() {
1494 return ObjCTypes.getCopyStructFn();
1495 }
1496 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001497 return ObjCTypes.getCopyStructFn();
1498 }
David Chisnalld397cfe2012-12-17 18:54:24 +00001499 virtual llvm::Constant *GetCppAtomicObjectSetFunction() {
1500 return ObjCTypes.getCppAtomicObjectFunction();
1501 }
1502 virtual llvm::Constant *GetCppAtomicObjectGetFunction() {
Fariborz Jahaniane3173022012-01-06 18:07:23 +00001503 return ObjCTypes.getCppAtomicObjectFunction();
1504 }
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001505
Chris Lattner74391b42009-03-22 21:03:39 +00001506 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001507 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbar28ed0842009-02-16 18:48:45 +00001508 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001509
John McCallf1549f62010-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 Jahanianaa23b572009-01-23 23:53:38 +00001514 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6a3c70e2013-01-10 19:02:56 +00001515 const ObjCAtThrowStmt &S,
1516 bool ClearInsertionPoint=true);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001517 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001518 llvm::Value *AddrWeakObj);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001519 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001520 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001521 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001522 llvm::Value *src, llvm::Value *dest,
1523 bool threadlocal = false);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001524 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001525 llvm::Value *src, llvm::Value *dest,
1526 llvm::Value *ivarOffset);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001527 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001528 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001529 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1530 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001531 llvm::Value *size);
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001532 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1533 QualType ObjectTy,
1534 llvm::Value *BaseValue,
1535 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001536 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001537 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001538 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001539 const ObjCIvarDecl *Ivar);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001540};
Fariborz Jahanian4e1524b2012-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 Jahanian3c267e62012-01-30 21:40:37 +00001563 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1564 const CallArgList &CallArgs,
1565 const ObjCMethodDecl *Method) {
Fariborz Jahanian4e1524b2012-01-29 20:27:13 +00001566 if (!NullBB) return result;
Fariborz Jahanian3c267e62012-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 Jahanian4e1524b2012-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 Jahanian3c267e62012-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 Jahanian4e1524b2012-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 Dunbarc17a4d32008-08-11 02:45:11 +00001631} // end anonymous namespace
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001632
1633/* *** Helper Functions *** */
1634
1635/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Andersona1cf15f2009-07-14 23:10:40 +00001636static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001637 llvm::Constant *C,
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001638 unsigned idx0,
1639 unsigned idx1) {
1640 llvm::Value *Idxs[] = {
Owen Anderson0032b272009-08-13 21:57:51 +00001641 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1642 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001643 };
Jay Foada5c04342011-07-21 14:31:17 +00001644 return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001645}
1646
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001647/// hasObjCExceptionAttribute - Return true if this class or any super
1648/// class has the __objc_exception__ attribute.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001649static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor68584ed2009-06-18 16:11:24 +00001650 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidis40b598e2009-06-30 02:34:44 +00001651 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001652 return true;
1653 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor68584ed2009-06-18 16:11:24 +00001654 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001655 return false;
1656}
1657
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001658/* *** CGObjCMac Public Interface *** */
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001659
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001660CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00001661 ObjCTypes(cgm) {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001662 ObjCABI = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001663 EmitImageInfo();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001664}
1665
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +00001666/// GetClass - Return a reference to the class for the given interface
1667/// decl.
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001668llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001669 const ObjCInterfaceDecl *ID) {
1670 return EmitClassRef(Builder, ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001671}
1672
1673/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001674llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1675 bool lval) {
1676 return EmitSelector(Builder, Sel, lval);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001677}
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001678llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001679 *Method) {
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001680 return EmitSelector(Builder, Method->getSelector());
1681}
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001682
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001683llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00001684 if (T->isObjCIdType() ||
1685 T->isObjCQualifiedIdType()) {
1686 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor01a4cf12011-08-11 20:58:55 +00001687 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00001688 }
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001689 if (T->isObjCClassType() ||
1690 T->isObjCQualifiedClassType()) {
1691 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor01a4cf12011-08-11 20:58:55 +00001692 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001693 }
1694 if (T->isObjCObjectPointerType())
1695 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1696
John McCall5a180392010-07-24 00:37:23 +00001697 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall5a180392010-07-24 00:37:23 +00001698}
1699
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001700/// Generate a constant CFString object.
Daniel Dunbar6bff2512009-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 Dunbarbbce49b2008-08-12 00:12:39 +00001708*/
1709
Fariborz Jahanian33e982b2010-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 Jahanianaa23b572009-01-23 23:53:38 +00001719llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall0d13f6f2010-01-23 02:40:42 +00001720 const StringLiteral *SL) {
David Blaikie4e4d0842012-03-11 07:00:24 +00001721 return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001722 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian4c733072010-10-19 17:19:29 +00001723 CGM.GetAddrOfConstantString(SL));
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001724}
1725
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001726enum {
1727 kCFTaggedObjectID_Integer = (1 << 1) + 1
1728};
1729
Daniel Dunbarc17a4d32008-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 Dunbar8f2926b2008-08-23 03:46:30 +00001733CodeGen::RValue
1734CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001735 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001736 QualType ResultType,
1737 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001738 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001739 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001740 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001741 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001742 const CodeGen::CallArgList &CallArgs,
1743 const ObjCMethodDecl *Method) {
Daniel Dunbare8b470d2008-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 Dunbar6bff2512009-08-03 17:06:42 +00001746 llvm::Value *ObjCSuper =
John McCall604da292011-03-04 08:00:29 +00001747 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001748 llvm::Value *ReceiverAsObject =
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001749 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001750 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001751 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001752
Daniel Dunbarf56f1912008-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 Jahanian7ce77922009-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 Stumpb3589f42009-07-30 22:28:39 +00001766 } else {
Fariborz Jahanian7ce77922009-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 Dunbar6bff2512009-08-03 17:06:42 +00001771 }
Fariborz Jahanian182f2682009-11-14 02:18:31 +00001772 }
1773 else if (isCategoryImpl)
1774 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1775 else {
Fariborz Jahanianb0069ee2009-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 Dunbarf56f1912008-08-25 08:19:24 +00001779 }
Mike Stumpf5408fe2009-05-16 07:57:57 +00001780 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1781 // ObjCTypes types.
Chris Lattner2acc6e32011-07-18 04:24:23 +00001782 llvm::Type *ClassTy =
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001783 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001784 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001785 CGF.Builder.CreateStore(Target,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001786 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall944c8432011-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 Dunbarc17a4d32008-08-11 02:45:11 +00001791}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001792
1793/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001794CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001795 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001796 QualType ResultType,
1797 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001798 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001799 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001800 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001801 const ObjCMethodDecl *Method) {
John McCall944c8432011-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 Dunbar14c80b72008-08-23 09:25:55 +00001806}
1807
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001808CodeGen::RValue
John McCall944c8432011-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 Dunbar19cd87e2008-08-30 03:02:31 +00001819 CallArgList ActualArgs;
Fariborz Jahaniand019d962009-04-24 21:07:43 +00001820 if (!IsSuper)
Benjamin Kramer578faa82011-09-27 21:06:10 +00001821 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman04c9a492011-05-02 17:57:46 +00001822 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1823 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCallf85e1932011-06-15 23:02:42 +00001824 ActualArgs.addFrom(CallArgs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001825
John McCallde5d3c72012-02-17 03:33:10 +00001826 // If we're calling a method, use the formal signature.
1827 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001828
Anders Carlsson7e70fb22010-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 McCallcba681a2011-05-14 21:12:11 +00001834 NullReturnState nullReturn;
1835
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001836 llvm::Constant *Fn = NULL;
John McCallde5d3c72012-02-17 03:33:10 +00001837 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
Fariborz Jahanian4e1524b2012-01-29 20:27:13 +00001838 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001839 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001840 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001841 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1842 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1843 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlssoneea64802011-10-31 16:27:11 +00001844 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
1845 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
1846 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001847 } else {
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001848 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001849 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001850 }
Fariborz Jahanian3c267e62012-01-30 21:40:37 +00001851
1852 bool requiresnullCheck = false;
David Blaikie4e4d0842012-03-11 07:00:24 +00001853 if (CGM.getLangOpts().ObjCAutoRefCount && Method)
Fariborz Jahanian3c267e62012-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 McCallde5d3c72012-02-17 03:33:10 +00001865 Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
1866 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs);
Fariborz Jahanian3c267e62012-01-30 21:40:37 +00001867 return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
1868 requiresnullCheck ? Method : 0);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001869}
1870
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001871static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1872 if (FQT.isObjCGCStrong())
1873 return Qualifiers::Strong;
1874
John McCallf85e1932011-06-15 23:02:42 +00001875 if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001876 return Qualifiers::Weak;
1877
Fariborz Jahanianba83c952012-02-16 00:15:02 +00001878 // check for __unsafe_unretained
1879 if (FQT.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
1880 return Qualifiers::GCNone;
1881
Fariborz Jahanian93ce50d2010-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 McCall6b5a61b2011-02-07 10:33:21 +00001891llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1892 const CGBlockInfo &blockInfo) {
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00001893
Chris Lattner8b418682012-02-07 00:39:47 +00001894 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
David Blaikie4e4d0842012-03-11 07:00:24 +00001895 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
1896 !CGM.getLangOpts().ObjCAutoRefCount)
John McCall6b5a61b2011-02-07 10:33:21 +00001897 return nullPtr;
1898
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001899 bool hasUnion = false;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001900 SkipIvars.clear();
1901 IvarsInfo.clear();
Eli Friedmane5b46662012-11-06 22:15:52 +00001902 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
1903 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001904
Fariborz Jahanian81979822010-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 Friedmane5b46662012-11-06 22:15:52 +00001907 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall6b5a61b2011-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 Villmow25a6a842012-10-08 16:25:52 +00001913 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
John McCall6b5a61b2011-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 Friedmane5b46662012-11-06 22:15:52 +00001929 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
John McCall6b5a61b2011-02-07 10:33:21 +00001930
1931 // __block variables are passed by their descriptor address.
1932 if (ci->isByRef()) {
Eli Friedmane5b46662012-11-06 22:15:52 +00001933 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanianc5904b42010-09-11 01:27:29 +00001934 continue;
John McCall6b5a61b2011-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 Jahaniane1a48982010-08-05 21:00:25 +00001940 continue;
1941 }
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001942
John McCall6b5a61b2011-02-07 10:33:21 +00001943 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
Eli Friedmane5b46662012-11-06 22:15:52 +00001944 unsigned fieldSize = CGM.getContext().getTypeSize(type);
John McCall6b5a61b2011-02-07 10:33:21 +00001945
1946 if (GCAttr == Qualifiers::Strong)
Eli Friedmane5b46662012-11-06 22:15:52 +00001947 IvarsInfo.push_back(GC_IVAR(fieldOffset,
1948 fieldSize / WordSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001949 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
Eli Friedmane5b46662012-11-06 22:15:52 +00001950 SkipIvars.push_back(GC_IVAR(fieldOffset,
1951 fieldSize / ByteSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001952 }
1953
1954 if (IvarsInfo.empty())
John McCall6b5a61b2011-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 Jahanian93ce50d2010-08-04 23:55:24 +00001961
1962 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00001963 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
David Blaikie4e4d0842012-03-11 07:00:24 +00001964 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001965 printf("\n block variable layout for block: ");
Roman Divacky31ba6132012-09-06 15:59:27 +00001966 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling13562a12012-02-07 09:06:01 +00001967 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian93ce50d2010-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 Jahanian89ecd412010-08-04 16:57:49 +00001976}
1977
Fariborz Jahanianc441cd32012-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 Jahanian3ca23d72012-11-14 17:15:51 +00001981Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
1982 bool ByrefLayout) {
Fariborz Jahanian44fcff92012-11-02 22:51:18 +00001983 if (CGM.getLangOpts().ObjCAutoRefCount)
1984 return FQT.getObjCLifetime();
1985
Fariborz Jahanianc441cd32012-11-04 18:19:40 +00001986 // MRR.
Fariborz Jahanian44fcff92012-11-02 22:51:18 +00001987 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00001988 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fariborz Jahanian44fcff92012-11-02 22:51:18 +00001989
1990 return Qualifiers::OCL_None;
1991}
1992
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00001993void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
1994 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00001995 CharUnits FieldOffset,
1996 CharUnits FieldSize) {
Fariborz Jahanianc6abe9e2012-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 Jahanian1da01d62012-11-07 20:00:32 +00002000 FieldSize));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002001 else if (LifeTime == Qualifiers::OCL_Strong)
2002 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002003 FieldSize));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002004 else if (LifeTime == Qualifiers::OCL_Weak)
2005 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002006 FieldSize));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002007 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2008 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002009 FieldSize));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002010 else
2011 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2012 FieldOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002013 FieldSize));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002014}
2015
2016void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2017 const RecordDecl *RD,
2018 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002019 CharUnits BytePos, bool &HasUnion,
2020 bool ByrefLayout) {
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002021 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002022 CharUnits MaxUnionSize = CharUnits::Zero();
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002023 const FieldDecl *MaxField = 0;
2024 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002025 CharUnits MaxFieldOffset = CharUnits::Zero();
2026 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fariborz Jahanianc6abe9e2012-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 Jahanianc6abe9e2012-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 Jahanian1da01d62012-11-07 20:00:32 +00002037 CharUnits FieldOffset =
2038 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fariborz Jahanianc6abe9e2012-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 Jahanian1da01d62012-11-07 20:00:32 +00002083 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanianc6abe9e2012-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 Jahanian1da01d62012-11-07 20:00:32 +00002093 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002094 if (IsUnion) {
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002095 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanianc6abe9e2012-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 Jahanian3ca23d72012-11-14 17:15:51 +00002103 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanianc6abe9e2012-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 Jahanian1da01d62012-11-07 20:00:32 +00002114 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedmane5b46662012-11-06 22:15:52 +00002115 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002116 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002117 Size += LastBitfieldOrUnnamedOffset;
2118 UpdateRunSkipBlockVars(false,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002119 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2120 ByrefLayout),
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002121 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002122 Size);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002123 } else {
2124 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2125 // Last field was unnamed. Must update skip info.
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002126 CharUnits FieldSize
2127 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002128 UpdateRunSkipBlockVars(false,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002129 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2130 ByrefLayout),
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002131 BytePos + LastBitfieldOrUnnamedOffset,
2132 FieldSize);
2133 }
2134 }
2135
2136 if (MaxField)
2137 UpdateRunSkipBlockVars(false,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002138 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002139 BytePos + MaxFieldOffset,
2140 MaxUnionSize);
2141}
2142
2143void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002144 CharUnits BytePos,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002145 bool &HasUnion,
2146 bool ByrefLayout) {
Fariborz Jahanianc6abe9e2012-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 Jahanian3ca23d72012-11-14 17:15:51 +00002156 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002157}
2158
Fariborz Jahanianf22ae652012-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 Jahanian3ca23d72012-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 Jahanianc46b4352012-10-27 21:10:38 +00002414llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2415 const CGBlockInfo &blockInfo) {
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002416 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2417
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002418 RunSkipBlockVars.clear();
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002419 bool hasUnion = false;
2420
Fariborz Jahanianc46b4352012-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 Jahanianff685c52012-12-04 17:20:57 +00002433 if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
2434 UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
2435 blockInfo.BlockHeaderForcedGapOffset,
2436 blockInfo.BlockHeaderForcedGapSize);
Fariborz Jahanianc46b4352012-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 Jahanian1da01d62012-11-07 20:00:32 +00002448 CharUnits fieldOffset =
2449 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002450
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002451 assert(!type->isArrayType() && "array variable should not be caught");
Fariborz Jahanian3ca23d72012-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 Jahanian1da01d62012-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 Jahanian3ca23d72012-11-14 17:15:51 +00002462 UpdateRunSkipBlockVars(ci->isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002463 fieldOffset, fieldSize);
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002464 }
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002465 return getBitmapBlockLayout(false);
2466}
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002467
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002468
Fariborz Jahanian3ca23d72012-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 Jahanianc46b4352012-10-27 21:10:38 +00002480 }
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002481 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2482 return nullPtr;
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002483}
2484
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002485llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00002486 const ObjCProtocolDecl *PD) {
Daniel Dunbarc67876d2008-09-04 04:33:15 +00002487 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00002488 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc67876d2008-09-04 04:33:15 +00002489 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2490
Owen Anderson3c4972d2009-07-29 18:54:39 +00002491 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor4c86fdb2012-01-17 18:36:30 +00002492 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002493}
2494
Fariborz Jahanianda320092009-01-29 19:24:30 +00002495void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stumpf5408fe2009-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 Dunbar0c0e7a62008-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 Dunbar6bff2512009-08-03 17:06:42 +00002503 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002504 GetOrEmitProtocol(PD);
2505}
2506
Fariborz Jahanianda320092009-01-29 19:24:30 +00002507llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002508 if (DefinedProtocols.count(PD->getIdentifier()))
2509 return GetOrEmitProtocol(PD);
Douglas Gregorf968d832011-05-27 01:19:52 +00002510
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002511 return GetOrEmitProtocolRef(PD);
2512}
2513
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002514/*
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +00002523
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002524See EmitProtocolExtension().
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002525*/
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002526llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCall50651b92012-03-30 21:29:05 +00002527 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar0c0e7a62008-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 Gregor1d784b22012-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 Dunbar242d4dc2008-08-25 06:02:07 +00002537 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00002538 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002539 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2540
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002541 // Construct method lists.
2542 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2543 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilsondc8dab62011-11-30 01:57:58 +00002544 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002545 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002546 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002547 ObjCMethodDecl *MD = *i;
2548 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00002549 if (!C)
2550 return GetOrEmitProtocolRef(PD);
2551
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002552 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2553 OptInstanceMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00002554 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002555 } else {
2556 InstanceMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00002557 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002558 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002559 }
2560
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002561 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002562 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002563 ObjCMethodDecl *MD = *i;
2564 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00002565 if (!C)
2566 return GetOrEmitProtocolRef(PD);
2567
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002568 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2569 OptClassMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00002570 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002571 } else {
2572 ClassMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00002573 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002574 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002575 }
2576
Bob Wilsondc8dab62011-11-30 01:57:58 +00002577 MethodTypesExt.insert(MethodTypesExt.end(),
2578 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
2579
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002580 llvm::Constant *Values[] = {
Bob Wilsondc8dab62011-11-30 01:57:58 +00002581 EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
2582 MethodTypesExt),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002583 GetClassName(PD->getIdentifier()),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002584 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardbc93372008-08-21 21:57:41 +00002585 PD->protocol_begin(),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002586 PD->protocol_end()),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002587 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002588 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002589 InstanceMethods),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002590 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002591 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002592 ClassMethods)
2593 };
Owen Anderson08e25242009-07-27 22:29:56 +00002594 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002595 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002596
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002597 if (Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002598 // Already created, fix the linkage and update the initializer.
2599 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002600 Entry->setInitializer(Init);
2601 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002602 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00002603 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002604 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002605 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002606 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002607 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002608 // FIXME: Is this necessary? Why only for protocol?
2609 Entry->setAlignment(4);
John McCall50651b92012-03-30 21:29:05 +00002610
2611 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002612 }
Chris Lattnerad64e022009-07-17 23:57:13 +00002613 CGM.AddUsedGlobal(Entry);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002614
2615 return Entry;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002616}
2617
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002618llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002619 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2620
2621 if (!Entry) {
Daniel Dunbar0c0e7a62008-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 Dunbar6bff2512009-08-03 17:06:42 +00002625 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00002626 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002627 llvm::GlobalValue::ExternalLinkage,
2628 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002629 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002630 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002631 // FIXME: Is this necessary? Why only for protocol?
2632 Entry->setAlignment(4);
2633 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002634
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002635 return Entry;
2636}
2637
2638/*
2639 struct _objc_protocol_extension {
Daniel Dunbar6bff2512009-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 Wilsondc8dab62011-11-30 01:57:58 +00002644 const char ** extendedMethodTypes;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002645 };
2646*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002647llvm::Constant *
2648CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingbb028552012-02-07 09:25:09 +00002649 ArrayRef<llvm::Constant*> OptInstanceMethods,
2650 ArrayRef<llvm::Constant*> OptClassMethods,
2651 ArrayRef<llvm::Constant*> MethodTypesExt) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002652 uint64_t Size =
Micah Villmow25a6a842012-10-08 16:25:52 +00002653 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002654 llvm::Constant *Values[] = {
2655 llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002656 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002657 + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002658 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002659 OptInstanceMethods),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002660 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002661 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002662 OptClassMethods),
2663 EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
Bob Wilsondc8dab62011-11-30 01:57:58 +00002664 ObjCTypes),
2665 EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
2666 MethodTypesExt, ObjCTypes)
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002667 };
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002668
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002669 // Return null if no extension bits are used.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002670 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Bob Wilsondc8dab62011-11-30 01:57:58 +00002671 Values[3]->isNullValue() && Values[4]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002672 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002673
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002674 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00002675 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002676
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002677 // No special section, but goes in llvm.used
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002678 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002679 Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002680 0, 0, true);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002681}
2682
2683/*
2684 struct objc_protocol_list {
Bill Wendling3964e622012-02-09 22:16:49 +00002685 struct objc_protocol_list *next;
2686 long count;
2687 Protocol *list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002688 };
2689*/
Daniel Dunbardbc93372008-08-21 21:57:41 +00002690llvm::Constant *
Chris Lattner5f9e2722011-07-23 10:55:15 +00002691CGObjCMac::EmitProtocolList(Twine Name,
Daniel Dunbardbc93372008-08-21 21:57:41 +00002692 ObjCProtocolDecl::protocol_iterator begin,
2693 ObjCProtocolDecl::protocol_iterator end) {
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00002694 SmallVector<llvm::Constant *, 16> ProtocolRefs;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002695
Daniel Dunbardbc93372008-08-21 21:57:41 +00002696 for (; begin != end; ++begin)
2697 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002698
2699 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002700 if (ProtocolRefs.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002701 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002702
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002703 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002704 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002705
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002706 llvm::Constant *Values[3];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002707 // This field is only used by the runtime.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002708 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002709 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar6bff2512009-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 Dunbar6efc0c52008-08-13 03:21:16 +00002714 ProtocolRefs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002715
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002716 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002717 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002718 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002719 4, false);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002720 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002721}
2722
Bill Wendlingbb028552012-02-07 09:25:09 +00002723void CGObjCCommonMac::
2724PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00002725 SmallVectorImpl<llvm::Constant *> &Properties,
Bill Wendlingbb028552012-02-07 09:25:09 +00002726 const Decl *Container,
2727 const ObjCProtocolDecl *PROTO,
2728 const ObjCCommonTypesHelper &ObjCTypes) {
Fariborz Jahanian191dcd72009-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 Blaikie581deb32012-06-06 20:45:41 +00002734 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002735 if (!PropertySet.insert(PD->getIdentifier()))
2736 continue;
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002737 llvm::Constant *Prop[] = {
2738 GetPropertyName(PD->getIdentifier()),
2739 GetPropertyTypeString(PD, Container)
2740 };
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002741 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
2742 }
2743}
2744
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002745/*
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002746 struct _objc_property {
Bill Wendling3964e622012-02-09 22:16:49 +00002747 const char * const name;
2748 const char * const attributes;
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002749 };
2750
2751 struct _objc_property_list {
Bill Wendling3964e622012-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 Dunbarc8ef5512008-08-23 00:19:03 +00002755 };
2756*/
Chris Lattner5f9e2722011-07-23 10:55:15 +00002757llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002758 const Decl *Container,
2759 const ObjCContainerDecl *OCD,
2760 const ObjCCommonTypesHelper &ObjCTypes) {
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00002761 SmallVector<llvm::Constant *, 16> Properties;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002762 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002763 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2764 E = OCD->prop_end(); I != E; ++I) {
David Blaikie581deb32012-06-06 20:45:41 +00002765 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002766 PropertySet.insert(PD->getIdentifier());
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002767 llvm::Constant *Prop[] = {
2768 GetPropertyName(PD->getIdentifier()),
2769 GetPropertyTypeString(PD, Container)
2770 };
Owen Anderson08e25242009-07-27 22:29:56 +00002771 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002772 Prop));
2773 }
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00002774 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek53b94412010-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 Jahanian6afbdf52010-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 Dunbarc8ef5512008-08-23 00:19:03 +00002787
2788 // Return null for empty list.
2789 if (Properties.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002790 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002791
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002792 unsigned PropertySize =
Micah Villmow25a6a842012-10-08 16:25:52 +00002793 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002794 llvm::Constant *Values[3];
Owen Anderson4a28d5d2009-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 Dunbar6bff2512009-08-03 17:06:42 +00002797 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002798 Properties.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002799 Values[2] = llvm::ConstantArray::get(AT, Properties);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002800 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002801
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002802 llvm::GlobalVariable *GV =
2803 CreateMetadataVar(Name, Init,
2804 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002805 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002806 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002807 true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002808 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002809}
2810
Bill Wendlingbb028552012-02-07 09:25:09 +00002811llvm::Constant *
2812CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
2813 ArrayRef<llvm::Constant*> MethodTypes,
2814 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilsondc8dab62011-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 Dunbarc8ef5512008-08-23 00:19:03 +00002831/*
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002832 struct objc_method_description_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002833 int count;
2834 struct objc_method_description list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002835 };
2836*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002837llvm::Constant *
2838CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002839 llvm::Constant *Desc[] = {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002840 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002841 ObjCTypes.SelectorPtrTy),
2842 GetMethodVarType(MD)
2843 };
Douglas Gregorf968d832011-05-27 01:19:52 +00002844 if (!Desc[1])
2845 return 0;
2846
Owen Anderson08e25242009-07-27 22:29:56 +00002847 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002848 Desc);
2849}
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002850
Bill Wendlingbb028552012-02-07 09:25:09 +00002851llvm::Constant *
2852CGObjCMac::EmitMethodDescList(Twine Name, const char *Section,
2853 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002854 // Return null for empty list.
2855 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002856 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002857
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002858 llvm::Constant *Values[2];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002859 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002860 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002861 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002862 Values[1] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002863 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002864
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002865 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002866 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002867 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002868}
2869
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002870/*
2871 struct _objc_category {
Daniel Dunbar6bff2512009-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 Dunbar86e253a2008-08-22 20:34:54 +00002879 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002880*/
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00002881void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmow25a6a842012-10-08 16:25:52 +00002882 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002883
Mike Stumpf5408fe2009-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 Dunbar86e253a2008-08-22 20:34:54 +00002888 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002889 const ObjCCategoryDecl *Category =
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002890 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002891
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002892 SmallString<256> ExtName;
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002893 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2894 << OCD->getName();
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002895
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00002896 SmallVector<llvm::Constant *, 16> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002897 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002898 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002899 // Instance methods should always be defined.
2900 InstanceMethods.push_back(GetMethodConstant(*i));
2901 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002902 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002903 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002904 // Class methods should always be defined.
2905 ClassMethods.push_back(GetMethodConstant(*i));
2906 }
2907
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002908 llvm::Constant *Values[7];
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002909 Values[0] = GetClassName(OCD->getIdentifier());
2910 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahanian679cd7f2009-04-29 20:40:05 +00002911 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002912 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002913 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002914 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002915 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002916 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002917 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002918 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002919 ClassMethods);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002920 if (Category) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002921 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002922 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002923 Category->protocol_begin(),
2924 Category->protocol_end());
2925 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002926 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002927 }
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002928 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002929
2930 // If there is no category @interface then there can be no properties.
2931 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002932 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002933 OCD, Category, ObjCTypes);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002934 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002935 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002936 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002937
Owen Anderson08e25242009-07-27 22:29:56 +00002938 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002939 Values);
2940
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002941 llvm::GlobalVariable *GV =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002942 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002943 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002944 4, true);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002945 DefinedCategories.push_back(GV);
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00002946 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00002947 // method definition entries must be clear for next implementation.
2948 MethodDefinitions.clear();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002949}
2950
John McCall621915c2012-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 McCallb03527a2012-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 Dunbar27f9d772008-08-21 04:36:09 +00002982};
2983
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002984/*
2985 struct _objc_class {
Daniel Dunbar6bff2512009-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 Dunbar27f9d772008-08-21 04:36:09 +00002999 };
3000
3001 See EmitClassExtension();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003002*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003003void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003004 DefinedSymbols.insert(ID->getIdentifier());
3005
Chris Lattner8ec03f52008-11-24 03:54:41 +00003006 std::string ClassName = ID->getNameAsString();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003007 // FIXME: Gross
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003008 ObjCInterfaceDecl *Interface =
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003009 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003010 llvm::Constant *Protocols =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003011 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00003012 Interface->all_referenced_protocol_begin(),
3013 Interface->all_referenced_protocol_end());
John McCall621915c2012-10-17 04:53:23 +00003014 unsigned Flags = FragileABI_Class_Factory;
John McCallb03527a2012-10-17 04:53:31 +00003015 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCall621915c2012-10-17 04:53:23 +00003016 Flags |= FragileABI_Class_HasCXXStructors;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003017 unsigned Size =
Ken Dyck5f022d82011-02-09 01:59:34 +00003018 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003019
3020 // FIXME: Set CXX-structors flag.
John McCall1fb0caa2010-10-22 21:05:15 +00003021 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCall621915c2012-10-17 04:53:23 +00003022 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003023
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00003024 SmallVector<llvm::Constant *, 16> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003025 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00003026 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003027 // Instance methods should always be defined.
3028 InstanceMethods.push_back(GetMethodConstant(*i));
3029 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003030 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00003031 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003032 // Class methods should always be defined.
3033 ClassMethods.push_back(GetMethodConstant(*i));
3034 }
3035
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003036 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00003037 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie581deb32012-06-06 20:45:41 +00003038 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbarc45ef602008-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 Lattnerc5cbb902011-06-20 04:01:35 +00003052 llvm::Constant *Values[12];
Daniel Dunbar5384b092009-05-03 08:56:52 +00003053 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003054 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003055 // Record a reference to the super class.
3056 LazySymbols.insert(Super->getIdentifier());
3057
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003058 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003059 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003060 ObjCTypes.ClassPtrTy);
3061 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00003062 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003063 }
3064 Values[ 2] = GetClassName(ID->getIdentifier());
3065 // Version is always 0.
Owen Anderson4a28d5d2009-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 Jahanian46b86c62009-01-28 19:12:34 +00003069 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003070 Values[ 7] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003071 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003072 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003073 InstanceMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003074 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00003075 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003076 Values[ 9] = Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003077 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003078 Values[11] = EmitClassExtension(ID);
Owen Anderson08e25242009-07-27 22:29:56 +00003079 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003080 Values);
Fariborz Jahanianb0069ee2009-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 Dunbar27f9d772008-08-21 04:36:09 +00003097 DefinedClasses.push_back(GV);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00003098 // method definition entries must be clear for next implementation.
3099 MethodDefinitions.clear();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003100}
3101
3102llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3103 llvm::Constant *Protocols,
Bill Wendlingbb028552012-02-07 09:25:09 +00003104 ArrayRef<llvm::Constant*> Methods) {
John McCall621915c2012-10-17 04:53:23 +00003105 unsigned Flags = FragileABI_Class_Meta;
Micah Villmow25a6a842012-10-08 16:25:52 +00003106 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003107
John McCall1fb0caa2010-10-22 21:05:15 +00003108 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCall621915c2012-10-17 04:53:23 +00003109 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003110
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003111 llvm::Constant *Values[12];
Daniel Dunbar27f9d772008-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 Dunbar6bff2512009-08-03 17:06:42 +00003116 Values[ 0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003117 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003118 ObjCTypes.ClassPtrTy);
Daniel Dunbar86e253a2008-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 Dunbar27f9d772008-08-21 04:36:09 +00003122 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003123 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003124 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003125 ObjCTypes.ClassPtrTy);
3126 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00003127 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003128 }
3129 Values[ 2] = GetClassName(ID->getIdentifier());
3130 // Version is always 0.
Owen Anderson4a28d5d2009-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 Jahanian46b86c62009-01-28 19:12:34 +00003134 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003135 Values[ 7] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00003136 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003137 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003138 Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003139 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00003140 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003141 Values[ 9] = Protocols;
3142 // ivar_layout for metaclass is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00003143 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003144 // The class extension is always unused for metaclasses.
Owen Andersonc9c88b42009-07-31 20:28:54 +00003145 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00003146 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003147 Values);
3148
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003149 std::string Name("\01L_OBJC_METACLASS_");
Benjamin Kramer94be8ea2012-07-31 11:45:39 +00003150 Name += ID->getName();
Daniel Dunbarf56f1912008-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 Anderson1c431b32009-07-08 19:05:04 +00003160 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003161 llvm::GlobalValue::InternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00003162 Init, Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003163 }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003164 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbar58a29122009-03-09 22:18:41 +00003165 GV->setAlignment(4);
Chris Lattnerad64e022009-07-17 23:57:13 +00003166 CGM.AddUsedGlobal(GV);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003167
3168 return GV;
3169}
3170
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003171llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00003172 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003173
Mike Stumpf5408fe2009-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 Dunbarf56f1912008-08-25 08:19:24 +00003178
3179 // Check for an existing forward reference.
Fariborz Jahanianb0d27942009-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 Dunbar6bff2512009-08-03 17:06:42 +00003182 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
3183 true)) {
Daniel Dunbarf56f1912008-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 Anderson1c431b32009-07-08 19:05:04 +00003190 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003191 llvm::GlobalValue::ExternalLinkage,
3192 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00003193 Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003194 }
3195}
3196
Fariborz Jahanianb0069ee2009-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 Dunbar27f9d772008-08-21 04:36:09 +00003213/*
3214 struct objc_class_ext {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003215 uint32_t size;
3216 const char *weak_ivar_layout;
3217 struct _objc_property_list *properties;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003218 };
3219*/
3220llvm::Constant *
3221CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003222 uint64_t Size =
Micah Villmow25a6a842012-10-08 16:25:52 +00003223 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003224
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003225 llvm::Constant *Values[3];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003226 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanianc71303d2009-04-22 23:00:43 +00003227 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003228 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00003229 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003230
3231 // Return null if no extension bits are used.
3232 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00003233 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003234
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003235 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00003236 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003237 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003238 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003239 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003240}
3241
3242/*
3243 struct objc_ivar {
Bill Wendling795b1002012-02-22 09:30:11 +00003244 char *ivar_name;
3245 char *ivar_type;
3246 int ivar_offset;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003247 };
3248
3249 struct objc_ivar_list {
Bill Wendling795b1002012-02-22 09:30:11 +00003250 int ivar_count;
3251 struct objc_ivar list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003252 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003253*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003254llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00003255 bool ForClass) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003256 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar27f9d772008-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 Andersonc9c88b42009-07-31 20:28:54 +00003264 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003265
Jordy Rosedb8264e2011-07-22 02:08:32 +00003266 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003267
Jordy Rosedb8264e2011-07-22 02:08:32 +00003268 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00003269 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00003270 // Ignore unnamed bit-fields.
3271 if (!IVD->getDeclName())
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003272 continue;
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003273 llvm::Constant *Ivar[] = {
3274 GetMethodVarName(IVD->getIdentifier()),
3275 GetMethodVarType(IVD),
3276 llvm::ConstantInt::get(ObjCTypes.IntTy,
Eli Friedmane5b46662012-11-06 22:15:52 +00003277 ComputeIvarBaseOffset(CGM, OID, IVD))
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003278 };
Owen Anderson08e25242009-07-27 22:29:56 +00003279 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003280 }
3281
3282 // Return null for empty list.
3283 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00003284 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003285
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003286 llvm::Constant *Values[2];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003287 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00003288 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003289 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00003290 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003291 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003292
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003293 llvm::GlobalVariable *GV;
3294 if (ForClass)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003295 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003296 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00003297 4, true);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003298 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003299 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003300 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003301 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00003302 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003303}
3304
3305/*
3306 struct objc_method {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003307 SEL method_name;
3308 char *method_types;
3309 void *method;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003310 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003311
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003312 struct objc_method_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003313 struct objc_method_list *obsolete;
3314 int count;
3315 struct objc_method methods_list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003316 };
3317*/
Daniel Dunbarc45ef602008-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 Dunbarae226fa2008-08-27 02:31:56 +00003322llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00003323 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003324 if (!Fn)
3325 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003326
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003327 llvm::Constant *Method[] = {
Owen Anderson3c4972d2009-07-29 18:54:39 +00003328 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003329 ObjCTypes.SelectorPtrTy),
3330 GetMethodVarType(MD),
3331 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
3332 };
Owen Anderson08e25242009-07-27 22:29:56 +00003333 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003334}
3335
Chris Lattner5f9e2722011-07-23 10:55:15 +00003336llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003337 const char *Section,
Bill Wendlingbb028552012-02-07 09:25:09 +00003338 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003339 // Return null for empty list.
3340 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00003341 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003342
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003343 llvm::Constant *Values[3];
Owen Andersonc9c88b42009-07-31 20:28:54 +00003344 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003345 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00003346 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003347 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00003348 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003349 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003350
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003351 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003352 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003353}
3354
Fariborz Jahanian493dab72009-01-26 21:38:32 +00003355llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003356 const ObjCContainerDecl *CD) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00003357 SmallString<256> Name;
Fariborz Jahanian679a5022009-01-10 21:06:09 +00003358 GetNameForMethod(OMD, CD, Name);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003359
Daniel Dunbar541b63b2009-02-02 23:23:47 +00003360 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2acc6e32011-07-18 04:24:23 +00003361 llvm::FunctionType *MethodTy =
John McCallde5d3c72012-02-17 03:33:10 +00003362 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003363 llvm::Function *Method =
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00003364 llvm::Function::Create(MethodTy,
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003365 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00003366 Name.str(),
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003367 &CGM.getModule());
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003368 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003369
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003370 return Method;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00003371}
3372
Daniel Dunbarfd65d372009-03-09 20:09:19 +00003373llvm::GlobalVariable *
Chris Lattner5f9e2722011-07-23 10:55:15 +00003374CGObjCCommonMac::CreateMetadataVar(Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +00003375 llvm::Constant *Init,
3376 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +00003377 unsigned Align,
3378 bool AddToUsed) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00003379 llvm::Type *Ty = Init->getType();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003380 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00003381 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerad64e022009-07-17 23:57:13 +00003382 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00003383 if (Section)
3384 GV->setSection(Section);
Daniel Dunbar35bd7632009-03-09 20:50:13 +00003385 if (Align)
3386 GV->setAlignment(Align);
3387 if (AddToUsed)
Chris Lattnerad64e022009-07-17 23:57:13 +00003388 CGM.AddUsedGlobal(GV);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00003389 return GV;
3390}
3391
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003392llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003393 // Abuse this interface function as a place to finalize.
3394 FinishModule();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00003395 return NULL;
3396}
3397
Chris Lattner74391b42009-03-22 21:03:39 +00003398llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00003399 return ObjCTypes.getGetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00003400}
3401
Chris Lattner74391b42009-03-22 21:03:39 +00003402llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00003403 return ObjCTypes.getSetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00003404}
3405
Ted Kremenekebcb57a2012-03-06 20:05:56 +00003406llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3407 bool copy) {
3408 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3409}
3410
David Chisnall8fac25d2010-12-26 22:13:16 +00003411llvm::Constant *CGObjCMac::GetGetStructFunction() {
3412 return ObjCTypes.getCopyStructFn();
3413}
3414llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00003415 return ObjCTypes.getCopyStructFn();
3416}
3417
David Chisnalld397cfe2012-12-17 18:54:24 +00003418llvm::Constant *CGObjCMac::GetCppAtomicObjectGetFunction() {
3419 return ObjCTypes.getCppAtomicObjectFunction();
3420}
3421llvm::Constant *CGObjCMac::GetCppAtomicObjectSetFunction() {
Fariborz Jahaniane3173022012-01-06 18:07:23 +00003422 return ObjCTypes.getCppAtomicObjectFunction();
3423}
3424
Chris Lattner74391b42009-03-22 21:03:39 +00003425llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00003426 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson2abd89c2008-08-31 04:05:03 +00003427}
3428
John McCallf1549f62010-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 McCallcc505292010-07-21 06:59:36 +00003438namespace {
John McCall1f0fca52010-07-21 07:22:38 +00003439 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCallcc505292010-07-21 06:59:36 +00003440 const Stmt &S;
John McCall0b251722010-08-04 05:59:32 +00003441 llvm::Value *SyncArgSlot;
John McCallcc505292010-07-21 06:59:36 +00003442 llvm::Value *CallTryExitVar;
3443 llvm::Value *ExceptionData;
3444 ObjCTypesHelper &ObjCTypes;
3445 PerformFragileFinally(const Stmt *S,
John McCall0b251722010-08-04 05:59:32 +00003446 llvm::Value *SyncArgSlot,
John McCallcc505292010-07-21 06:59:36 +00003447 llvm::Value *CallTryExitVar,
3448 llvm::Value *ExceptionData,
3449 ObjCTypesHelper *ObjCTypes)
John McCall0b251722010-08-04 05:59:32 +00003450 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCallcc505292010-07-21 06:59:36 +00003451 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
3452
John McCallad346f42011-07-12 20:27:29 +00003453 void Emit(CodeGenFunction &CGF, Flags flags) {
John McCallcc505292010-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 McCalld96a8e72010-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 McCallcc505292010-07-21 06:59:36 +00003477 CGF.EmitStmt(FinallyStmt->getFinallyBody());
3478
John McCalld96a8e72010-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 McCallcc505292010-07-21 06:59:36 +00003487 } else {
3488 // Emit objc_sync_exit(expr); as finally's sole statement for
3489 // @synchronized.
John McCall0b251722010-08-04 05:59:32 +00003490 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCallcc505292010-07-21 06:59:36 +00003491 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
3492 ->setDoesNotThrow();
3493 }
3494 }
3495 };
John McCall87bb5822010-07-31 23:20:56 +00003496
3497 class FragileHazards {
3498 CodeGenFunction &CGF;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003499 SmallVector<llvm::Value*, 20> Locals;
John McCall87bb5822010-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 McCall0b251722010-08-04 05:59:32 +00003512
John McCall87bb5822010-07-31 23:20:56 +00003513 void emitWriteHazard();
John McCall0b251722010-08-04 05:59:32 +00003514 void emitHazardsInNewBlocks();
John McCall87bb5822010-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 Foad4c7d9f12011-07-15 08:37:34 +00003569 CGF.Builder.CreateCall(WriteHazard, Locals)->setDoesNotThrow();
John McCall87bb5822010-07-31 23:20:56 +00003570}
3571
John McCall87bb5822010-07-31 23:20:56 +00003572void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
3573 assert(!Locals.empty());
Jay Foad4c7d9f12011-07-15 08:37:34 +00003574 Builder.CreateCall(ReadHazard, Locals)->setDoesNotThrow();
John McCall87bb5822010-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 McCall0b251722010-08-04 05:59:32 +00003579void FragileHazards::emitHazardsInNewBlocks() {
John McCall87bb5822010-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 McCall0b251722010-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 McCall87bb5822010-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 McCall87bb5822010-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 Lattner5f9e2722011-07-23 10:55:15 +00003637 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall0774cb82011-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 McCallcc505292010-07-21 06:59:36 +00003641}
3642
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003643/*
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003644
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003645 Objective-C setjmp-longjmp (sjlj) Exception Handling
3646 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003647
John McCallf1549f62010-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 Dunbar6bff2512009-08-03 17:06:42 +00003680 The basic framework for a @try-catch-finally is as follows:
3681 {
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003682 objc_exception_data d;
3683 id _rethrow = null;
Anders Carlsson190d00e2009-02-07 21:26:04 +00003684 bool _call_try_exit = true;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003685
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003686 objc_exception_try_enter(&d);
3687 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003688 ... try body ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003689 } else {
Daniel Dunbar6bff2512009-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 Dunbar18ccc772008-09-28 01:03:14 +00003706 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00003707 ... jump-through-finally to finally_end ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003708
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003709 finally:
Anders Carlsson190d00e2009-02-07 21:26:04 +00003710 if (_call_try_exit)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003711 objc_exception_try_exit(&d);
Anders Carlsson190d00e2009-02-07 21:26:04 +00003712
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003713 ... finally block ....
Daniel Dunbar898d5082008-09-30 01:06:03 +00003714 ... dispatch to finally destination ...
3715
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003716 finally_rethrow:
Daniel Dunbar898d5082008-09-30 01:06:03 +00003717 objc_exception_throw(_rethrow);
3718
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003719 finally_end:
3720 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003721
Daniel Dunbar6bff2512009-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 Dunbar18ccc772008-09-28 01:03:14 +00003726
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003727 We specialize this framework for a few particular circumstances:
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003728
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003729 - If there are no catch blocks, then we avoid emitting the second
3730 exception handling context.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003731
Daniel Dunbar6bff2512009-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 Dunbar18ccc772008-09-28 01:03:14 +00003734
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003735 - FIXME: If there is no @finally block we can do a few more
3736 simplifications.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003737
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003738 Rethrows and Jumps-Through-Finally
3739 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003740
John McCallf1549f62010-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 Dunbar18ccc772008-09-28 01:03:14 +00003743
John McCallf1549f62010-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 Dunbar898d5082008-09-30 01:06:03 +00003748
John McCallf1549f62010-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 Dunbar18ccc772008-09-28 01:03:14 +00003753*/
3754
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00003755void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
3756 const Stmt &S) {
3757 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallf1549f62010-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 Dunbar6bff2512009-08-03 17:06:42 +00003768
Daniel Dunbar1c566672009-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 McCall0b251722010-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 Dunbar1c566672009-02-24 01:43:46 +00003775 if (!isTry) {
John McCall0b251722010-08-04 05:59:32 +00003776 llvm::Value *SyncArg =
Daniel Dunbar1c566672009-02-24 01:43:46 +00003777 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
3778 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallf1549f62010-07-06 01:34:17 +00003779 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
3780 ->setDoesNotThrow();
John McCall0b251722010-08-04 05:59:32 +00003781
3782 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
3783 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar1c566672009-02-24 01:43:46 +00003784 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00003785
John McCall0b251722010-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 McCall87bb5822010-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 McCallf1549f62010-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 McCall0b251722010-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 McCallf1549f62010-07-06 01:34:17 +00003805 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlsson190d00e2009-02-07 21:26:04 +00003806 "_call_try_exit");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003807
John McCall9e2213d2010-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 McCallf1549f62010-07-06 01:34:17 +00003812 // Push a normal cleanup to leave the try scope.
John McCall1f0fca52010-07-21 07:22:38 +00003813 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall0b251722010-08-04 05:59:32 +00003814 SyncArgSlot,
John McCall1f0fca52010-07-21 07:22:38 +00003815 CallTryExitVar,
3816 ExceptionData,
3817 &ObjCTypes);
John McCallf1549f62010-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 Foad0f6ac7c2011-07-22 08:16:57 +00003829 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
John McCallf1549f62010-07-06 01:34:17 +00003830 llvm::CallInst *SetJmpResult =
3831 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3832 SetJmpResult->setDoesNotThrow();
Bill Wendling6446c3e2011-12-19 23:53:28 +00003833 SetJmpResult->setCanReturnTwice();
John McCallf1549f62010-07-06 01:34:17 +00003834
3835 // If setjmp returned 0, enter the protected block; otherwise,
3836 // branch to the handler.
Daniel Dunbar55e87422008-11-11 02:29:29 +00003837 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3838 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallf1549f62010-07-06 01:34:17 +00003839 llvm::Value *DidCatch =
John McCalld96a8e72010-08-11 00:16:14 +00003840 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3841 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson80f25672008-09-09 17:59:25 +00003842
John McCallf1549f62010-07-06 01:34:17 +00003843 // Emit the protected block.
Anders Carlsson80f25672008-09-09 17:59:25 +00003844 CGF.EmitBlock(TryBlock);
John McCall0b251722010-08-04 05:59:32 +00003845 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003846 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallf1549f62010-07-06 01:34:17 +00003847 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall0b251722010-08-04 05:59:32 +00003848
3849 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003850
John McCallf1549f62010-07-06 01:34:17 +00003851 // Emit the exception handler block.
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003852 CGF.EmitBlock(TryHandler);
Daniel Dunbar55e40722008-09-27 07:03:52 +00003853
John McCall87bb5822010-07-31 23:20:56 +00003854 // Don't optimize loads of the in-scope locals across this point.
3855 Hazards.emitWriteHazard();
3856
John McCallf1549f62010-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 McCall0b251722010-08-04 05:59:32 +00003861 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003862 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallf1549f62010-07-06 01:34:17 +00003863
3864 // Otherwise, we have to match against the caught exceptions.
3865 } else {
John McCall0b251722010-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 McCallf1549f62010-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 Gregor8f5e3dd2010-04-23 22:50:49 +00003877 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003878
John McCall0b251722010-08-04 05:59:32 +00003879 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallf1549f62010-07-06 01:34:17 +00003880
John McCall0b251722010-08-04 05:59:32 +00003881 llvm::BasicBlock *CatchBlock = 0;
3882 llvm::BasicBlock *CatchHandler = 0;
3883 if (HasFinally) {
John McCall9e2213d2010-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 McCall0b251722010-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 Carlsson80f25672008-09-09 17:59:25 +00003894
John McCall0b251722010-08-04 05:59:32 +00003895 llvm::CallInst *SetJmpResult =
3896 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3897 "setjmp.result");
3898 SetJmpResult->setDoesNotThrow();
Bill Wendling6446c3e2011-12-19 23:53:28 +00003899 SetJmpResult->setCanReturnTwice();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003900
John McCall0b251722010-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 Dunbar6bff2512009-08-03 17:06:42 +00003912
Daniel Dunbar55e40722008-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 Gregor8f5e3dd2010-04-23 22:50:49 +00003917 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3918 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson80f25672008-09-09 17:59:25 +00003919
Douglas Gregorc00d8e12010-04-26 16:46:50 +00003920 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff14108da2009-07-10 23:34:53 +00003921 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar129271a2008-09-27 07:36:24 +00003922
Anders Carlsson80f25672008-09-09 17:59:25 +00003923 // catch(...) always matches.
Daniel Dunbar55e40722008-09-27 07:03:52 +00003924 if (!CatchParam) {
3925 AllMatched = true;
3926 } else {
John McCall183700f2009-09-21 23:43:11 +00003927 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003928
John McCallf1549f62010-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 Dunbar97f61d12008-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 Friedman818e96f2009-07-11 00:57:02 +00003933 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbar55e40722008-09-27 07:03:52 +00003934 AllMatched = true;
Anders Carlsson80f25672008-09-09 17:59:25 +00003935 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003936
John McCallf1549f62010-07-06 01:34:17 +00003937 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003938 if (AllMatched) {
John McCallf1549f62010-07-06 01:34:17 +00003939 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3940
Anders Carlssondde0a942008-09-11 09:15:33 +00003941 if (CatchParam) {
John McCallb6bbcc92010-10-15 04:57:14 +00003942 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003943 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallf1549f62010-07-06 01:34:17 +00003944
3945 // These types work out because ConvertType(id) == i8*.
Steve Naroff7ba138a2009-03-03 19:52:17 +00003946 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlssondde0a942008-09-11 09:15:33 +00003947 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003948
Anders Carlssondde0a942008-09-11 09:15:33 +00003949 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003950
3951 // The scope of the catch variable ends right here.
3952 CatchVarCleanups.ForceCleanup();
3953
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003954 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson80f25672008-09-09 17:59:25 +00003955 break;
3956 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003957
Steve Naroff14108da2009-07-10 23:34:53 +00003958 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall506b57e2010-05-17 21:00:27 +00003959 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallf1549f62010-07-06 01:34:17 +00003960
3961 // FIXME: @catch (Class c) ?
John McCall506b57e2010-05-17 21:00:27 +00003962 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3963 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson80f25672008-09-09 17:59:25 +00003964
3965 // Check if the @catch block matches the exception object.
John McCall506b57e2010-05-17 21:00:27 +00003966 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003967
John McCallf1549f62010-07-06 01:34:17 +00003968 llvm::CallInst *Match =
Chris Lattner34b02a12009-04-22 02:26:14 +00003969 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3970 Class, Caught, "match");
John McCallf1549f62010-07-06 01:34:17 +00003971 Match->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003972
John McCallf1549f62010-07-06 01:34:17 +00003973 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3974 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003975
3976 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003977 MatchedBlock, NextCatchBlock);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003978
Anders Carlsson80f25672008-09-09 17:59:25 +00003979 // Emit the @catch block.
3980 CGF.EmitBlock(MatchedBlock);
John McCallf1549f62010-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 McCall0b251722010-08-04 05:59:32 +00003984 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallf1549f62010-07-06 01:34:17 +00003985
John McCallb6bbcc92010-10-15 04:57:14 +00003986 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003987 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003988
John McCallf1549f62010-07-06 01:34:17 +00003989 // Initialize the catch variable.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003990 llvm::Value *Tmp =
3991 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer578faa82011-09-27 21:06:10 +00003992 CGF.ConvertType(CatchParam->getType()));
Steve Naroff7ba138a2009-03-03 19:52:17 +00003993 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003994
Anders Carlssondde0a942008-09-11 09:15:33 +00003995 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003996
3997 // We're done with the catch variable.
3998 CatchVarCleanups.ForceCleanup();
3999
Anders Carlssonf3a79a92009-02-09 20:38:58 +00004000 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004001
Anders Carlsson80f25672008-09-09 17:59:25 +00004002 CGF.EmitBlock(NextCatchBlock);
4003 }
4004
John McCallf1549f62010-07-06 01:34:17 +00004005 CGF.ObjCEHValueStack.pop_back();
4006
John McCall0b251722010-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 McCall9e2213d2010-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 McCall0b251722010-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 Carlssonf3a79a92009-02-09 20:38:58 +00004035 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar55e40722008-09-27 07:03:52 +00004036 }
Anders Carlsson80f25672008-09-09 17:59:25 +00004037 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004038
John McCall87bb5822010-07-31 23:20:56 +00004039 // Insert read hazards as required in the new blocks.
John McCall0b251722010-08-04 05:59:32 +00004040 Hazards.emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00004041
John McCallf1549f62010-07-06 01:34:17 +00004042 // Pop the cleanup.
John McCall0b251722010-08-04 05:59:32 +00004043 CGF.Builder.restoreIP(TryFallthroughIP);
4044 if (CGF.HaveInsertPoint())
4045 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallf1549f62010-07-06 01:34:17 +00004046 CGF.PopCleanupBlock();
John McCall0b251722010-08-04 05:59:32 +00004047 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00004048
John McCallf1549f62010-07-06 01:34:17 +00004049 // Emit the rethrow block.
John McCall87bb5822010-07-31 23:20:56 +00004050 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallff8e1152010-07-23 21:56:41 +00004051 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallf1549f62010-07-06 01:34:17 +00004052 if (CGF.HaveInsertPoint()) {
John McCall9e2213d2010-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 McCall0b251722010-08-04 05:59:32 +00004057
John McCall9e2213d2010-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 McCallf1549f62010-07-06 01:34:17 +00004068 ->setDoesNotThrow();
4069 CGF.Builder.CreateUnreachable();
Fariborz Jahanianf2878e52008-11-21 19:21:53 +00004070 }
Anders Carlsson80f25672008-09-09 17:59:25 +00004071
John McCall87bb5822010-07-31 23:20:56 +00004072 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00004073}
4074
4075void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6a3c70e2013-01-10 19:02:56 +00004076 const ObjCAtThrowStmt &S,
4077 bool ClearInsertionPoint) {
Anders Carlsson2b1e3112008-09-09 16:16:55 +00004078 llvm::Value *ExceptionAsObject;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004079
Anders Carlsson2b1e3112008-09-09 16:16:55 +00004080 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall2b014d62011-10-01 10:32:24 +00004081 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004082 ExceptionAsObject =
Benjamin Kramer578faa82011-09-27 21:06:10 +00004083 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlsson2b1e3112008-09-09 16:16:55 +00004084 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004085 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar18ccc772008-09-28 01:03:14 +00004086 "Unexpected rethrow outside @catch block.");
Anders Carlsson273558f2009-02-07 21:37:21 +00004087 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlsson2b1e3112008-09-09 16:16:55 +00004088 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004089
John McCallf1549f62010-07-06 01:34:17 +00004090 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4091 ->setDoesNotReturn();
Anders Carlsson80f25672008-09-09 17:59:25 +00004092 CGF.Builder.CreateUnreachable();
Daniel Dunbara448fb22008-11-11 23:11:34 +00004093
4094 // Clear the insertion point to indicate we are in unreachable code.
Fariborz Jahanian6a3c70e2013-01-10 19:02:56 +00004095 if (ClearInsertionPoint)
4096 CGF.Builder.ClearInsertionPoint();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00004097}
4098
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00004099/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00004100/// object: objc_read_weak (id *src)
4101///
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00004102llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00004103 llvm::Value *AddrWeakObj) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00004104 llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004105 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
4106 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4107 ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00004108 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00004109 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00004110 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00004111 return read_weak;
4112}
4113
Fariborz Jahanian3e283e32008-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 Stump1eb44332009-09-09 15:08:12 +00004118 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00004119 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004120 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00004121 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00004124 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00004125 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4126 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00004127 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4128 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00004129 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00004130 src, dst, "weakassign");
4131 return;
4132}
4133
Fariborz Jahanian58626502008-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 Jahanian021a7a62010-07-20 20:30:03 +00004138 llvm::Value *src, llvm::Value *dst,
4139 bool threadlocal) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00004140 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004141 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00004142 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00004145 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00004146 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4147 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00004148 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4149 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-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 Jahanian58626502008-11-19 00:59:10 +00004156 return;
4157}
4158
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00004159/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00004160/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00004161///
4162void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00004163 llvm::Value *src, llvm::Value *dst,
4164 llvm::Value *ivarOffset) {
4165 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2acc6e32011-07-18 04:24:23 +00004166 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004167 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00004168 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00004171 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00004172 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4173 }
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00004174 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4175 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00004176 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
4177 src, dst, ivarOffset);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00004178 return;
4179}
4180
Fariborz Jahanian58626502008-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 Stump1eb44332009-09-09 15:08:12 +00004185 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00004186 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004187 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00004188 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00004191 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00004192 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4193 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00004194 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4195 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00004196 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian58626502008-11-19 00:59:10 +00004197 src, dst, "weakassign");
4198 return;
4199}
4200
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00004201void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004202 llvm::Value *DestPtr,
4203 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00004204 llvm::Value *size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00004205 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4206 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00004207 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00004208 DestPtr, SrcPtr, size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00004209 return;
4210}
4211
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00004212/// EmitObjCValueForIvar - Code Gen for ivar reference.
4213///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00004214LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4215 QualType ObjectTy,
4216 llvm::Value *BaseValue,
4217 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00004218 unsigned CVRQualifiers) {
John McCallc12c5bb2010-05-15 11:32:37 +00004219 const ObjCInterfaceDecl *ID =
4220 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00004221 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4222 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00004223}
4224
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00004225llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00004226 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00004227 const ObjCIvarDecl *Ivar) {
Eli Friedmane5b46662012-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 Jahanianf63aa3f2009-02-10 19:02:04 +00004232}
4233
Daniel Dunbarf77ac862008-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 Dunbarfce176b2010-04-25 20:39:01 +00004245 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004246 eImageInfo_GarbageCollected = (1 << 1),
4247 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00004248 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
4249
Daniel Dunbarfce176b2010-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 Wendling09822512012-04-24 11:04:57 +00004252 eImageInfo_CorrectedSynthesize = (1 << 4),
4253 eImageInfo_ImageIsSimulated = (1 << 5)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004254};
4255
Daniel Dunbarfce176b2010-04-25 20:39:01 +00004256void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004257 unsigned version = 0; // Version is unused?
Bill Wendling3973acc2012-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 Dunbarf77ac862008-08-11 21:35:06 +00004261
Bill Wendling3973acc2012-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 Dunbar6bff2512009-08-03 17:06:42 +00004265
Bill Wendling3973acc2012-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 Dunbarf77ac862008-08-11 21:35:06 +00004272
David Blaikie4e4d0842012-03-11 07:00:24 +00004273 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendling3973acc2012-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 Dunbar63c5b502009-03-09 21:49:58 +00004282
David Blaikie4e4d0842012-03-11 07:00:24 +00004283 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendling3973acc2012-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 Wendling09822512012-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 Dunbarf77ac862008-08-11 21:35:06 +00004306}
4307
Daniel Dunbar4e2d7d02008-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 Villmow25a6a842012-10-08 16:25:52 +00004319 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004320
Benjamin Kramer1d236ab2011-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 Dunbar6bff2512009-08-03 17:06:42 +00004328 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson08e25242009-07-27 22:29:56 +00004329 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004330 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00004331 4, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004332}
4333
4334llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004335 unsigned NumClasses = DefinedClasses.size();
4336 unsigned NumCategories = DefinedCategories.size();
4337
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004338 // Return null if no symbols were defined.
4339 if (!NumClasses && !NumCategories)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004340 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004341
Chris Lattnerc5cbb902011-06-20 04:01:35 +00004342 llvm::Constant *Values[5];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00004343 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004344 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00004345 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
4346 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004347
Daniel Dunbar86e253a2008-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 Lattner0b239712012-02-06 22:16:34 +00004350 SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00004351 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00004352 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00004353 ObjCTypes.Int8PtrTy);
4354 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004355 Symbols[NumClasses + i] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00004356 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00004357 ObjCTypes.Int8PtrTy);
4358
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004359 Values[4] =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004360 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner0b239712012-02-06 22:16:34 +00004361 Symbols.size()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004362 Symbols);
4363
Chris Lattnerc5cbb902011-06-20 04:01:35 +00004364 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004365
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004366 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004367 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
4368 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00004369 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00004370 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004371}
4372
John McCallf85e1932011-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 Dunbar27f9d772008-08-21 04:36:09 +00004379 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004380 llvm::Constant *Casted =
John McCallf85e1932011-06-15 23:02:42 +00004381 llvm::ConstantExpr::getBitCast(GetClassName(II),
4382 ObjCTypes.ClassPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004383 Entry =
John McCallf85e1932011-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 Dunbar27f9d772008-08-21 04:36:09 +00004387 }
John McCallf85e1932011-06-15 23:02:42 +00004388
Benjamin Kramer578faa82011-09-27 21:06:10 +00004389 return Builder.CreateLoad(Entry);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004390}
4391
John McCallf85e1932011-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 Jahanian03b29602010-06-17 19:56:20 +00004402llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
4403 bool lvalue) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004404 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004405
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004406 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004407 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00004408 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004409 ObjCTypes.SelectorPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004410 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004411 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
4412 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00004413 4, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004414 }
4415
Fariborz Jahanian03b29602010-06-17 19:56:20 +00004416 if (lvalue)
4417 return Entry;
Benjamin Kramer578faa82011-09-27 21:06:10 +00004418 return Builder.CreateLoad(Entry);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004419}
4420
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004421llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004422 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004423
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004424 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004425 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner94010692012-02-05 02:30:40 +00004426 llvm::ConstantDataArray::getString(VMContext,
4427 Ident->getNameStart()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004428 ((ObjCABI == 2) ?
4429 "__TEXT,__objc_classname,cstring_literals" :
4430 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004431 1, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004432
Owen Andersona1cf15f2009-07-14 23:10:40 +00004433 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004434}
4435
Argyrios Kyrtzidis9d50c062010-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 Kyrtzidis9d50c062010-08-09 10:54:20 +00004442 return NULL;
4443}
4444
Fariborz Jahaniand80d81b2009-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 Dunbar6bff2512009-08-03 17:06:42 +00004448 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Andersonc9c88b42009-07-31 20:28:54 +00004449 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00004450}
4451
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004452void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Eli Friedmane5b46662012-11-06 22:15:52 +00004453 unsigned int BytePos,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004454 bool ForStrongLayout,
4455 bool &HasUnion) {
4456 const RecordDecl *RD = RT->getDecl();
4457 // FIXME - Use iterator.
David Blaikie262bc182012-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 Blaikie581deb32012-06-06 20:45:41 +00004461 Fields.push_back(*i);
Chris Lattner2acc6e32011-07-18 04:24:23 +00004462 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004463 const llvm::StructLayout *RecLayout =
Micah Villmow25a6a842012-10-08 16:25:52 +00004464 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004465
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004466 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
4467 ForStrongLayout, HasUnion);
4468}
4469
Daniel Dunbar5a5a8032009-05-03 21:05:10 +00004470void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004471 const llvm::StructLayout *Layout,
4472 const RecordDecl *RD,
Bill Wendling795b1002012-02-22 09:30:11 +00004473 ArrayRef<const FieldDecl*> RecFields,
Eli Friedmane5b46662012-11-06 22:15:52 +00004474 unsigned int BytePos, bool ForStrongLayout,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004475 bool &HasUnion) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004476 bool IsUnion = (RD && RD->isUnion());
Eli Friedmane5b46662012-11-06 22:15:52 +00004477 uint64_t MaxUnionIvarSize = 0;
4478 uint64_t MaxSkippedUnionIvarSize = 0;
Jordy Rosedb8264e2011-07-22 02:08:32 +00004479 const FieldDecl *MaxField = 0;
4480 const FieldDecl *MaxSkippedField = 0;
4481 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Eli Friedmane5b46662012-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 Dunbar6bff2512009-08-03 17:06:42 +00004486
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004487 if (RecFields.empty())
4488 return;
Eli Friedmane5b46662012-11-06 22:15:52 +00004489 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
Douglas Gregorbcfd1f52011-09-02 00:18:52 +00004490 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
David Blaikie4e4d0842012-03-11 07:00:24 +00004491 if (!RD && CGM.getLangOpts().ObjCAutoRefCount) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004492 const FieldDecl *FirstField = RecFields[0];
4493 FirstFieldDelta =
4494 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
John McCallf85e1932011-06-15 23:02:42 +00004495 }
4496
Chris Lattnerf1690852009-03-31 08:48:01 +00004497 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Jordy Rosedb8264e2011-07-22 02:08:32 +00004498 const FieldDecl *Field = RecFields[i];
Eli Friedmane5b46662012-11-06 22:15:52 +00004499 uint64_t FieldOffset;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00004500 if (RD) {
Daniel Dunbarf8f8eba2010-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 Friedmane5b46662012-11-06 22:15:52 +00004504 FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00004505 } else
John McCallf85e1932011-06-15 23:02:42 +00004506 FieldOffset =
4507 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
Daniel Dunbar25d583e2009-05-03 14:17:18 +00004508
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004509 // Skip over unnamed or bitfields
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00004510 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004511 LastFieldBitfieldOrUnnamed = Field;
4512 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004513 continue;
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00004514 }
Daniel Dunbar25d583e2009-05-03 14:17:18 +00004515
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004516 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004517 QualType FQT = Field->getType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00004518 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004519 if (FQT->isUnionType())
4520 HasUnion = true;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004521
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004522 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar25d583e2009-05-03 14:17:18 +00004523 BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004524 ForStrongLayout, HasUnion);
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004525 continue;
4526 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004527
Chris Lattnerf1690852009-03-31 08:48:01 +00004528 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004529 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00004530 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00004531 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00004532 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004533 FQT = CArray->getElementType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00004534 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
4535 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00004536 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00004537 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00004538 FQT = CArray->getElementType();
4539 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004540
4541 assert(!FQT->isUnionType() &&
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004542 "layout for array of unions not supported");
Fariborz Jahanianf96bdf42011-01-03 19:23:18 +00004543 if (FQT->isRecordType() && ElCount) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004544 int OldIndex = IvarsInfo.size() - 1;
4545 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004546
Ted Kremenek6217b802009-07-29 21:53:49 +00004547 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar25d583e2009-05-03 14:17:18 +00004548 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004549 ForStrongLayout, HasUnion);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004550
Fariborz Jahanian820e0202009-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 Dunbar6bff2512009-08-03 17:06:42 +00004554 for (int FirstIndex = IvarsInfo.size() - 1,
4555 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004556 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar8b2926c2009-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 Jahanian820e0202009-03-11 00:07:04 +00004563 }
4564 continue;
4565 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004566 }
Fariborz Jahanian820e0202009-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 McCall0953e762009-09-24 19:53:00 +00004569 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00004570
Eli Friedmane5b46662012-11-06 22:15:52 +00004571 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall0953e762009-09-24 19:53:00 +00004572 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
4573 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00004574 if (IsUnion) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004575 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar487993b2009-05-03 13:32:01 +00004576 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004577 MaxUnionIvarSize = UnionIvarSize;
4578 MaxField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00004579 MaxFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004580 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00004581 } else {
Eli Friedmane5b46662012-11-06 22:15:52 +00004582 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
4583 FieldSize / WordSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004584 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004585 } else if ((ForStrongLayout &&
John McCall0953e762009-09-24 19:53:00 +00004586 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
4587 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00004588 if (IsUnion) {
Eli Friedmane5b46662012-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 Dunbar487993b2009-05-03 13:32:01 +00004592 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004593 MaxSkippedUnionIvarSize = UnionIvarSize;
4594 MaxSkippedField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00004595 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004596 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00004597 } else {
Eli Friedmane5b46662012-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 Jahanian820e0202009-03-11 00:07:04 +00004601 }
4602 }
4603 }
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004604
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004605 if (LastFieldBitfieldOrUnnamed) {
4606 if (LastFieldBitfieldOrUnnamed->isBitField()) {
4607 // Last field was a bitfield. Must update skip info.
Richard Smitha6b8b2c2011-10-10 18:28:20 +00004608 uint64_t BitFieldSize
4609 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004610 GC_IVAR skivar;
4611 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
Eli Friedmane5b46662012-11-06 22:15:52 +00004612 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
4613 + ((BitFieldSize % ByteSizeInBits) != 0);
Argyrios Kyrtzidis0dc75092010-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 Friedmane5b46662012-11-06 22:15:52 +00004618 unsigned FieldSize
4619 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004620 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
Eli Friedmane5b46662012-11-06 22:15:52 +00004621 FieldSize / ByteSizeInBits));
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004622 }
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00004623 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004624
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00004625 if (MaxField)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004626 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00004627 MaxUnionIvarSize));
4628 if (MaxSkippedField)
Daniel Dunbar900c1982009-05-03 23:31:46 +00004629 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00004630 MaxSkippedUnionIvarSize));
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00004631}
4632
Fariborz Jahanianb8fd2eb2010-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 Lattner94010692012-02-05 02:30:40 +00004638llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004639 unsigned int WordsToScan, WordsToSkip;
Chris Lattner8b418682012-02-07 00:39:47 +00004640 llvm::Type *PtrTy = CGM.Int8PtrTy;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004641
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004642 // Build the string of skip/scan nibbles
Chris Lattner5f9e2722011-07-23 10:55:15 +00004643 SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Eli Friedmane5b46662012-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 Dunbar31682fd2009-05-03 23:21:22 +00004653 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004654 unsigned int TailPrevGCObjC =
4655 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004656 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004657 // consecutive 'scanned' object pointers.
Eli Friedmane5b46662012-11-06 22:15:52 +00004658 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004659 } else {
Fariborz Jahanian9397e1d2009-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 Jahanianc8ce9c82009-03-12 22:50:49 +00004665 SKIP_SCAN SkScan;
4666 SkScan.skip = WordsToSkip;
4667 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004668 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004669
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004670 // Skip the hole.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00004671 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
4672 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004673 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004674 WordsToSkip = 0;
Eli Friedmane5b46662012-11-06 22:15:52 +00004675 WordsToScan = IvarsInfo[i].ivar_size;
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004676 }
4677 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004678 if (WordsToScan > 0) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00004679 SKIP_SCAN SkScan;
4680 SkScan.skip = WordsToSkip;
4681 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004682 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004683 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004684
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004685 if (!SkipIvars.empty()) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004686 unsigned int LastIndex = SkipIvars.size()-1;
Eli Friedmane5b46662012-11-06 22:15:52 +00004687 int LastByteSkipped =
4688 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004689 LastIndex = IvarsInfo.size()-1;
Eli Friedmane5b46662012-11-06 22:15:52 +00004690 int LastByteScanned =
4691 IvarsInfo[LastIndex].ivar_bytepos +
4692 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004693 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramer54d76db2009-12-25 15:43:36 +00004694 if (LastByteSkipped > LastByteScanned) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004695 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00004696 SKIP_SCAN SkScan;
Eli Friedmane5b46662012-11-06 22:15:52 +00004697 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00004698 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004699 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-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 Jahanian81adc052009-04-24 16:17:09 +00004704 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004705 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-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 Jahanian93ce50d2010-08-04 23:55:24 +00004715
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004716 // Generate the string.
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004717 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-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 Jahanian93ce50d2010-08-04 23:55:24 +00004723
Fariborz Jahanian9397e1d2009-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 Jahanian93ce50d2010-08-04 23:55:24 +00004727
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004728 // next (skip small, scan)
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004729 if (skip_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004730 byte = skip_small << 4;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004731 if (scan_big > 0) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004732 byte |= 0xf;
4733 --scan_big;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004734 } else if (scan_small) {
Fariborz Jahanian9397e1d2009-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 Dunbar31682fd2009-05-03 23:21:22 +00004744 if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004745 byte = scan_small;
4746 BitMap += byte;
4747 }
4748 }
4749 // null terminate string.
Fariborz Jahanian667423a2009-03-25 22:36:49 +00004750 unsigned char zero = 0;
4751 BitMap += zero;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004752
4753 llvm::GlobalVariable * Entry =
4754 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner94010692012-02-05 02:30:40 +00004755 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004756 ((ObjCABI == 2) ?
4757 "__TEXT,__objc_classname,cstring_literals" :
4758 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004759 1, true);
4760 return getConstantGEP(VMContext, Entry, 0, 0);
4761}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004762
Fariborz Jahanian93ce50d2010-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 Lattner8b418682012-02-07 00:39:47 +00004784 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikie4e4d0842012-03-11 07:00:24 +00004785 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
4786 !CGM.getLangOpts().ObjCAutoRefCount)
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004787 return llvm::Constant::getNullValue(PtrTy);
4788
Jordy Rosedb8264e2011-07-22 02:08:32 +00004789 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
4790 SmallVector<const FieldDecl*, 32> RecFields;
David Blaikie4e4d0842012-03-11 07:00:24 +00004791 if (CGM.getLangOpts().ObjCAutoRefCount) {
Jordy Rosedb8264e2011-07-22 02:08:32 +00004792 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00004793 IVD; IVD = IVD->getNextIvar())
4794 RecFields.push_back(cast<FieldDecl>(IVD));
4795 }
4796 else {
Jordy Rosedb8264e2011-07-22 02:08:32 +00004797 SmallVector<const ObjCIvarDecl*, 32> Ivars;
John McCallf85e1932011-06-15 23:02:42 +00004798 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004799
Jordy Rosedb8264e2011-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 Jahanianbf9eb882011-06-28 18:05:25 +00004802 }
Fariborz Jahanian93ce50d2010-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 Friedmane5b46662012-11-06 22:15:52 +00004810 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004811 if (IvarsInfo.empty())
4812 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanianb8fd2eb2010-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 Jahanian93ce50d2010-08-04 23:55:24 +00004820 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00004821 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004822
David Blaikie4e4d0842012-03-11 07:00:24 +00004823 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004824 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian3d2ad662009-04-20 22:03:45 +00004825 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar4087f272010-08-17 22:39:59 +00004826 OMD->getClassInterface()->getName().data());
Roman Divacky31ba6132012-09-06 15:59:27 +00004827 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling13562a12012-02-07 09:06:01 +00004828 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian3d2ad662009-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 Jahanian93ce50d2010-08-04 23:55:24 +00004835 return C;
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00004836}
4837
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004838llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004839 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
4840
Chris Lattner0b239712012-02-06 22:16:34 +00004841 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004842 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004843 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Chris Lattner94010692012-02-05 02:30:40 +00004844 llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004845 ((ObjCABI == 2) ?
4846 "__TEXT,__objc_methname,cstring_literals" :
4847 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004848 1, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004849
Owen Andersona1cf15f2009-07-14 23:10:40 +00004850 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004851}
4852
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004853// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004854llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004855 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4856}
4857
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00004858llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel7794bb82009-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 Dunbar6efc0c52008-08-13 03:21:16 +00004863
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004864 if (!Entry)
4865 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner94010692012-02-05 02:30:40 +00004866 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004867 ((ObjCABI == 2) ?
4868 "__TEXT,__objc_methtype,cstring_literals" :
4869 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004870 1, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004871
Owen Andersona1cf15f2009-07-14 23:10:40 +00004872 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004873}
4874
Bob Wilsondc8dab62011-11-30 01:57:58 +00004875llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
4876 bool Extended) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004877 std::string TypeStr;
Bill Wendlinga4dc6932012-02-09 22:45:21 +00004878 if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
Douglas Gregorf968d832011-05-27 01:19:52 +00004879 return 0;
Devang Patel7794bb82009-03-04 18:21:39 +00004880
4881 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4882
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004883 if (!Entry)
4884 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner94010692012-02-05 02:30:40 +00004885 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004886 ((ObjCABI == 2) ?
4887 "__TEXT,__objc_methtype,cstring_literals" :
4888 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004889 1, true);
Devang Patel7794bb82009-03-04 18:21:39 +00004890
Owen Andersona1cf15f2009-07-14 23:10:40 +00004891 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004892}
4893
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004894// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004895llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004896 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004897
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004898 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004899 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Chris Lattner94010692012-02-05 02:30:40 +00004900 llvm::ConstantDataArray::getString(VMContext,
4901 Ident->getNameStart()),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004902 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004903 1, true);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004904
Owen Andersona1cf15f2009-07-14 23:10:40 +00004905 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004906}
4907
4908// FIXME: Merge into a single cstring creation function.
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00004909// FIXME: This Decl should be more precise.
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004910llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004911CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4912 const Decl *Container) {
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00004913 std::string TypeStr;
4914 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004915 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4916}
4917
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004918void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004919 const ObjCContainerDecl *CD,
Chris Lattner5f9e2722011-07-23 10:55:15 +00004920 SmallVectorImpl<char> &Name) {
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004921 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian679a5022009-01-10 21:06:09 +00004922 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004923 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4924 << '[' << CD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004925 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004926 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramerf9780592012-02-07 11:57:45 +00004927 OS << '(' << *CID << ')';
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004928 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00004929}
4930
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004931void CGObjCMac::FinishModule() {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004932 EmitModuleInfo();
4933
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004934 // Emit the dummy bodies for any protocols which were referenced but
4935 // never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004936 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerad64e022009-07-17 23:57:13 +00004937 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4938 if (I->second->hasInitializer())
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004939 continue;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004940
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00004941 llvm::Constant *Values[5];
Owen Andersonc9c88b42009-07-31 20:28:54 +00004942 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004943 Values[1] = GetClassName(I->first);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004944 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004945 Values[3] = Values[4] =
Owen Andersonc9c88b42009-07-31 20:28:54 +00004946 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004947 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson08e25242009-07-27 22:29:56 +00004948 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004949 Values));
Chris Lattnerad64e022009-07-17 23:57:13 +00004950 CGM.AddUsedGlobal(I->second);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004951 }
4952
Daniel Dunbar242d4dc2008-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 Dunbar33063492009-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 Noblesmithf7ccbad2012-02-05 02:13:05 +00004959 SmallString<256> Asm;
Daniel Dunbar33063492009-09-07 00:20:42 +00004960 Asm += CGM.getModule().getModuleInlineAsm();
4961 if (!Asm.empty() && Asm.back() != '\n')
4962 Asm += '\n';
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004963
Daniel Dunbar33063492009-09-07 00:20:42 +00004964 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbar33063492009-09-07 00:20:42 +00004965 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4966 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar01eb9b92009-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 Lattnerafd5eda2010-04-17 18:26:20 +00004969 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004970 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004971 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004972 }
4973
Bill Wendling13562a12012-02-07 09:06:01 +00004974 for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) {
Fariborz Jahanianb9c5b3d2010-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 Lattnerafd5eda2010-04-17 18:26:20 +00004978
Daniel Dunbar33063492009-09-07 00:20:42 +00004979 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004980 }
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004981}
4982
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004983CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004984 : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00004985 ObjCTypes(cgm) {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004986 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004987 ObjCABI = 2;
4988}
4989
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004990/* *** */
4991
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004992ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Douglas Gregor65a1e672012-01-17 23:38:32 +00004993 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(0)
4994{
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004995 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4996 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004997
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004998 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004999 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00005000 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005001 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Chris Lattner8b418682012-02-07 00:39:47 +00005002 Int8PtrTy = CGM.Int8PtrTy;
5003 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005004
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00005005 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00005006 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00005007 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005008
Fariborz Jahanianee0af742009-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 Dunbar6bff2512009-08-03 17:06:42 +00005013
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005014 // FIXME: This is leaked.
5015 // FIXME: Merge with rewriter code?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005016
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005017 // struct _objc_super {
5018 // id self;
5019 // Class cls;
5020 // }
Abramo Bagnara465d41b2010-05-11 21:36:43 +00005021 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00005022 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00005023 SourceLocation(), SourceLocation(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005024 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00005025 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smithca523302012-06-10 03:12:00 +00005026 Ctx.getObjCIdType(), 0, 0, false, ICIS_NoInit));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00005027 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smithca523302012-06-10 03:12:00 +00005028 Ctx.getObjCClassType(), 0, 0, false,
5029 ICIS_NoInit));
Douglas Gregor838db382010-02-11 01:19:42 +00005030 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005031
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005032 SuperCTy = Ctx.getTagDeclType(RD);
5033 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005034
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005035 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005036 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5037
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005038 // struct _prop_t {
5039 // char *name;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005040 // char *attributes;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005041 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00005042 PropertyTy = llvm::StructType::create("struct._prop_t",
5043 Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005044
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005045 // struct _prop_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005046 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005047 // uint32_t count_of_properties;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005048 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005049 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005050 PropertyListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005051 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
5052 llvm::ArrayType::get(PropertyTy, 0), NULL);
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005053 // struct _prop_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00005054 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005055
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005056 // struct _objc_method {
5057 // SEL _cmd;
5058 // char *method_type;
5059 // char *_imp;
5060 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00005061 MethodTy = llvm::StructType::create("struct._objc_method",
5062 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
5063 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005064
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005065 // struct _objc_cache *
Chris Lattnerc1c20112011-08-12 17:43:31 +00005066 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson96e0fc72009-07-29 22:16:19 +00005067 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00005068
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005069}
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00005070
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005071ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00005072 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005073 // struct _objc_method_description {
5074 // SEL name;
5075 // char *types;
5076 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005077 MethodDescriptionTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005078 llvm::StructType::create("struct._objc_method_description",
5079 SelectorPtrTy, Int8PtrTy, NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005080
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005081 // struct _objc_method_description_list {
5082 // int count;
5083 // struct _objc_method_description[1];
5084 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005085 MethodDescriptionListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005086 llvm::StructType::create("struct._objc_method_description_list",
5087 IntTy,
5088 llvm::ArrayType::get(MethodDescriptionTy, 0),NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005089
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005090 // struct _objc_method_description_list *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005091 MethodDescriptionListPtrTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +00005092 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005093
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005094 // Protocol description structures
5095
Fariborz Jahanian10a42312009-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 Wilsondc8dab62011-11-30 01:57:58 +00005101 // const char ** extendedMethodTypes;
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005102 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005103 ProtocolExtensionTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005104 llvm::StructType::create("struct._objc_protocol_extension",
5105 IntTy, MethodDescriptionListPtrTy,
5106 MethodDescriptionListPtrTy, PropertyListPtrTy,
Bob Wilsondc8dab62011-11-30 01:57:58 +00005107 Int8PtrPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005108
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005109 // struct _objc_protocol_extension *
Owen Anderson96e0fc72009-07-29 22:16:19 +00005110 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005111
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00005112 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005113
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005114 ProtocolTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005115 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005116
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005117 ProtocolListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005118 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005119 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005120 LongTy,
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005121 llvm::ArrayType::get(ProtocolTy, 0),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005122 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005123
Fariborz Jahanian10a42312009-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 Lattner9cbe4f02011-07-09 17:41:47 +00005131 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5132 llvm::PointerType::getUnqual(ProtocolListTy),
5133 MethodDescriptionListPtrTy,
5134 MethodDescriptionListPtrTy,
5135 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005136
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005137 // struct _objc_protocol_list *
Owen Anderson96e0fc72009-07-29 22:16:19 +00005138 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005139
Owen Anderson96e0fc72009-07-29 22:16:19 +00005140 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005141
5142 // Class description structures
5143
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005144 // struct _objc_ivar {
5145 // char *ivar_name;
5146 // char *ivar_type;
5147 // int ivar_offset;
5148 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00005149 IvarTy = llvm::StructType::create("struct._objc_ivar",
5150 Int8PtrTy, Int8PtrTy, IntTy, NULL);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005151
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005152 // struct _objc_ivar_list *
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005153 IvarListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005154 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson96e0fc72009-07-29 22:16:19 +00005155 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005156
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005157 // struct _objc_method_list *
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005158 MethodListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005159 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson96e0fc72009-07-29 22:16:19 +00005160 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005161
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005162 // struct _objc_class_extension *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005163 ClassExtensionTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005164 llvm::StructType::create("struct._objc_class_extension",
5165 IntTy, Int8PtrTy, PropertyListPtrTy, NULL);
Owen Anderson96e0fc72009-07-29 22:16:19 +00005166 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005167
Chris Lattnerc1c20112011-08-12 17:43:31 +00005168 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005169
Fariborz Jahanian10a42312009-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 Lattner9cbe4f02011-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 Dunbar6bff2512009-08-03 17:06:42 +00005197
Owen Anderson96e0fc72009-07-29 22:16:19 +00005198 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005199
Fariborz Jahanian10a42312009-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 Lattner9cbe4f02011-07-09 17:41:47 +00005208 CategoryTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005209 llvm::StructType::create("struct._objc_category",
5210 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5211 MethodListPtrTy, ProtocolListPtrTy,
5212 IntTy, PropertyListPtrTy, NULL);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00005213
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005214 // Global metadata structures
5215
Fariborz Jahanian10a42312009-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 Lattner9cbe4f02011-07-09 17:41:47 +00005223 SymtabTy =
Chris Lattnerc1c20112011-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 Anderson96e0fc72009-07-29 22:16:19 +00005227 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005228
Fariborz Jahaniandb286862009-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 Dunbar6bff2512009-08-03 17:06:42 +00005235 ModuleTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005236 llvm::StructType::create("struct._objc_module",
5237 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00005238
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005239
Mike Stumpf5408fe2009-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 Carlsson124526b2008-09-09 10:10:21 +00005242 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005243
Anders Carlsson124526b2008-09-09 10:10:21 +00005244 // Exceptions
Chris Lattner8b418682012-02-07 00:39:47 +00005245 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005246
5247 ExceptionDataTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005248 llvm::StructType::create("struct._objc_exception_data",
Chris Lattner8b418682012-02-07 00:39:47 +00005249 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
5250 StackPtrTy, NULL);
Anders Carlsson124526b2008-09-09 10:10:21 +00005251
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00005252}
5253
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005254ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00005255 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian30bc5712009-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 Lattner9cbe4f02011-07-09 17:41:47 +00005261 MethodListnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005262 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
5263 llvm::ArrayType::get(MethodTy, 0), NULL);
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005264 // struct method_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00005265 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005266
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005267 // struct _protocol_t {
5268 // id isa; // NULL
5269 // const char * const protocol_name;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005270 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanian30bc5712009-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 Jahaniand55b6fc2009-01-23 01:46:23 +00005275 // const struct _prop_list_t * properties;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005276 // const uint32_t size; // sizeof(struct _protocol_t)
5277 // const uint32_t flags; // = 0
Bob Wilsondc8dab62011-11-30 01:57:58 +00005278 // const char ** extendedMethodTypes;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005279 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005280
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005281 // Holder for struct _protocol_list_t *
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005282 ProtocolListnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005283 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005284
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005285 ProtocolnfABITy =
Chris Lattnerc1c20112011-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 Wilsondc8dab62011-11-30 01:57:58 +00005290 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
5291 NULL);
Daniel Dunbar948e2582009-02-15 07:36:20 +00005292
5293 // struct _protocol_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00005294 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005295
Fariborz Jahanianda320092009-01-29 19:24:30 +00005296 // struct _protocol_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005297 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar948e2582009-02-15 07:36:20 +00005298 // struct _protocol_t *[protocol_count];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005299 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005300 ProtocolListnfABITy->setBody(LongTy,
5301 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
5302 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005303
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005304 // struct _objc_protocol_list*
Owen Anderson96e0fc72009-07-29 22:16:19 +00005305 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005306
Fariborz Jahanian30bc5712009-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 Lattner9cbe4f02011-07-09 17:41:47 +00005314 IvarnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005315 llvm::StructType::create("struct._ivar_t",
5316 llvm::PointerType::getUnqual(LongTy),
5317 Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005318
Fariborz Jahanian30bc5712009-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 Lattner9cbe4f02011-07-09 17:41:47 +00005324 IvarListnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005325 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
5326 llvm::ArrayType::get(IvarnfABITy, 0), NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005327
Owen Anderson96e0fc72009-07-29 22:16:19 +00005328 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005329
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005330 // struct _class_ro_t {
Fariborz Jahanian30bc5712009-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 Dunbar6bff2512009-08-03 17:06:42 +00005343
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005344 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattnerc1c20112011-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 Dunbar6bff2512009-08-03 17:06:42 +00005351
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005352 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005353 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall0774cb82011-05-15 01:53:33 +00005354 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5355 ->getPointerTo();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005356
Fariborz Jahaniand55b6fc2009-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 Dunbar6bff2512009-08-03 17:06:42 +00005364
Chris Lattnerc1c20112011-08-12 17:43:31 +00005365 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattner9cbe4f02011-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 Dunbar6bff2512009-08-03 17:06:42 +00005372
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005373 // LLVM for struct _class_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00005374 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005375
Fariborz Jahaniand55b6fc2009-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 Jahanian45c2ba02009-01-23 17:41:22 +00005383 // }
Chris Lattnerc1c20112011-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 Dunbar6bff2512009-08-03 17:06:42 +00005391
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00005392 // New types for nonfragile abi messaging.
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005393 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5394 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005395
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00005396 // MessageRefTy - LLVM for:
5397 // struct _message_ref_t {
5398 // IMP messenger;
5399 // SEL name;
5400 // };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005401
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005402 // First the clang type for struct _message_ref_t
Abramo Bagnara465d41b2010-05-11 21:36:43 +00005403 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00005404 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00005405 SourceLocation(), SourceLocation(),
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005406 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00005407 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smithca523302012-06-10 03:12:00 +00005408 Ctx.VoidPtrTy, 0, 0, false, ICIS_NoInit));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00005409 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smithca523302012-06-10 03:12:00 +00005410 Ctx.getObjCSelType(), 0, 0, false,
5411 ICIS_NoInit));
Douglas Gregor838db382010-02-11 01:19:42 +00005412 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005413
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005414 MessageRefCTy = Ctx.getTagDeclType(RD);
5415 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5416 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005417
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00005418 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00005419 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005420
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00005421 // SuperMessageRefTy - LLVM for:
5422 // struct _super_message_ref_t {
5423 // SUPER_IMP messenger;
5424 // SEL name;
5425 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005426 SuperMessageRefTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005427 llvm::StructType::create("struct._super_message_ref_t",
5428 ImpnfABITy, SelectorPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005429
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00005430 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005431 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00005432
Daniel Dunbare588b992009-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 Lattner9cbe4f02011-07-09 17:41:47 +00005439 EHTypeTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005440 llvm::StructType::create("struct._objc_typeinfo",
5441 llvm::PointerType::getUnqual(Int8PtrTy),
5442 Int8PtrTy, ClassnfABIPtrTy, NULL);
Owen Anderson96e0fc72009-07-29 22:16:19 +00005443 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00005444}
5445
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005446llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005447 FinishNonFragileABIModule();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005448
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005449 return NULL;
5450}
5451
Bill Wendlingbb028552012-02-07 09:25:09 +00005452void CGObjCNonFragileABIMac::
5453AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
5454 const char *SymbolName,
5455 const char *SectionName) {
Daniel Dunbar463b8762009-05-15 21:48:48 +00005456 unsigned NumClasses = Container.size();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005457
Daniel Dunbar463b8762009-05-15 21:48:48 +00005458 if (!NumClasses)
5459 return;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005460
Chris Lattner0b239712012-02-06 22:16:34 +00005461 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar463b8762009-05-15 21:48:48 +00005462 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00005463 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar463b8762009-05-15 21:48:48 +00005464 ObjCTypes.Int8PtrTy);
Chris Lattner0b239712012-02-06 22:16:34 +00005465 llvm::Constant *Init =
Owen Anderson96e0fc72009-07-29 22:16:19 +00005466 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner0b239712012-02-06 22:16:34 +00005467 Symbols.size()),
Daniel Dunbar463b8762009-05-15 21:48:48 +00005468 Symbols);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005469
Daniel Dunbar463b8762009-05-15 21:48:48 +00005470 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005471 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar463b8762009-05-15 21:48:48 +00005472 llvm::GlobalValue::InternalLinkage,
5473 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005474 SymbolName);
Micah Villmow25a6a842012-10-08 16:25:52 +00005475 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Daniel Dunbar463b8762009-05-15 21:48:48 +00005476 GV->setSection(SectionName);
Chris Lattnerad64e022009-07-17 23:57:13 +00005477 CGM.AddUsedGlobal(GV);
Daniel Dunbar463b8762009-05-15 21:48:48 +00005478}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005479
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005480void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5481 // nonfragile abi has no module definition.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005482
Daniel Dunbar463b8762009-05-15 21:48:48 +00005483 // Build list of all implemented class addresses in array
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00005484 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005485 AddModuleClassList(DefinedClasses,
Daniel Dunbar463b8762009-05-15 21:48:48 +00005486 "\01L_OBJC_LABEL_CLASS_$",
5487 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005488
Bill Wendling13562a12012-02-07 09:06:01 +00005489 for (unsigned i = 0, e = DefinedClasses.size(); i < e; i++) {
Fariborz Jahaniana03d0dd2009-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 Jahaniana03d0dd2009-11-17 21:37:35 +00005494 }
5495
Bill Wendling13562a12012-02-07 09:06:01 +00005496 for (unsigned i = 0, e = DefinedMetaClasses.size(); i < e; i++) {
Fariborz Jahanian0e93d252009-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 Jahaniana03d0dd2009-11-17 21:37:35 +00005502
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005503 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005504 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
5505 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005506
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00005507 // Build list of all implemented category addresses in array
5508 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005509 AddModuleClassList(DefinedCategories,
Daniel Dunbar463b8762009-05-15 21:48:48 +00005510 "\01L_OBJC_LABEL_CATEGORY_$",
5511 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005512 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005513 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
5514 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005515
Daniel Dunbarfce176b2010-04-25 20:39:01 +00005516 EmitImageInfo();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005517}
5518
John McCall944c8432011-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 Dunbar6bff2512009-08-03 17:06:42 +00005521/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00005522/// message dispatch call for all the rest.
John McCall944c8432011-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 Dunbarf643b9b2010-04-24 17:56:46 +00005526 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00005527 case CodeGenOptions::Legacy:
Fariborz Jahanian776dbf92010-04-19 17:53:30 +00005528 return false;
John McCall944c8432011-05-14 03:10:52 +00005529 case CodeGenOptions::NonLegacy:
5530 return true;
Daniel Dunbarf643b9b2010-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 McCall944c8432011-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 Dunbar6bff2512009-08-03 17:06:42 +00005544
John McCall944c8432011-05-14 03:10:52 +00005545 // These are vtable-based if GC is disabled.
5546 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikie4e4d0842012-03-11 07:00:24 +00005547 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall944c8432011-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 Blaikie4e4d0842012-03-11 07:00:24 +00005563 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall944c8432011-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 Jahaniand0f8a8d2009-05-11 19:25:47 +00005576 }
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00005577
John McCall944c8432011-05-14 03:10:52 +00005578 return VTableDispatchMethods.count(Sel);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00005579}
5580
Fariborz Jahanian058a1b72009-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 Jahanianda320092009-01-29 19:24:30 +00005590/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian058a1b72009-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 Dunbar6bff2512009-08-03 17:06:42 +00005597 unsigned flags,
5598 unsigned InstanceStart,
5599 unsigned InstanceSize,
5600 const ObjCImplementationDecl *ID) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005601 std::string ClassName = ID->getNameAsString();
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005602 llvm::Constant *Values[10]; // 11 for 64bit targets!
John McCallf85e1932011-06-15 23:02:42 +00005603
David Blaikie4e4d0842012-03-11 07:00:24 +00005604 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCall621915c2012-10-17 04:53:23 +00005605 flags |= NonFragileABI_Class_CompiledByARC;
John McCallf85e1932011-06-15 23:02:42 +00005606
Owen Anderson4a28d5d2009-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 Jahanian058a1b72009-01-24 20:21:50 +00005610 // FIXME. For 64bit targets add 0 here.
John McCall621915c2012-10-17 04:53:23 +00005611 Values[ 3] = (flags & NonFragileABI_Class_Meta)
5612 ? GetIvarLayoutName(0, ObjCTypes)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005613 : BuildIvarLayout(ID, true);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005614 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian493dab72009-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 McCall621915c2012-10-17 04:53:23 +00005618 if (flags & NonFragileABI_Class_Meta) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005619 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005620 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005621 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-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 Dunbar6bff2512009-08-03 17:06:42 +00005627 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005628 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005629 // Instance methods should always be defined.
5630 Methods.push_back(GetMethodConstant(*i));
5631 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005632 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005633 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie581deb32012-06-06 20:45:41 +00005634 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005635
Fariborz Jahanian939abce2009-01-28 22:46:49 +00005636 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
5637 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005638
Fariborz Jahanian939abce2009-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 Jahanian493dab72009-01-26 21:38:32 +00005647 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005648 Values[ 5] = EmitMethodList(MethodListName,
5649 "__DATA, __objc_const", Methods);
5650
Fariborz Jahanianda320092009-01-29 19:24:30 +00005651 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5652 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005653 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005654 + OID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00005655 OID->all_referenced_protocol_begin(),
5656 OID->all_referenced_protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005657
John McCall621915c2012-10-17 04:53:23 +00005658 if (flags & NonFragileABI_Class_Meta) {
Owen Andersonc9c88b42009-07-31 20:28:54 +00005659 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCall621915c2012-10-17 04:53:23 +00005660 Values[ 8] = GetIvarLayoutName(0, ObjCTypes);
Owen Andersonc9c88b42009-07-31 20:28:54 +00005661 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
John McCall621915c2012-10-17 04:53:23 +00005662 } else {
5663 Values[ 7] = EmitIvarList(ID);
5664 Values[ 8] = BuildIvarLayout(ID, false);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005665 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
5666 ID, ID->getClassInterface(), ObjCTypes);
John McCall621915c2012-10-17 04:53:23 +00005667 }
Owen Anderson08e25242009-07-27 22:29:56 +00005668 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005669 Values);
5670 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005671 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
5672 llvm::GlobalValue::InternalLinkage,
5673 Init,
John McCall621915c2012-10-17 04:53:23 +00005674 (flags & NonFragileABI_Class_Meta) ?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005675 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
5676 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005677 CLASS_RO_GV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00005678 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005679 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005680 return CLASS_RO_GV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005681
Fariborz Jahanian058a1b72009-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 Jahanian84394a52009-01-24 21:21:53 +00005694llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar6bff2512009-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 Kramer1d236ab2011-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 Dunbar6bff2512009-08-03 17:06:42 +00005707 if (!Values[1])
5708 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005709 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005710 Values);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005711 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
5712 GV->setInitializer(Init);
Fariborz Jahaniandd0db2a2009-01-31 01:07:39 +00005713 GV->setSection("__DATA, __objc_data");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005714 GV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00005715 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005716 if (HiddenVisibility)
5717 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005718 return GV;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005719}
5720
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005721bool
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00005722CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005723 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005724}
5725
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005726void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00005727 uint32_t &InstanceStart,
5728 uint32_t &InstanceSize) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005729 const ASTRecordLayout &RL =
Daniel Dunbarb4c79e02009-05-04 21:26:30 +00005730 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005731
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00005732 // InstanceSize is really instance end.
Ken Dyckec299032011-02-11 02:20:09 +00005733 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar6e8575b2009-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 Dyckfb67ccd2011-04-14 00:43:09 +00005739 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbarb02532a2009-04-19 23:41:48 +00005740}
5741
Fariborz Jahanianaa23b572009-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 Dunbar6bff2512009-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 Jahanianaa23b572009-01-23 23:53:38 +00005753 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005754 CGM.getModule(),
5755 ObjCTypes.ImpnfABITy,
5756 false,
5757 llvm::GlobalValue::ExternalLinkage,
5758 0,
5759 "_objc_empty_vtable");
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005760 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005761 assert(ID->getClassInterface() &&
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005762 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbar6c1aac82009-04-20 20:18:54 +00005763 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005764 uint32_t InstanceStart =
Micah Villmow25a6a842012-10-08 16:25:52 +00005765 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005766 uint32_t InstanceSize = InstanceStart;
John McCall621915c2012-10-17 04:53:23 +00005767 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005768 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
5769 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005770
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005771 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005772
John McCallb03527a2012-10-17 04:53:31 +00005773 // Build the flags for the metaclass.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005774 bool classIsHidden =
John McCall1fb0caa2010-10-22 21:05:15 +00005775 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005776 if (classIsHidden)
John McCall621915c2012-10-17 04:53:23 +00005777 flags |= NonFragileABI_Class_Hidden;
John McCallb03527a2012-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 McCall621915c2012-10-17 04:53:23 +00005782 flags |= NonFragileABI_Class_HasCXXStructors;
John McCallb03527a2012-10-17 04:53:31 +00005783 if (!ID->hasNonZeroConstructors())
5784 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5785 }
5786
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005787 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005788 // class is root
John McCall621915c2012-10-17 04:53:23 +00005789 flags |= NonFragileABI_Class_Root;
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005790 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005791 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005792 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005793 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00005794 const ObjCInterfaceDecl *Root = ID->getClassInterface();
5795 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
5796 Root = Super;
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005797 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005798 if (Root->isWeakImported())
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00005799 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00005800 // work on super class metadata symbol.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005801 std::string SuperClassName =
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00005802 ObjCMetaClassName +
5803 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005804 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005805 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005806 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005807 }
5808 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
5809 InstanceStart,
5810 InstanceSize,ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005811 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005812 llvm::GlobalVariable *MetaTClass =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005813 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
5814 classIsHidden);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005815 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005816
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005817 // Metadata for the class
John McCall621915c2012-10-17 04:53:23 +00005818 flags = 0;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005819 if (classIsHidden)
John McCall621915c2012-10-17 04:53:23 +00005820 flags |= NonFragileABI_Class_Hidden;
John McCallb03527a2012-10-17 04:53:31 +00005821
5822 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCall621915c2012-10-17 04:53:23 +00005823 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005824
John McCallb03527a2012-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 Gregor68584ed2009-06-18 16:11:24 +00005835 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
John McCall621915c2012-10-17 04:53:23 +00005836 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005837
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005838 if (!ID->getClassInterface()->getSuperClass()) {
John McCall621915c2012-10-17 04:53:23 +00005839 flags |= NonFragileABI_Class_Root;
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005840 SuperClassGV = 0;
Chris Lattnerb7b58b12009-04-19 06:02:28 +00005841 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005842 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00005843 std::string RootClassName =
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005844 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005845 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005846 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005847 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005848 }
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005849 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005850 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00005851 InstanceStart,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005852 InstanceSize,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00005853 ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005854
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005855 TClassName = ObjCClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005856 llvm::GlobalVariable *ClassMD =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005857 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5858 classIsHidden);
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00005859 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005860
Daniel Dunbar74d4b122009-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 Dunbar8158a2f2009-04-08 04:21:03 +00005865 // Force the definition of the EHType if necessary.
John McCall621915c2012-10-17 04:53:23 +00005866 if (flags & NonFragileABI_Class_Exception)
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005867 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00005868 // Make sure method definition entries are all clear for next implementation.
5869 MethodDefinitions.clear();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005870}
5871
Fariborz Jahanian8cfd3972009-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 Dunbar6bff2512009-08-03 17:06:42 +00005881 const ObjCProtocolDecl *PD) {
5882
Fariborz Jahanian960cd062009-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 Dunbar6bff2512009-08-03 17:06:42 +00005886 llvm::Constant *Init =
5887 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor4c86fdb2012-01-17 18:36:30 +00005888 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005889
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005890 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar4087f272010-08-17 22:39:59 +00005891 ProtocolName += PD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005892
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005893 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5894 if (PTGV)
Benjamin Kramer578faa82011-09-27 21:06:10 +00005895 return Builder.CreateLoad(PTGV);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005896 PTGV = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005897 CGM.getModule(),
5898 Init->getType(), false,
5899 llvm::GlobalValue::WeakAnyLinkage,
5900 Init,
5901 ProtocolName);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005902 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5903 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005904 CGM.AddUsedGlobal(PTGV);
Benjamin Kramer578faa82011-09-27 21:06:10 +00005905 return Builder.CreateLoad(PTGV);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005906}
5907
Fariborz Jahanianeb062d92009-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 Dunbar74d4b122009-05-15 22:33:15 +00005918void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005919 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005920 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005921 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5922 "_$_" + OCD->getNameAsString());
5923 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005924 Interface->getNameAsString());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005925
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005926 llvm::Constant *Values[6];
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005927 Values[0] = GetClassName(OCD->getIdentifier());
5928 // meta-class entry symbol
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005929 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005930 if (Interface->isWeakImported())
Fariborz Jahanian2cdcc4c2009-11-17 22:02:21 +00005931 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5932
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005933 Values[1] = ClassGV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005934 std::vector<llvm::Constant*> Methods;
5935 std::string MethodListName(Prefix);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005936 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005937 "_$_" + OCD->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005938
5939 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005940 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005941 // Instance methods should always be defined.
5942 Methods.push_back(GetMethodConstant(*i));
5943 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005944
5945 Values[2] = EmitMethodList(MethodListName,
5946 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005947 Methods);
5948
5949 MethodListName = Prefix;
5950 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5951 OCD->getNameAsString();
5952 Methods.clear();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005953 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005954 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005955 // Class methods should always be defined.
5956 Methods.push_back(GetMethodConstant(*i));
5957 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005958
5959 Values[3] = EmitMethodList(MethodListName,
5960 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005961 Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005962 const ObjCCategoryDecl *Category =
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00005963 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005964 if (Category) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00005965 SmallString<256> ExtName;
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005966 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5967 << OCD->getName();
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005968 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005969 + Interface->getName() + "_$_"
5970 + Category->getName(),
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005971 Category->protocol_begin(),
5972 Category->protocol_end());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005973 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5974 OCD, Category, ObjCTypes);
Mike Stumpb3589f42009-07-30 22:28:39 +00005975 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00005976 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5977 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005978 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005979
5980 llvm::Constant *Init =
5981 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005982 Values);
5983 llvm::GlobalVariable *GCATV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005984 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005985 false,
5986 llvm::GlobalValue::InternalLinkage,
5987 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005988 ExtCatName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005989 GCATV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00005990 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005991 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerad64e022009-07-17 23:57:13 +00005992 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005993 DefinedCategories.push_back(GCATV);
Daniel Dunbar74d4b122009-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 Jahanian64089ce2011-04-22 22:02:28 +00005998 // method definition entries must be clear for next implementation.
5999 MethodDefinitions.clear();
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00006000}
Fariborz Jahanian493dab72009-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 Dunbar6bff2512009-08-03 17:06:42 +00006006 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00006007 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006008 if (!Fn)
6009 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006010
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006011 llvm::Constant *Method[] = {
Owen Anderson3c4972d2009-07-29 18:54:39 +00006012 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006013 ObjCTypes.SelectorPtrTy),
6014 GetMethodVarType(MD),
6015 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
6016 };
Owen Anderson08e25242009-07-27 22:29:56 +00006017 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian493dab72009-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 Wendlingbb028552012-02-07 09:25:09 +00006027llvm::Constant *
6028CGObjCNonFragileABIMac::EmitMethodList(Twine Name,
6029 const char *Section,
6030 ArrayRef<llvm::Constant*> Methods) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006031 // Return null for empty list.
6032 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00006033 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006034
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006035 llvm::Constant *Values[3];
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006036 // sizeof(struct _objc_method)
Micah Villmow25a6a842012-10-08 16:25:52 +00006037 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006038 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006039 // method_count
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006040 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00006041 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006042 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00006043 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006044 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006045
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006046 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00006047 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006048 llvm::GlobalValue::InternalLinkage, Init, Name);
Micah Villmow25a6a842012-10-08 16:25:52 +00006049 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006050 GV->setSection(Section);
Chris Lattnerad64e022009-07-17 23:57:13 +00006051 CGM.AddUsedGlobal(GV);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006052 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006053}
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006054
Fariborz Jahanianed157d32009-02-10 20:21:06 +00006055/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6056/// the given ivar.
Daniel Dunbare83be122010-04-02 21:14:02 +00006057llvm::GlobalVariable *
6058CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6059 const ObjCIvarDecl *Ivar) {
6060 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbara81419d2009-05-05 00:36:57 +00006061 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregor6ab35242009-04-09 21:40:53 +00006062 '.' + Ivar->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006063 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanianed157d32009-02-10 20:21:06 +00006064 CGM.getModule().getGlobalVariable(Name);
6065 if (!IvarOffsetGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006066 IvarOffsetGV =
Owen Anderson1c431b32009-07-08 19:05:04 +00006067 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanianed157d32009-02-10 20:21:06 +00006068 false,
6069 llvm::GlobalValue::ExternalLinkage,
6070 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00006071 Name);
Fariborz Jahanianed157d32009-02-10 20:21:06 +00006072 return IvarOffsetGV;
6073}
6074
Daniel Dunbare83be122010-04-02 21:14:02 +00006075llvm::Constant *
6076CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6077 const ObjCIvarDecl *Ivar,
Eli Friedmane5b46662012-11-06 22:15:52 +00006078 unsigned long int Offset) {
Daniel Dunbar737c5022009-04-19 00:44:02 +00006079 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006080 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Eli Friedmane5b46662012-11-06 22:15:52 +00006081 Offset));
Fariborz Jahanian09796d62009-01-31 02:43:27 +00006082 IvarOffsetGV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006083 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbar737c5022009-04-19 00:44:02 +00006084
Mike Stumpf5408fe2009-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 Dunbar737c5022009-04-19 00:44:02 +00006087 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6088 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall1fb0caa2010-10-22 21:05:15 +00006089 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00006090 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar04d40782009-04-14 06:00:08 +00006091 else
Fariborz Jahanian77c9fd22009-04-06 18:30:00 +00006092 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendling1f382512011-05-04 21:37:25 +00006093 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanian45012a72009-02-03 00:09:52 +00006094 return IvarOffsetGV;
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00006095}
6096
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006097/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar11394522009-04-18 08:51:00 +00006098/// implementation. The return value has type
Fariborz Jahanian98abf4b2009-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 Dunbar3e5f0d82009-04-20 06:54:31 +00006113
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006114llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006115 const ObjCImplementationDecl *ID) {
6116
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006117 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006118
Jordy Rosedb8264e2011-07-22 02:08:32 +00006119 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006120 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006121
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00006122 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006123
Jordy Rosedb8264e2011-07-22 02:08:32 +00006124 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00006125 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00006126 // Ignore unnamed bit-fields.
6127 if (!IVD->getDeclName())
6128 continue;
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006129 llvm::Constant *Ivar[5];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006130 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00006131 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00006132 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
6133 Ivar[2] = GetMethodVarType(IVD);
Chris Lattner2acc6e32011-07-18 04:24:23 +00006134 llvm::Type *FieldTy =
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00006135 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmow25a6a842012-10-08 16:25:52 +00006136 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006137 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006138 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006139 Align = llvm::Log2_32(Align);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006140 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbar91636d62009-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 Anderson4a28d5d2009-07-24 23:12:58 +00006146 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson08e25242009-07-27 22:29:56 +00006147 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006148 }
6149 // Return null for empty list.
6150 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00006151 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006152
6153 llvm::Constant *Values[3];
Micah Villmow25a6a842012-10-08 16:25:52 +00006154 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Anderson4a28d5d2009-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 Anderson96e0fc72009-07-29 22:16:19 +00006157 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006158 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00006159 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006160 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006161 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
6162 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00006163 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006164 llvm::GlobalValue::InternalLinkage,
6165 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006166 Prefix + OID->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00006167 GV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006168 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00006169 GV->setSection("__DATA, __objc_const");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006170
Chris Lattnerad64e022009-07-17 23:57:13 +00006171 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00006172 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006173}
6174
6175llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006176 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00006177 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006178
Fariborz Jahanianda320092009-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 Dunbar6bff2512009-08-03 17:06:42 +00006183 Entry =
6184 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
6185 llvm::GlobalValue::ExternalLinkage,
6186 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006187 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianda320092009-01-29 19:24:30 +00006188 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00006189 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006190
Fariborz Jahanianda320092009-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 Wilsondc8dab62011-11-30 01:57:58 +00006207/// const char ** extendedMethodTypes;
Fariborz Jahanianda320092009-01-29 19:24:30 +00006208/// }
6209/// @endcode
6210///
6211
6212llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006213 const ObjCProtocolDecl *PD) {
John McCall50651b92012-03-30 21:29:05 +00006214 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006215
Fariborz Jahanianda320092009-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 Gregor1d784b22012-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 Jahanianda320092009-01-29 19:24:30 +00006224 // Construct method lists.
6225 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
6226 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilsondc8dab62011-11-30 01:57:58 +00006227 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006228 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00006229 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00006230 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006231 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00006232 if (!C)
6233 return GetOrEmitProtocolRef(PD);
6234
Fariborz Jahanianda320092009-01-29 19:24:30 +00006235 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6236 OptInstanceMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00006237 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanianda320092009-01-29 19:24:30 +00006238 } else {
6239 InstanceMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00006240 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006241 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00006242 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006243
6244 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00006245 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00006246 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006247 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00006248 if (!C)
6249 return GetOrEmitProtocolRef(PD);
6250
Fariborz Jahanianda320092009-01-29 19:24:30 +00006251 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6252 OptClassMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00006253 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanianda320092009-01-29 19:24:30 +00006254 } else {
6255 ClassMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00006256 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006257 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00006258 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006259
Bob Wilsondc8dab62011-11-30 01:57:58 +00006260 MethodTypesExt.insert(MethodTypesExt.end(),
6261 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
6262
6263 llvm::Constant *Values[11];
Fariborz Jahanianda320092009-01-29 19:24:30 +00006264 // isa is NULL
Owen Andersonc9c88b42009-07-31 20:28:54 +00006265 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006266 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006267 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
6268 PD->protocol_begin(),
6269 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006270
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006271 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006272 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00006273 "__DATA, __objc_const",
6274 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006275 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006276 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00006277 "__DATA, __objc_const",
6278 ClassMethods);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006279 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006280 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00006281 "__DATA, __objc_const",
6282 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006283 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006284 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00006285 "__DATA, __objc_const",
6286 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006287 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00006288 0, PD, ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006289 uint32_t Size =
Micah Villmow25a6a842012-10-08 16:25:52 +00006290 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006291 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Andersonc9c88b42009-07-31 20:28:54 +00006292 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Bob Wilsondc8dab62011-11-30 01:57:58 +00006293 Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
6294 + PD->getName(),
6295 MethodTypesExt, ObjCTypes);
Owen Anderson08e25242009-07-27 22:29:56 +00006296 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanianda320092009-01-29 19:24:30 +00006297 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006298
Fariborz Jahanianda320092009-01-29 19:24:30 +00006299 if (Entry) {
6300 // Already created, fix the linkage and update the initializer.
Mike Stump286acbd2009-03-07 16:33:28 +00006301 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006302 Entry->setInitializer(Init);
6303 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006304 Entry =
Daniel Dunbar9c29bf52009-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 Jahanian09796d62009-01-31 02:43:27 +00006308 Entry->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006309 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanianda320092009-01-29 19:24:30 +00006310 Entry->setSection("__DATA,__datacoal_nt,coalesced");
John McCall50651b92012-03-30 21:29:05 +00006311
6312 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanianda320092009-01-29 19:24:30 +00006313 }
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00006314 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00006315 CGM.AddUsedGlobal(Entry);
6316
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00006317 // Use this protocol meta-data to build protocol list table in section
6318 // __DATA, __objc_protolist
Daniel Dunbar9c29bf52009-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 Jahanian09796d62009-01-31 02:43:27 +00006323 PTGV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006324 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbar0bf21992009-04-15 02:56:18 +00006325 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00006326 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00006327 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanianda320092009-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 Lattner5f9e2722011-07-23 10:55:15 +00006340CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006341 ObjCProtocolDecl::protocol_iterator begin,
6342 ObjCProtocolDecl::protocol_iterator end) {
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00006343 SmallVector<llvm::Constant *, 16> ProtocolRefs;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006344
Fariborz Jahanianda320092009-01-29 19:24:30 +00006345 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006346 if (begin == end)
Owen Andersonc9c88b42009-07-31 20:28:54 +00006347 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006348
Daniel Dunbar948e2582009-02-15 07:36:20 +00006349 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00006350 SmallString<256> TmpName;
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006351 Name.toVector(TmpName);
6352 llvm::GlobalVariable *GV =
6353 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006354 if (GV)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006355 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006356
Daniel Dunbar948e2582009-02-15 07:36:20 +00006357 for (; begin != end; ++begin)
6358 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
6359
Fariborz Jahanianda320092009-01-29 19:24:30 +00006360 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00006361 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006362 ObjCTypes.ProtocolnfABIPtrTy));
6363
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006364 llvm::Constant *Values[2];
Owen Andersona1cf15f2009-07-14 23:10:40 +00006365 Values[0] =
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006366 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006367 Values[1] =
Bill Wendling3964e622012-02-09 22:16:49 +00006368 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
6369 ProtocolRefs.size()),
6370 ProtocolRefs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006371
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006372 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Owen Anderson1c431b32009-07-08 19:05:04 +00006373 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanianda320092009-01-29 19:24:30 +00006374 llvm::GlobalValue::InternalLinkage,
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006375 Init, Name);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006376 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00006377 GV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006378 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Chris Lattnerad64e022009-07-17 23:57:13 +00006379 CGM.AddUsedGlobal(GV);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006380 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar948e2582009-02-15 07:36:20 +00006381 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006382}
6383
Fariborz Jahanian3819a0b2009-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 Kramer1d236ab2011-10-15 12:20:02 +00006393 llvm::Constant *Desc[3];
Owen Andersona1cf15f2009-07-14 23:10:40 +00006394 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006395 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
6396 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006397 Desc[1] = GetMethodVarType(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00006398 if (!Desc[1])
6399 return 0;
6400
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00006401 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00006402 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00006403 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006404}
Fariborz Jahanian45012a72009-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 Dunbar6bff2512009-08-03 17:06:42 +00006411///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00006412LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall506b57e2010-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 Jahaniancd285d02012-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 Dunbar97776872009-04-22 07:32:20 +00006424 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancd285d02012-02-20 22:42:22 +00006425 Offset);
Fariborz Jahanian45012a72009-02-03 00:09:52 +00006426}
6427
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00006428llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006429 CodeGen::CodeGenFunction &CGF,
6430 const ObjCInterfaceDecl *Interface,
6431 const ObjCIvarDecl *Ivar) {
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00006432 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00006433}
6434
John McCallb1e81442011-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 Dunbar6bff2512009-08-03 17:06:42 +00006441
John McCallb1e81442011-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 McCall944c8432011-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 McCallb1e81442011-05-13 23:16:18 +00006468 // Compute the actual arguments.
6469 CallArgList args;
6470
John McCall944c8432011-05-14 03:10:52 +00006471 // First argument: the receiver / super-call structure.
John McCallb1e81442011-05-13 23:16:18 +00006472 if (!isSuper)
John McCall944c8432011-05-14 03:10:52 +00006473 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
6474 args.add(RValue::get(arg0), arg0Type);
John McCallb1e81442011-05-13 23:16:18 +00006475
John McCall944c8432011-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 McCallb1e81442011-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 McCallde5d3c72012-02-17 03:33:10 +00006482 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCallb1e81442011-05-13 23:16:18 +00006483
John McCallcba681a2011-05-14 21:12:11 +00006484 NullReturnState nullReturn;
6485
John McCall944c8432011-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 McCallb1e81442011-05-13 23:16:18 +00006493 llvm::Constant *fn = 0;
6494 std::string messageRefName("\01l_");
John McCallde5d3c72012-02-17 03:33:10 +00006495 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
John McCallb1e81442011-05-13 23:16:18 +00006496 if (isSuper) {
6497 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
6498 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00006499 } else {
John McCallcba681a2011-05-14 21:12:11 +00006500 nullReturn.init(CGF, arg0);
John McCallb1e81442011-05-13 23:16:18 +00006501 fn = ObjCTypes.getMessageSendStretFixupFn();
6502 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00006503 }
John McCallb1e81442011-05-13 23:16:18 +00006504 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
6505 fn = ObjCTypes.getMessageSendFpretFixupFn();
6506 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stumpb3589f42009-07-30 22:28:39 +00006507 } else {
John McCallb1e81442011-05-13 23:16:18 +00006508 if (isSuper) {
6509 fn = ObjCTypes.getMessageSendSuper2FixupFn();
6510 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00006511 } else {
John McCallb1e81442011-05-13 23:16:18 +00006512 fn = ObjCTypes.getMessageSendFixupFn();
6513 messageRefName += "objc_msgSend_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00006514 }
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00006515 }
John McCallb1e81442011-05-13 23:16:18 +00006516 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
6517 messageRefName += '_';
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006518
John McCallb1e81442011-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 McCall944c8432011-05-14 03:10:52 +00006526 // Build the message ref structure.
John McCallb1e81442011-05-13 23:16:18 +00006527 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006528 llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
John McCallb1e81442011-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 Jahanian3c52d362012-01-30 23:39:30 +00006539
6540 bool requiresnullCheck = false;
David Blaikie4e4d0842012-03-11 07:00:24 +00006541 if (CGM.getLangOpts().ObjCAutoRefCount && method)
Fariborz Jahanian3c52d362012-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 McCallb1e81442011-05-13 23:16:18 +00006553 llvm::Value *mref =
6554 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
6555
John McCall944c8432011-05-14 03:10:52 +00006556 // Update the message ref argument.
John McCallb1e81442011-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 McCallde5d3c72012-02-17 03:33:10 +00006563 callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
John McCallb1e81442011-05-13 23:16:18 +00006564
John McCallde5d3c72012-02-17 03:33:10 +00006565 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Fariborz Jahanian3c52d362012-01-30 23:39:30 +00006566 return nullReturn.complete(CGF, result, resultType, formalArgs,
6567 requiresnullCheck ? method : 0);
Fariborz Jahanian46551122009-02-04 00:22:57 +00006568}
6569
6570/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbard6c93d72009-09-17 04:01:22 +00006571CodeGen::RValue
6572CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00006573 ReturnValueSlot Return,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00006574 QualType ResultType,
6575 Selector Sel,
6576 llvm::Value *Receiver,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00006577 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00006578 const ObjCInterfaceDecl *Class,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00006579 const ObjCMethodDecl *Method) {
John McCall944c8432011-05-14 03:10:52 +00006580 return isVTableDispatchedSelector(Sel)
6581 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006582 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00006583 false, CallArgs, Method)
6584 : EmitMessageSend(CGF, Return, ResultType,
6585 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006586 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00006587 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian46551122009-02-04 00:22:57 +00006588}
6589
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00006590llvm::GlobalVariable *
Fariborz Jahanian0f902942009-04-14 18:41:56 +00006591CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00006592 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
6593
Daniel Dunbardfff2302009-03-02 05:18:14 +00006594 if (!GV) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006595 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Anderson1c431b32009-07-08 19:05:04 +00006596 false, llvm::GlobalValue::ExternalLinkage,
6597 0, Name);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00006598 }
6599
6600 return GV;
6601}
6602
John McCallf85e1932011-06-15 23:02:42 +00006603llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CGBuilderTy &Builder,
6604 IdentifierInfo *II) {
6605 llvm::GlobalVariable *&Entry = ClassReferences[II];
6606
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006607 if (!Entry) {
John McCallf85e1932011-06-15 23:02:42 +00006608 std::string ClassName(getClassSymbolPrefix() + II->getName().str());
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00006609 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006610 Entry =
John McCallf85e1932011-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 Jahanian0e81f4b2009-02-05 20:41:40 +00006615 Entry->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006616 CGM.getDataLayout().getABITypeAlignment(
John McCallf85e1932011-06-15 23:02:42 +00006617 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00006618 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00006619 CGM.AddUsedGlobal(Entry);
Daniel Dunbar11394522009-04-18 08:51:00 +00006620 }
John McCallf85e1932011-06-15 23:02:42 +00006621
Benjamin Kramer578faa82011-09-27 21:06:10 +00006622 return Builder.CreateLoad(Entry);
Daniel Dunbar11394522009-04-18 08:51:00 +00006623}
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006624
John McCallf85e1932011-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 Dunbar11394522009-04-18 08:51:00 +00006636llvm::Value *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006637CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00006638 const ObjCInterfaceDecl *ID) {
6639 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006640
Daniel Dunbar11394522009-04-18 08:51:00 +00006641 if (!Entry) {
6642 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6643 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006644 Entry =
6645 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00006646 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006647 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00006648 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar11394522009-04-18 08:51:00 +00006649 Entry->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006650 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006651 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00006652 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00006653 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006654 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006655
Benjamin Kramer578faa82011-09-27 21:06:10 +00006656 return Builder.CreateLoad(Entry);
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006657}
6658
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006659/// EmitMetaClassRef - Return a Value * of the address of _class_t
6660/// meta-data
6661///
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006662llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
6663 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006664 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
6665 if (Entry)
Benjamin Kramer578faa82011-09-27 21:06:10 +00006666 return Builder.CreateLoad(Entry);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006667
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006668 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00006669 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006670 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00006671 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006672 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006673 MetaClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00006674 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006675 Entry->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006676 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006677 ObjCTypes.ClassnfABIPtrTy));
6678
Daniel Dunbar33af70f2009-04-15 19:03:14 +00006679 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00006680 CGM.AddUsedGlobal(Entry);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006681
Benjamin Kramer578faa82011-09-27 21:06:10 +00006682 return Builder.CreateLoad(Entry);
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006683}
6684
Fariborz Jahanian0e81f4b2009-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 Gregor0a0d2b12011-03-23 00:50:03 +00006689 if (ID->isWeakImported()) {
Fariborz Jahanian269f8bc2009-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 Jahanian0e81f4b2009-02-05 20:41:40 +00006695 return EmitClassRef(Builder, ID);
6696}
6697
Fariborz Jahanian7a06aae2009-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 McCallef072fd2010-05-22 01:48:05 +00006703 ReturnValueSlot Return,
Daniel Dunbar6bff2512009-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 Dunbard6c93d72009-09-17 04:01:22 +00006710 const CodeGen::CallArgList &CallArgs,
6711 const ObjCMethodDecl *Method) {
Fariborz Jahanian7a06aae2009-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 McCall604da292011-03-04 08:00:29 +00006716 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006717
Fariborz Jahanian7a06aae2009-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 Dunbar6bff2512009-08-03 17:06:42 +00006722
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006723 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00006724 llvm::Value *Target;
Fariborz Jahanianb9966bd2012-10-10 23:11:18 +00006725 if (IsClassMessage)
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00006726 Target = EmitMetaClassRef(CGF.Builder, Class);
Fariborz Jahanianb9966bd2012-10-10 23:11:18 +00006727 else
Daniel Dunbar11394522009-04-18 08:51:00 +00006728 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006729
Mike Stumpf5408fe2009-05-16 07:57:57 +00006730 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
6731 // ObjCTypes types.
Chris Lattner2acc6e32011-07-18 04:24:23 +00006732 llvm::Type *ClassTy =
Fariborz Jahanian7a06aae2009-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 Dunbar6bff2512009-08-03 17:06:42 +00006737
John McCall944c8432011-05-14 03:10:52 +00006738 return (isVTableDispatchedSelector(Sel))
6739 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006740 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00006741 true, CallArgs, Method)
6742 : EmitMessageSend(CGF, Return, ResultType,
6743 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006744 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00006745 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006746}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006747
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006748llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian03b29602010-06-17 19:56:20 +00006749 Selector Sel, bool lval) {
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006750 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006751
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006752 if (!Entry) {
Daniel Dunbar6bff2512009-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 Jahaniand0f8a8d2009-05-11 19:25:47 +00006760 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00006761 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006762 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006763
Fariborz Jahanian03b29602010-06-17 19:56:20 +00006764 if (lval)
6765 return Entry;
Pete Cooperb6d71142011-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 Jahanian26cc89f2009-02-11 20:51:17 +00006772}
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006773/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00006774/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006775///
6776void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00006777 llvm::Value *src,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00006778 llvm::Value *dst,
6779 llvm::Value *ivarOffset) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00006780 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006781 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00006782 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Jahanian3b8a6522009-03-13 00:42:52 +00006786 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6787 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006788 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6789 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00006790 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
6791 src, dst, ivarOffset);
Fariborz Jahanian6948aea2009-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 Dunbar6bff2512009-08-03 17:06:42 +00006799 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00006800 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00006801 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006802 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00006803 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Dunbar6bff2512009-08-03 17:06:42 +00006806 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00006807 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6808 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006809 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6810 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00006811 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006812 src, dst, "weakassign");
6813 return;
6814}
6815
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00006816void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006817 CodeGen::CodeGenFunction &CGF,
6818 llvm::Value *DestPtr,
6819 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00006820 llvm::Value *Size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00006821 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
6822 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00006823 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00006824 DestPtr, SrcPtr, Size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00006825 return;
6826}
6827
Fariborz Jahanian6948aea2009-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 Dunbar6bff2512009-08-03 17:06:42 +00006832 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00006833 llvm::Value *AddrWeakObj) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00006834 llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006835 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
6836 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00006837 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006838 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00006839 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6948aea2009-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 Stump1eb44332009-09-09 15:08:12 +00006847 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00006848 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006849 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00006850 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Jahanian3b8a6522009-03-13 00:42:52 +00006854 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6855 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006856 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6857 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00006858 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian6948aea2009-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 Jahanian021a7a62010-07-20 20:30:03 +00006867 llvm::Value *src, llvm::Value *dst,
6868 bool threadlocal) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00006869 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006870 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00006871 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-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 Jahanian3b8a6522009-03-13 00:42:52 +00006875 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6876 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006877 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6878 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-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 Jahanian6948aea2009-02-16 22:52:32 +00006885 return;
6886}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006887
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006888void
John McCallf1549f62010-07-06 01:34:17 +00006889CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6890 const ObjCAtSynchronizedStmt &S) {
David Chisnall05dc91b2011-03-25 17:46:35 +00006891 EmitAtSynchronizedStmt(CGF, S,
6892 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6893 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallf1549f62010-07-06 01:34:17 +00006894}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006895
John McCall5a180392010-07-24 00:37:23 +00006896llvm::Constant *
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00006897CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall5a180392010-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 McCallf1549f62010-07-06 01:34:17 +00006921void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6922 const ObjCAtTryStmt &S) {
David Chisnall05dc91b2011-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 Dunbar8ecbaf22009-02-24 07:47:38 +00006927}
6928
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006929/// EmitThrowStmt - Generate code for a throw statement.
6930void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6a3c70e2013-01-10 19:02:56 +00006931 const ObjCAtThrowStmt &S,
6932 bool ClearInsertionPoint) {
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006933 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall2b014d62011-10-01 10:32:24 +00006934 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer578faa82011-09-27 21:06:10 +00006935 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Jay Foad4c7d9f12011-07-15 08:37:34 +00006936 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall7ec404c2010-10-16 08:21:07 +00006937 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006938 } else {
Jay Foad4c7d9f12011-07-15 08:37:34 +00006939 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall7ec404c2010-10-16 08:21:07 +00006940 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006941 }
6942
John McCall7ec404c2010-10-16 08:21:07 +00006943 CGF.Builder.CreateUnreachable();
Fariborz Jahanian6a3c70e2013-01-10 19:02:56 +00006944 if (ClearInsertionPoint)
6945 CGF.Builder.ClearInsertionPoint();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006946}
Daniel Dunbare588b992009-03-01 04:46:24 +00006947
John McCall5a180392010-07-24 00:37:23 +00006948llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006949CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006950 bool ForDefinition) {
Daniel Dunbare588b992009-03-01 04:46:24 +00006951 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbare588b992009-03-01 04:46:24 +00006952
Daniel Dunbar8158a2f2009-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 Dunbar7e075cb2009-04-07 06:43:45 +00006958
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006959 // If this type (or a super class) has the __objc_exception__
6960 // attribute, emit an external reference.
Douglas Gregor68584ed2009-06-18 16:11:24 +00006961 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006962 return Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00006963 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006964 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006965 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006966 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006967 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006968 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006969
Daniel Dunbar8158a2f2009-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 Dunbar6ab187a2009-04-07 05:48:37 +00006973 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbare588b992009-03-01 04:46:24 +00006974 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006975 llvm::GlobalVariable *VTableGV =
Daniel Dunbare588b992009-03-01 04:46:24 +00006976 CGM.getModule().getGlobalVariable(VTableName);
6977 if (!VTableGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006978 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6979 false,
Daniel Dunbare588b992009-03-01 04:46:24 +00006980 llvm::GlobalValue::ExternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00006981 0, VTableName);
Daniel Dunbare588b992009-03-01 04:46:24 +00006982
Chris Lattner8b418682012-02-07 00:39:47 +00006983 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
Daniel Dunbare588b992009-03-01 04:46:24 +00006984
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006985 llvm::Constant *Values[] = {
6986 llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
6987 GetClassName(ID->getIdentifier()),
6988 GetClassGlobal(ClassName)
6989 };
Owen Andersona1cf15f2009-07-14 23:10:40 +00006990 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00006991 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbare588b992009-03-01 04:46:24 +00006992
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006993 if (Entry) {
6994 Entry->setInitializer(Init);
6995 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00006996 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006997 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006998 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006999 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00007000 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00007001 }
7002
David Blaikie4e4d0842012-03-11 07:00:24 +00007003 if (CGM.getLangOpts().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00007004 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Micah Villmow25a6a842012-10-08 16:25:52 +00007005 Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00007006 ObjCTypes.EHTypeTy));
Daniel Dunbar8158a2f2009-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 Dunbare588b992009-03-01 04:46:24 +00007014
7015 return Entry;
7016}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00007017
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00007018/* *** */
7019
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00007020CodeGen::CGObjCRuntime *
7021CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall260611a2012-06-20 06:18:46 +00007022 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7023 case ObjCRuntime::FragileMacOSX:
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00007024 return new CGObjCMac(CGM);
John McCall260611a2012-06-20 06:18:46 +00007025
7026 case ObjCRuntime::MacOSX:
7027 case ObjCRuntime::iOS:
7028 return new CGObjCNonFragileABIMac(CGM);
7029
David Chisnall11d3f4c2012-07-03 20:49:52 +00007030 case ObjCRuntime::GNUstep:
7031 case ObjCRuntime::GCC:
John McCallf7226fb2012-07-12 02:07:58 +00007032 case ObjCRuntime::ObjFW:
John McCall260611a2012-06-20 06:18:46 +00007033 llvm_unreachable("these runtimes are not Mac runtimes");
7034 }
7035 llvm_unreachable("bad runtime");
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00007036}