blob: 611fb384bdaf5f94ddbb00272dac7a31167ccc90 [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"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000015
Daniel Dunbar198bcb42010-03-31 01:09:11 +000016#include "CGRecordLayout.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000017#include "CodeGenModule.h"
Daniel Dunbarb7ec2462008-08-16 03:19:19 +000018#include "CodeGenFunction.h"
John McCalld16c2cf2011-02-08 08:22:06 +000019#include "CGBlocks.h"
John McCall36f893c2011-01-28 11:13:47 +000020#include "CGCleanup.h"
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000021#include "clang/AST/ASTContext.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000022#include "clang/AST/Decl.h"
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000023#include "clang/AST/DeclObjC.h"
Anders Carlsson19cc4ab2009-07-18 19:43:29 +000024#include "clang/AST/RecordLayout.h"
Chris Lattner16f00492009-04-26 01:32:48 +000025#include "clang/AST/StmtObjC.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000026#include "clang/Basic/LangOptions.h"
Chandler Carruth06057ce2010-06-15 23:19:56 +000027#include "clang/Frontend/CodeGenOptions.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000028
John McCall87bb5822010-07-31 23:20:56 +000029#include "llvm/InlineAsm.h"
30#include "llvm/IntrinsicInst.h"
Owen Anderson69243822009-07-13 04:10:07 +000031#include "llvm/LLVMContext.h"
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000032#include "llvm/Module.h"
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +000033#include "llvm/ADT/DenseSet.h"
Daniel Dunbar33063492009-09-07 00:20:42 +000034#include "llvm/ADT/SetVector.h"
35#include "llvm/ADT/SmallString.h"
Fariborz Jahanian191dcd72009-12-12 21:26:21 +000036#include "llvm/ADT/SmallPtrSet.h"
John McCall8e3f8612010-07-13 22:12:14 +000037#include "llvm/Support/CallSite.h"
Daniel Dunbar33063492009-09-07 00:20:42 +000038#include "llvm/Support/raw_ostream.h"
Micah Villmow25a6a842012-10-08 16:25:52 +000039#include "llvm/DataLayout.h"
Torok Edwinf42e4a62009-08-24 13:25:12 +000040#include <cstdio>
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000041
42using namespace clang;
Daniel Dunbar46f45b92008-09-09 01:06:48 +000043using namespace CodeGen;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000044
45namespace {
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000046
Daniel Dunbar6bff2512009-08-03 17:06:42 +000047// FIXME: We should find a nicer way to make the labels for metadata, string
48// concatenation is lame.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000049
Fariborz Jahanianee0af742009-01-21 22:04:16 +000050class ObjCCommonTypesHelper {
Owen Andersona1cf15f2009-07-14 23:10:40 +000051protected:
52 llvm::LLVMContext &VMContext;
Daniel Dunbar6bff2512009-08-03 17:06:42 +000053
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000054private:
John McCall0774cb82011-05-15 01:53:33 +000055 // The types of these functions don't really matter because we
56 // should always bitcast before calling them.
57
58 /// id objc_msgSend (id, SEL, ...)
59 ///
60 /// The default messenger, used for sends whose ABI is unchanged from
61 /// the all-integer/pointer case.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000062 llvm::Constant *getMessageSendFn() const {
John McCallf85e1932011-06-15 23:02:42 +000063 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
64 // be called a lot.
Chris Lattner9cbe4f02011-07-09 17:41:47 +000065 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall0774cb82011-05-15 01:53:33 +000066 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
67 params, true),
John McCallf85e1932011-06-15 23:02:42 +000068 "objc_msgSend",
Bill Wendling50e6b182012-10-15 04:47:45 +000069 llvm::Attributes::get(CGM.getLLVMContext(),
Bill Wendlinga6375562012-10-16 05:23:44 +000070 llvm::Attributes::NonLazyBind));
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000071 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000072
John McCall0774cb82011-05-15 01:53:33 +000073 /// void objc_msgSend_stret (id, SEL, ...)
74 ///
75 /// The messenger used when the return value is an aggregate returned
76 /// by indirect reference in the first argument, and therefore the
77 /// self and selector parameters are shifted over by one.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000078 llvm::Constant *getMessageSendStretFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +000079 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall0774cb82011-05-15 01:53:33 +000080 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
81 params, true),
82 "objc_msgSend_stret");
Daniel Dunbar6bff2512009-08-03 17:06:42 +000083
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000084 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000085
John McCall0774cb82011-05-15 01:53:33 +000086 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
87 ///
88 /// The messenger used when the return value is returned on the x87
89 /// floating-point stack; without a special entrypoint, the nil case
90 /// would be unbalanced.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000091 llvm::Constant *getMessageSendFpretFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +000092 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
Chris Lattner8b418682012-02-07 00:39:47 +000093 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy,
94 params, true),
John McCall0774cb82011-05-15 01:53:33 +000095 "objc_msgSend_fpret");
Daniel Dunbar6bff2512009-08-03 17:06:42 +000096
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000097 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000098
Anders Carlssoneea64802011-10-31 16:27:11 +000099 /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
100 ///
101 /// The messenger used when the return value is returned in two values on the
102 /// x87 floating point stack; without a special entrypoint, the nil case
103 /// would be unbalanced. Only used on 64-bit X86.
104 llvm::Constant *getMessageSendFp2retFn() const {
105 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
106 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
107 llvm::Type *resultType =
108 llvm::StructType::get(longDoubleType, longDoubleType, NULL);
109
110 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
111 params, true),
112 "objc_msgSend_fp2ret");
113 }
114
John McCall0774cb82011-05-15 01:53:33 +0000115 /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
116 ///
117 /// The messenger used for super calls, which have different dispatch
118 /// semantics. The class passed is the superclass of the current
119 /// class.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000120 llvm::Constant *getMessageSendSuperFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000121 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000122 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000123 params, true),
124 "objc_msgSendSuper");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000125 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000126
John McCall0774cb82011-05-15 01:53:33 +0000127 /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
128 ///
129 /// A slightly different messenger used for super calls. The class
130 /// passed is the current class.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000131 llvm::Constant *getMessageSendSuperFn2() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000132 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000133 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000134 params, true),
135 "objc_msgSendSuper2");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000136 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000137
John McCall0774cb82011-05-15 01:53:33 +0000138 /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
139 /// SEL op, ...)
140 ///
141 /// The messenger used for super calls which return an aggregate indirectly.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000142 llvm::Constant *getMessageSendSuperStretFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000143 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000144 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000145 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000146 "objc_msgSendSuper_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000147 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000148
John McCall0774cb82011-05-15 01:53:33 +0000149 /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
150 /// SEL op, ...)
151 ///
152 /// objc_msgSendSuper_stret with the super2 semantics.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000153 llvm::Constant *getMessageSendSuperStretFn2() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000154 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000155 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000156 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000157 "objc_msgSendSuper2_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000158 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000159
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000160 llvm::Constant *getMessageSendSuperFpretFn() const {
161 // There is no objc_msgSendSuper_fpret? How can that work?
162 return getMessageSendSuperFn();
163 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000164
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000165 llvm::Constant *getMessageSendSuperFpretFn2() const {
166 // There is no objc_msgSendSuper_fpret? How can that work?
167 return getMessageSendSuperFn2();
168 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000169
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000170protected:
171 CodeGen::CodeGenModule &CGM;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000172
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000173public:
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000174 llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Bob Wilsondc8dab62011-11-30 01:57:58 +0000175 llvm::Type *Int8PtrTy, *Int8PtrPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000176
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000177 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000178 llvm::Type *ObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000179
Fariborz Jahanian6d657c42008-11-18 20:18:11 +0000180 /// PtrObjectPtrTy - LLVM type for id *
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000181 llvm::Type *PtrObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000182
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000183 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000184 llvm::Type *SelectorPtrTy;
Douglas Gregor4c86fdb2012-01-17 18:36:30 +0000185
186private:
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000187 /// ProtocolPtrTy - LLVM type for external protocol handles
188 /// (typeof(Protocol))
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000189 llvm::Type *ExternalProtocolPtrTy;
Douglas Gregor4c86fdb2012-01-17 18:36:30 +0000190
191public:
192 llvm::Type *getExternalProtocolPtrTy() {
193 if (!ExternalProtocolPtrTy) {
194 // FIXME: It would be nice to unify this with the opaque type, so that the
195 // IR comes out a bit cleaner.
196 CodeGen::CodeGenTypes &Types = CGM.getTypes();
197 ASTContext &Ctx = CGM.getContext();
198 llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
199 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
200 }
201
202 return ExternalProtocolPtrTy;
203 }
204
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000205 // SuperCTy - clang type for struct objc_super.
206 QualType SuperCTy;
207 // SuperPtrCTy - clang type for struct objc_super *.
208 QualType SuperPtrCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000209
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000210 /// SuperTy - LLVM type for struct objc_super.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000211 llvm::StructType *SuperTy;
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000212 /// SuperPtrTy - LLVM type for struct objc_super *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000213 llvm::Type *SuperPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000214
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000215 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
216 /// in GCC parlance).
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000217 llvm::StructType *PropertyTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000218
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000219 /// PropertyListTy - LLVM type for struct objc_property_list
220 /// (_prop_list_t in GCC parlance).
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000221 llvm::StructType *PropertyListTy;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000222 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000223 llvm::Type *PropertyListPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000224
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000225 // MethodTy - LLVM type for struct objc_method.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000226 llvm::StructType *MethodTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000227
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000228 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000229 llvm::Type *CacheTy;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000230 /// CachePtrTy - LLVM type for struct objc_cache *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000231 llvm::Type *CachePtrTy;
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +0000232
Chris Lattner72db6c32009-04-22 02:44:54 +0000233 llvm::Constant *getGetPropertyFn() {
234 CodeGen::CodeGenTypes &Types = CGM.getTypes();
235 ASTContext &Ctx = CGM.getContext();
236 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
Chris Lattner5f9e2722011-07-23 10:55:15 +0000237 SmallVector<CanQualType,4> Params;
John McCallead608a2010-02-26 00:48:12 +0000238 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
239 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattner72db6c32009-04-22 02:44:54 +0000240 Params.push_back(IdType);
241 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000242 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000243 Params.push_back(Ctx.BoolTy);
Chris Lattner2acc6e32011-07-18 04:24:23 +0000244 llvm::FunctionType *FTy =
John McCall0f3d0972012-07-07 06:41:13 +0000245 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(IdType, Params,
246 FunctionType::ExtInfo(),
247 RequiredArgs::All));
Chris Lattner72db6c32009-04-22 02:44:54 +0000248 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
249 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000250
Chris Lattner72db6c32009-04-22 02:44:54 +0000251 llvm::Constant *getSetPropertyFn() {
252 CodeGen::CodeGenTypes &Types = CGM.getTypes();
253 ASTContext &Ctx = CGM.getContext();
254 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
Chris Lattner5f9e2722011-07-23 10:55:15 +0000255 SmallVector<CanQualType,6> Params;
John McCallead608a2010-02-26 00:48:12 +0000256 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
257 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattner72db6c32009-04-22 02:44:54 +0000258 Params.push_back(IdType);
259 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000260 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000261 Params.push_back(IdType);
262 Params.push_back(Ctx.BoolTy);
263 Params.push_back(Ctx.BoolTy);
Chris Lattner2acc6e32011-07-18 04:24:23 +0000264 llvm::FunctionType *FTy =
John McCall0f3d0972012-07-07 06:41:13 +0000265 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
266 FunctionType::ExtInfo(),
267 RequiredArgs::All));
Chris Lattner72db6c32009-04-22 02:44:54 +0000268 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
269 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000270
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000271 llvm::Constant *getOptimizedSetPropertyFn(bool atomic, bool copy) {
272 CodeGen::CodeGenTypes &Types = CGM.getTypes();
273 ASTContext &Ctx = CGM.getContext();
274 // void objc_setProperty_atomic(id self, SEL _cmd,
275 // id newValue, ptrdiff_t offset);
276 // void objc_setProperty_nonatomic(id self, SEL _cmd,
277 // id newValue, ptrdiff_t offset);
278 // void objc_setProperty_atomic_copy(id self, SEL _cmd,
279 // id newValue, ptrdiff_t offset);
280 // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
281 // id newValue, ptrdiff_t offset);
282
283 SmallVector<CanQualType,4> Params;
284 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
285 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
286 Params.push_back(IdType);
287 Params.push_back(SelType);
288 Params.push_back(IdType);
289 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
290 llvm::FunctionType *FTy =
John McCall0f3d0972012-07-07 06:41:13 +0000291 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
292 FunctionType::ExtInfo(),
293 RequiredArgs::All));
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000294 const char *name;
295 if (atomic && copy)
296 name = "objc_setProperty_atomic_copy";
297 else if (atomic && !copy)
298 name = "objc_setProperty_atomic";
299 else if (!atomic && copy)
300 name = "objc_setProperty_nonatomic_copy";
301 else
302 name = "objc_setProperty_nonatomic";
303
304 return CGM.CreateRuntimeFunction(FTy, name);
305 }
Fariborz Jahanian6cc59062010-04-12 18:18:10 +0000306
307 llvm::Constant *getCopyStructFn() {
308 CodeGen::CodeGenTypes &Types = CGM.getTypes();
309 ASTContext &Ctx = CGM.getContext();
310 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
Chris Lattner5f9e2722011-07-23 10:55:15 +0000311 SmallVector<CanQualType,5> Params;
Fariborz Jahanian6cc59062010-04-12 18:18:10 +0000312 Params.push_back(Ctx.VoidPtrTy);
313 Params.push_back(Ctx.VoidPtrTy);
314 Params.push_back(Ctx.LongTy);
315 Params.push_back(Ctx.BoolTy);
316 Params.push_back(Ctx.BoolTy);
Chris Lattner2acc6e32011-07-18 04:24:23 +0000317 llvm::FunctionType *FTy =
John McCall0f3d0972012-07-07 06:41:13 +0000318 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
319 FunctionType::ExtInfo(),
320 RequiredArgs::All));
Fariborz Jahanian6cc59062010-04-12 18:18:10 +0000321 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
322 }
323
Fariborz Jahaniane3173022012-01-06 18:07:23 +0000324 /// This routine declares and returns address of:
325 /// void objc_copyCppObjectAtomic(
326 /// void *dest, const void *src,
327 /// void (*copyHelper) (void *dest, const void *source));
328 llvm::Constant *getCppAtomicObjectFunction() {
329 CodeGen::CodeGenTypes &Types = CGM.getTypes();
330 ASTContext &Ctx = CGM.getContext();
331 /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper);
332 SmallVector<CanQualType,3> Params;
333 Params.push_back(Ctx.VoidPtrTy);
334 Params.push_back(Ctx.VoidPtrTy);
335 Params.push_back(Ctx.VoidPtrTy);
336 llvm::FunctionType *FTy =
John McCall0f3d0972012-07-07 06:41:13 +0000337 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
338 FunctionType::ExtInfo(),
339 RequiredArgs::All));
Fariborz Jahaniane3173022012-01-06 18:07:23 +0000340 return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
341 }
342
Chris Lattner72db6c32009-04-22 02:44:54 +0000343 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000344 CodeGen::CodeGenTypes &Types = CGM.getTypes();
345 ASTContext &Ctx = CGM.getContext();
Chris Lattner72db6c32009-04-22 02:44:54 +0000346 // void objc_enumerationMutation (id)
Chris Lattner5f9e2722011-07-23 10:55:15 +0000347 SmallVector<CanQualType,1> Params;
John McCallead608a2010-02-26 00:48:12 +0000348 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2acc6e32011-07-18 04:24:23 +0000349 llvm::FunctionType *FTy =
John McCall0f3d0972012-07-07 06:41:13 +0000350 Types.GetFunctionType(Types.arrangeLLVMFunctionInfo(Ctx.VoidTy, Params,
John McCallde5d3c72012-02-17 03:33:10 +0000351 FunctionType::ExtInfo(),
352 RequiredArgs::All));
Chris Lattner72db6c32009-04-22 02:44:54 +0000353 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
354 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000355
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000356 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattner72db6c32009-04-22 02:44:54 +0000357 llvm::Constant *getGcReadWeakFn() {
358 // id objc_read_weak (id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000359 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000360 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000361 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000362 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000363 }
364
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000365 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner96508e12009-04-17 22:12:36 +0000366 llvm::Constant *getGcAssignWeakFn() {
367 // id objc_assign_weak (id, id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000368 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner96508e12009-04-17 22:12:36 +0000369 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000370 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner96508e12009-04-17 22:12:36 +0000371 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
372 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000373
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000374 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000375 llvm::Constant *getGcAssignGlobalFn() {
376 // id objc_assign_global(id, id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000377 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000378 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000379 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000380 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
381 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000382
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000383 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
384 llvm::Constant *getGcAssignThreadLocalFn() {
385 // id objc_assign_threadlocal(id src, id * dest)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000386 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000387 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000388 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000389 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
390 }
391
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000392 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000393 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +0000394 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000395 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
396 CGM.PtrDiffTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000397 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000398 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000399 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
400 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000401
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000402 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
403 llvm::Constant *GcMemmoveCollectableFn() {
404 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000405 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall0774cb82011-05-15 01:53:33 +0000406 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000407 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
408 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000409
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000410 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000411 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000412 // id objc_assign_strongCast(id, id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000413 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000414 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000415 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000416 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
417 }
Anders Carlssonf57c5b22009-02-16 22:59:18 +0000418
419 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000420 llvm::Constant *getExceptionThrowFn() {
421 // void objc_exception_throw(id)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000422 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerbbccd612009-04-22 02:38:11 +0000423 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000424 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000425 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
426 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000427
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000428 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
429 llvm::Constant *getExceptionRethrowFn() {
430 // void objc_exception_rethrow(void)
John McCall0774cb82011-05-15 01:53:33 +0000431 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000432 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
433 }
434
Daniel Dunbar1c566672009-02-24 01:43:46 +0000435 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000436 llvm::Constant *getSyncEnterFn() {
Aaron Ballman2d234d732012-09-06 16:44:16 +0000437 // int objc_sync_enter (id)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000438 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000439 llvm::FunctionType *FTy =
Aaron Ballman2d234d732012-09-06 16:44:16 +0000440 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000441 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
442 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000443
Daniel Dunbar1c566672009-02-24 01:43:46 +0000444 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000445 llvm::Constant *getSyncExitFn() {
Aaron Ballman2d234d732012-09-06 16:44:16 +0000446 // int objc_sync_exit (id)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000447 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerbbccd612009-04-22 02:38:11 +0000448 llvm::FunctionType *FTy =
Aaron Ballman2d234d732012-09-06 16:44:16 +0000449 llvm::FunctionType::get(CGM.IntTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000450 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
451 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000452
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000453 llvm::Constant *getSendFn(bool IsSuper) const {
454 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
455 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000456
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000457 llvm::Constant *getSendFn2(bool IsSuper) const {
458 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
459 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000460
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000461 llvm::Constant *getSendStretFn(bool IsSuper) const {
462 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
463 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000464
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000465 llvm::Constant *getSendStretFn2(bool IsSuper) const {
466 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
467 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000468
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000469 llvm::Constant *getSendFpretFn(bool IsSuper) const {
470 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
471 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000472
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000473 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
474 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
475 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000476
Anders Carlssoneea64802011-10-31 16:27:11 +0000477 llvm::Constant *getSendFp2retFn(bool IsSuper) const {
478 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
479 }
480
481 llvm::Constant *getSendFp2RetFn2(bool IsSuper) const {
482 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
483 }
484
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000485 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
486 ~ObjCCommonTypesHelper(){}
487};
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000488
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000489/// ObjCTypesHelper - Helper class that encapsulates lazy
490/// construction of varies types used during ObjC generation.
491class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000492public:
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000493 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000494 llvm::StructType *SymtabTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000495 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000496 llvm::Type *SymtabPtrTy;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000497 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000498 llvm::StructType *ModuleTy;
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000499
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000500 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000501 llvm::StructType *ProtocolTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000502 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000503 llvm::Type *ProtocolPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000504 /// ProtocolExtensionTy - LLVM type for struct
505 /// objc_protocol_extension.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000506 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000507 /// ProtocolExtensionTy - LLVM type for struct
508 /// objc_protocol_extension *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000509 llvm::Type *ProtocolExtensionPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000510 /// MethodDescriptionTy - LLVM type for struct
511 /// objc_method_description.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000512 llvm::StructType *MethodDescriptionTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000513 /// MethodDescriptionListTy - LLVM type for struct
514 /// objc_method_description_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000515 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000516 /// MethodDescriptionListPtrTy - LLVM type for struct
517 /// objc_method_description_list *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000518 llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000519 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000520 llvm::StructType *ProtocolListTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000521 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000522 llvm::Type *ProtocolListPtrTy;
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000523 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000524 llvm::StructType *CategoryTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000525 /// ClassTy - LLVM type for struct objc_class.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000526 llvm::StructType *ClassTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000527 /// ClassPtrTy - LLVM type for struct objc_class *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000528 llvm::Type *ClassPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000529 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000530 llvm::StructType *ClassExtensionTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000531 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000532 llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000533 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000534 llvm::StructType *IvarTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000535 /// IvarListTy - LLVM type for struct objc_ivar_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000536 llvm::Type *IvarListTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000537 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000538 llvm::Type *IvarListPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000539 /// MethodListTy - LLVM type for struct objc_method_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000540 llvm::Type *MethodListTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000541 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000542 llvm::Type *MethodListPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000543
Anders Carlsson124526b2008-09-09 10:10:21 +0000544 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000545 llvm::Type *ExceptionDataTy;
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +0000546
Anders Carlsson124526b2008-09-09 10:10:21 +0000547 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000548 llvm::Constant *getExceptionTryEnterFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000549 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000550 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000551 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000552 "objc_exception_try_enter");
Chris Lattner34b02a12009-04-22 02:26:14 +0000553 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000554
555 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000556 llvm::Constant *getExceptionTryExitFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000557 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000558 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000559 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000560 "objc_exception_try_exit");
Chris Lattner34b02a12009-04-22 02:26:14 +0000561 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000562
563 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000564 llvm::Constant *getExceptionExtractFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000565 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000566 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000567 params, false),
Chris Lattner34b02a12009-04-22 02:26:14 +0000568 "objc_exception_extract");
Chris Lattner34b02a12009-04-22 02:26:14 +0000569 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000570
Anders Carlsson124526b2008-09-09 10:10:21 +0000571 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000572 llvm::Constant *getExceptionMatchFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000573 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000574 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000575 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000576 "objc_exception_match");
577
Chris Lattner34b02a12009-04-22 02:26:14 +0000578 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000579
Anders Carlsson124526b2008-09-09 10:10:21 +0000580 /// SetJmpFn - LLVM _setjmp function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000581 llvm::Constant *getSetJmpFn() {
John McCall0774cb82011-05-15 01:53:33 +0000582 // This is specifically the prototype for x86.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000583 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
John McCall0774cb82011-05-15 01:53:33 +0000584 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
585 params, false),
Bill Wendlinga9e269e2011-11-29 00:10:10 +0000586 "_setjmp",
Bill Wendling50e6b182012-10-15 04:47:45 +0000587 llvm::Attributes::get(CGM.getLLVMContext(),
Bill Wendlinga6375562012-10-16 05:23:44 +0000588 llvm::Attributes::NonLazyBind));
Chris Lattner34b02a12009-04-22 02:26:14 +0000589 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000590
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000591public:
592 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000593 ~ObjCTypesHelper() {}
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000594};
595
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000596/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000597/// modern abi
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000598class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000599public:
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000600
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000601 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000602 llvm::StructType *MethodListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000603
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000604 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000605 llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000606
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000607 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000608 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000609
Daniel Dunbar948e2582009-02-15 07:36:20 +0000610 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000611 llvm::Type *ProtocolnfABIPtrTy;
Daniel Dunbar948e2582009-02-15 07:36:20 +0000612
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000613 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000614 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000615
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000616 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000617 llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000618
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000619 // ClassnfABITy - LLVM for struct _class_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000620 llvm::StructType *ClassnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000621
Fariborz Jahanianaa23b572009-01-23 23:53:38 +0000622 // ClassnfABIPtrTy - LLVM for struct _class_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000623 llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000624
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000625 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000626 llvm::StructType *IvarnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000627
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000628 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000629 llvm::StructType *IvarListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000630
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000631 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000632 llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000633
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000634 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000635 llvm::StructType *ClassRonfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000636
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000637 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000638 llvm::Type *ImpnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000639
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000640 // CategorynfABITy - LLVM for struct _category_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000641 llvm::StructType *CategorynfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000642
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000643 // New types for nonfragile abi messaging.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000644
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000645 // MessageRefTy - LLVM for:
646 // struct _message_ref_t {
647 // IMP messenger;
648 // SEL name;
649 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000650 llvm::StructType *MessageRefTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000651 // MessageRefCTy - clang type for struct _message_ref_t
652 QualType MessageRefCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000653
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000654 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000655 llvm::Type *MessageRefPtrTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000656 // MessageRefCPtrTy - clang type for struct _message_ref_t*
657 QualType MessageRefCPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000658
Fariborz Jahanianef163782009-02-05 01:13:09 +0000659 // MessengerTy - Type of the messenger (shown as IMP above)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000660 llvm::FunctionType *MessengerTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000661
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000662 // SuperMessageRefTy - LLVM for:
663 // struct _super_message_ref_t {
664 // SUPER_IMP messenger;
665 // SEL name;
666 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000667 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000668
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000669 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000670 llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000671
Chris Lattner1c02f862009-04-22 02:53:24 +0000672 llvm::Constant *getMessageSendFixupFn() {
673 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000674 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000675 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000676 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000677 "objc_msgSend_fixup");
678 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000679
Chris Lattner1c02f862009-04-22 02:53:24 +0000680 llvm::Constant *getMessageSendFpretFixupFn() {
681 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000682 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000683 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000684 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000685 "objc_msgSend_fpret_fixup");
686 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000687
Chris Lattner1c02f862009-04-22 02:53:24 +0000688 llvm::Constant *getMessageSendStretFixupFn() {
689 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000690 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000691 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000692 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000693 "objc_msgSend_stret_fixup");
694 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000695
Chris Lattner1c02f862009-04-22 02:53:24 +0000696 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000697 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000698 // struct _super_message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000699 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000700 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000701 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000702 "objc_msgSendSuper2_fixup");
703 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000704
Chris Lattner1c02f862009-04-22 02:53:24 +0000705 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000706 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000707 // struct _super_message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000708 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000709 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000710 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000711 "objc_msgSendSuper2_stret_fixup");
712 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000713
Chris Lattner8a569112009-04-22 02:15:23 +0000714 llvm::Constant *getObjCEndCatchFn() {
John McCall0774cb82011-05-15 01:53:33 +0000715 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattner8a569112009-04-22 02:15:23 +0000716 "objc_end_catch");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000717
Chris Lattner8a569112009-04-22 02:15:23 +0000718 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000719
Chris Lattner8a569112009-04-22 02:15:23 +0000720 llvm::Constant *getObjCBeginCatchFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000721 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000722 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000723 params, false),
Chris Lattner8a569112009-04-22 02:15:23 +0000724 "objc_begin_catch");
725 }
Daniel Dunbare588b992009-03-01 04:46:24 +0000726
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000727 llvm::StructType *EHTypeTy;
728 llvm::Type *EHTypePtrTy;
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +0000729
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000730 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
731 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000732};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000733
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000734class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000735public:
736 // FIXME - accessibility
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000737 class GC_IVAR {
Fariborz Jahanian820e0202009-03-11 00:07:04 +0000738 public:
Eli Friedmane5b46662012-11-06 22:15:52 +0000739 unsigned ivar_bytepos;
740 unsigned ivar_size;
741 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000742 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar0941b492009-04-23 01:29:05 +0000743
744 // Allow sorting based on byte pos.
745 bool operator<(const GC_IVAR &b) const {
746 return ivar_bytepos < b.ivar_bytepos;
747 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000748 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000749
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000750 class SKIP_SCAN {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000751 public:
752 unsigned skip;
753 unsigned scan;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000754 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000755 : skip(_skip), scan(_scan) {}
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000756 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000757
Fariborz Jahaniane11dba82012-10-25 21:15:04 +0000758 /// opcode for captured block variables layout 'instructions'.
759 /// In the following descriptions, 'I' is the value of the immediate field.
760 /// (field following the opcode).
761 ///
762 enum BLOCK_LAYOUT_OPCODE {
763 /// An operator which affects how the following layout should be
764 /// interpreted.
765 /// I == 0: Halt interpretation and treat everything else as
766 /// a non-pointer. Note that this instruction is equal
767 /// to '\0'.
768 /// I != 0: Currently unused.
769 BLOCK_LAYOUT_OPERATOR = 0,
770
771 /// The next I+1 bytes do not contain a value of object pointer type.
772 /// Note that this can leave the stream unaligned, meaning that
773 /// subsequent word-size instructions do not begin at a multiple of
774 /// the pointer size.
775 BLOCK_LAYOUT_NON_OBJECT_BYTES = 1,
776
777 /// The next I+1 words do not contain a value of object pointer type.
778 /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
779 /// when the required skip quantity is a multiple of the pointer size.
780 BLOCK_LAYOUT_NON_OBJECT_WORDS = 2,
781
782 /// The next I+1 words are __strong pointers to Objective-C
783 /// objects or blocks.
784 BLOCK_LAYOUT_STRONG = 3,
785
786 /// The next I+1 words are pointers to __block variables.
787 BLOCK_LAYOUT_BYREF = 4,
788
789 /// The next I+1 words are __weak pointers to Objective-C
790 /// objects or blocks.
791 BLOCK_LAYOUT_WEAK = 5,
792
793 /// The next I+1 words are __unsafe_unretained pointers to
794 /// Objective-C objects or blocks.
795 BLOCK_LAYOUT_UNRETAINED = 6
796
797 /// The next I+1 words are block or object pointers with some
798 /// as-yet-unspecified ownership semantics. If we add more
799 /// flavors of ownership semantics, values will be taken from
800 /// this range.
801 ///
802 /// This is included so that older tools can at least continue
803 /// processing the layout past such things.
804 //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,
805
806 /// All other opcodes are reserved. Halt interpretation and
807 /// treat everything else as opaque.
808 };
809
810 class RUN_SKIP {
811 public:
812 enum BLOCK_LAYOUT_OPCODE opcode;
Fariborz Jahanian1da01d62012-11-07 20:00:32 +0000813 CharUnits block_var_bytepos;
814 CharUnits block_var_size;
Fariborz Jahaniane11dba82012-10-25 21:15:04 +0000815 RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +0000816 CharUnits BytePos = CharUnits::Zero(),
817 CharUnits Size = CharUnits::Zero())
Fariborz Jahanianc46b4352012-10-27 21:10:38 +0000818 : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
Fariborz Jahaniane11dba82012-10-25 21:15:04 +0000819
820 // Allow sorting based on byte pos.
821 bool operator<(const RUN_SKIP &b) const {
822 return block_var_bytepos < b.block_var_bytepos;
823 }
824 };
825
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000826protected:
Owen Anderson69243822009-07-13 04:10:07 +0000827 llvm::LLVMContext &VMContext;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000828 // FIXME! May not be needing this after all.
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000829 unsigned ObjCABI;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000830
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000831 // gc ivar layout bitmap calculation helper caches.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000832 SmallVector<GC_IVAR, 16> SkipIvars;
833 SmallVector<GC_IVAR, 16> IvarsInfo;
Fariborz Jahaniane11dba82012-10-25 21:15:04 +0000834
835 // arc/mrr layout of captured block literal variables.
836 SmallVector<RUN_SKIP, 16> RunSkipBlockVars;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000837
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000838 /// LazySymbols - Symbols to generate a lazy reference for. See
839 /// DefinedSymbols and FinishModule().
Daniel Dunbar33063492009-09-07 00:20:42 +0000840 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000841
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000842 /// DefinedSymbols - External symbols which are defined by this
843 /// module. The symbols in this list and LazySymbols are used to add
844 /// special linker symbols which ensure that Objective-C modules are
845 /// linked properly.
Daniel Dunbar33063492009-09-07 00:20:42 +0000846 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000847
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000848 /// ClassNames - uniqued class names.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000849 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000850
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000851 /// MethodVarNames - uniqued method variable names.
852 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000853
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +0000854 /// DefinedCategoryNames - list of category names in form Class_Category.
855 llvm::SetVector<std::string> DefinedCategoryNames;
856
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000857 /// MethodVarTypes - uniqued method type signatures. We have to use
858 /// a StringMap here because have no other unique reference.
859 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000860
Daniel Dunbarc45ef602008-08-26 21:51:14 +0000861 /// MethodDefinitions - map of methods which have been defined in
862 /// this translation unit.
863 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000864
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000865 /// PropertyNames - uniqued method variable names.
866 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000867
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000868 /// ClassReferences - uniqued class references.
869 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000870
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000871 /// SelectorReferences - uniqued selector references.
872 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000873
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000874 /// Protocols - Protocols for which an objc_protocol structure has
875 /// been emitted. Forward declarations are handled by creating an
876 /// empty structure whose initializer is filled in when/if defined.
877 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000878
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000879 /// DefinedProtocols - Protocols which have actually been
880 /// defined. We should not need this, see FIXME in GenerateProtocol.
881 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000882
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000883 /// DefinedClasses - List of defined classes.
Bill Wendling1e01ac42012-02-07 09:40:07 +0000884 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedClasses;
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000885
886 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
Bill Wendling1e01ac42012-02-07 09:40:07 +0000887 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyClasses;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000888
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000889 /// DefinedCategories - List of defined categories.
Bill Wendling1e01ac42012-02-07 09:40:07 +0000890 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000891
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000892 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
Bill Wendling1e01ac42012-02-07 09:40:07 +0000893 llvm::SmallVector<llvm::GlobalValue*, 16> DefinedNonLazyCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000894
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000895 /// GetNameForMethod - Return a name for the given method.
896 /// \param[out] NameOut - The return value.
897 void GetNameForMethod(const ObjCMethodDecl *OMD,
898 const ObjCContainerDecl *CD,
Chris Lattner5f9e2722011-07-23 10:55:15 +0000899 SmallVectorImpl<char> &NameOut);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000900
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000901 /// GetMethodVarName - Return a unique constant for the given
902 /// selector's name. The return value has type char *.
903 llvm::Constant *GetMethodVarName(Selector Sel);
904 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000905
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000906 /// GetMethodVarType - Return a unique constant for the given
Bob Wilsondc8dab62011-11-30 01:57:58 +0000907 /// method's type encoding string. The return value has type char *.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000908
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000909 // FIXME: This is a horrible name.
Bob Wilsondc8dab62011-11-30 01:57:58 +0000910 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
911 bool Extended = false);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +0000912 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000913
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000914 /// GetPropertyName - Return a unique constant for the given
915 /// name. The return value has type char *.
916 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000917
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000918 // FIXME: This can be dropped once string functions are unified.
919 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
920 const Decl *Container);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000921
Fariborz Jahanian058a1b72009-01-24 20:21:50 +0000922 /// GetClassName - Return a unique constant for the given selector's
923 /// name. The return value has type char *.
924 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000925
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +0000926 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
927
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000928 /// BuildIvarLayout - Builds ivar layout bitmap for the class
929 /// implementation for the __strong or __weak case.
930 ///
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000931 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
932 bool ForStrongLayout);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +0000933
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +0000934 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000935
Daniel Dunbard58edcb2009-05-03 14:10:34 +0000936 void BuildAggrIvarRecordLayout(const RecordType *RT,
Eli Friedmane5b46662012-11-06 22:15:52 +0000937 unsigned int BytePos, bool ForStrongLayout,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000938 bool &HasUnion);
Daniel Dunbar5a5a8032009-05-03 21:05:10 +0000939 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000940 const llvm::StructLayout *Layout,
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000941 const RecordDecl *RD,
Bill Wendling795b1002012-02-22 09:30:11 +0000942 ArrayRef<const FieldDecl*> RecFields,
Eli Friedmane5b46662012-11-06 22:15:52 +0000943 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahanian81adc052009-04-24 16:17:09 +0000944 bool &HasUnion);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +0000945
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +0000946 Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
Fariborz Jahanian44fcff92012-11-02 22:51:18 +0000947
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +0000948 void UpdateRunSkipBlockVars(bool IsByref,
949 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +0000950 CharUnits FieldOffset,
951 CharUnits FieldSize);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +0000952
953 void BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +0000954 CharUnits BytePos, bool &HasUnion,
955 bool ByrefLayout=false);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +0000956
957 void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
958 const RecordDecl *RD,
959 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +0000960 CharUnits BytePos, bool &HasUnion,
961 bool ByrefLayout);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +0000962
Fariborz Jahanianf22ae652012-11-01 18:32:55 +0000963 uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
964
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +0000965 llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);
966
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000967
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +0000968 /// GetIvarLayoutName - Returns a unique constant for the given
969 /// ivar layout bitmap.
970 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
971 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000972
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000973 /// EmitPropertyList - Emit the given property list. The return
974 /// value has type PropertyListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000975 llvm::Constant *EmitPropertyList(Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000976 const Decl *Container,
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000977 const ObjCContainerDecl *OCD,
978 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000979
Bob Wilsondc8dab62011-11-30 01:57:58 +0000980 /// EmitProtocolMethodTypes - Generate the array of extended method type
981 /// strings. The return value has type Int8PtrPtrTy.
982 llvm::Constant *EmitProtocolMethodTypes(Twine Name,
Bill Wendlingbb028552012-02-07 09:25:09 +0000983 ArrayRef<llvm::Constant*> MethodTypes,
Bob Wilsondc8dab62011-11-30 01:57:58 +0000984 const ObjCCommonTypesHelper &ObjCTypes);
985
Fariborz Jahanian191dcd72009-12-12 21:26:21 +0000986 /// PushProtocolProperties - Push protocol's property on the input stack.
Bill Wendling3964e622012-02-09 22:16:49 +0000987 void PushProtocolProperties(
988 llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
989 llvm::SmallVectorImpl<llvm::Constant*> &Properties,
990 const Decl *Container,
991 const ObjCProtocolDecl *PROTO,
992 const ObjCCommonTypesHelper &ObjCTypes);
Fariborz Jahanian191dcd72009-12-12 21:26:21 +0000993
Fariborz Jahanianda320092009-01-29 19:24:30 +0000994 /// GetProtocolRef - Return a reference to the internal protocol
995 /// description, creating an empty one if it has not been
996 /// defined. The return value has type ProtocolPtrTy.
997 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanianb21f07e2009-03-08 20:18:37 +0000998
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000999 /// CreateMetadataVar - Create a global variable with internal
1000 /// linkage for use by the Objective-C runtime.
1001 ///
1002 /// This is a convenience wrapper which not only creates the
1003 /// variable, but also sets the section and alignment and adds the
Chris Lattnerad64e022009-07-17 23:57:13 +00001004 /// global to the "llvm.used" list.
Daniel Dunbar35bd7632009-03-09 20:50:13 +00001005 ///
1006 /// \param Name - The variable name.
1007 /// \param Init - The variable initializer; this is also used to
1008 /// define the type of the variable.
1009 /// \param Section - The section the variable should go into, or 0.
1010 /// \param Align - The alignment for the variable, or 0.
1011 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbarc1583062009-04-14 17:42:51 +00001012 /// "llvm.used".
Chris Lattner5f9e2722011-07-23 10:55:15 +00001013 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +00001014 llvm::Constant *Init,
1015 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +00001016 unsigned Align,
1017 bool AddToUsed);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00001018
John McCall944c8432011-05-14 03:10:52 +00001019 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1020 ReturnValueSlot Return,
1021 QualType ResultType,
1022 llvm::Value *Sel,
1023 llvm::Value *Arg0,
1024 QualType Arg0Ty,
1025 bool IsSuper,
1026 const CallArgList &CallArgs,
1027 const ObjCMethodDecl *OMD,
1028 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00001029
Daniel Dunbarfce176b2010-04-25 20:39:01 +00001030 /// EmitImageInfo - Emit the image info marker used to encode some module
1031 /// level information.
1032 void EmitImageInfo();
1033
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001034public:
Owen Anderson69243822009-07-13 04:10:07 +00001035 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
John McCallde5d3c72012-02-17 03:33:10 +00001036 CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001037
David Chisnall0d13f6f2010-01-23 02:40:42 +00001038 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001039
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001040 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
1041 const ObjCContainerDecl *CD=0);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001042
Fariborz Jahanianda320092009-01-29 19:24:30 +00001043 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001044
Fariborz Jahanianda320092009-01-29 19:24:30 +00001045 /// GetOrEmitProtocol - Get the protocol object for the given
1046 /// declaration, emitting it if necessary. The return value has type
1047 /// ProtocolPtrTy.
1048 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001049
Fariborz Jahanianda320092009-01-29 19:24:30 +00001050 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1051 /// object for the given declaration, emitting it if needed. These
1052 /// forward references will be filled in with empty bodies if no
1053 /// definition is seen. The return value has type ProtocolPtrTy.
1054 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCall6b5a61b2011-02-07 10:33:21 +00001055 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
1056 const CGBlockInfo &blockInfo);
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00001057 virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
1058 const CGBlockInfo &blockInfo);
Fariborz Jahanian89ecd412010-08-04 16:57:49 +00001059
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00001060 virtual llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
1061 QualType T);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001062};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001063
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001064class CGObjCMac : public CGObjCCommonMac {
1065private:
1066 ObjCTypesHelper ObjCTypes;
Daniel Dunbarf77ac862008-08-11 21:35:06 +00001067
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001068 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001069 /// information.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001070 void EmitModuleInfo();
1071
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001072 /// EmitModuleSymols - Emit module symbols, the list of defined
1073 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001074 llvm::Constant *EmitModuleSymbols();
1075
Daniel Dunbarf77ac862008-08-11 21:35:06 +00001076 /// FinishModule - Write out global data structures at the end of
1077 /// processing a translation unit.
1078 void FinishModule();
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001079
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001080 /// EmitClassExtension - Generate the class extension structure used
1081 /// to store the weak ivar layout and properties. The return value
1082 /// has type ClassExtensionPtrTy.
1083 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
1084
1085 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1086 /// for the given class.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001087 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001088 const ObjCInterfaceDecl *ID);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00001089
John McCallf85e1932011-06-15 23:02:42 +00001090 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
1091 IdentifierInfo *II);
1092
1093 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
1094
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00001095 /// EmitSuperClassRef - Emits reference to class's main metadata class.
1096 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001097
1098 /// EmitIvarList - Emit the ivar list for the given
1099 /// implementation. If ForClass is true the list of class ivars
1100 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1101 /// interface ivars will be emitted. The return value has type
1102 /// IvarListPtrTy.
1103 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00001104 bool ForClass);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001105
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001106 /// EmitMetaClass - Emit a forward reference to the class structure
1107 /// for the metaclass of the given interface. The return value has
1108 /// type ClassPtrTy.
1109 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
1110
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001111 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001112 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001113 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
1114 llvm::Constant *Protocols,
Bill Wendlingbb028552012-02-07 09:25:09 +00001115 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001116
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001117 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001118
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001119 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001120
1121 /// EmitMethodList - Emit the method list for the given
Daniel Dunbaraf05bb92008-08-26 08:29:31 +00001122 /// implementation. The return value has type MethodListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +00001123 llvm::Constant *EmitMethodList(Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001124 const char *Section,
Bill Wendlingbb028552012-02-07 09:25:09 +00001125 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001126
1127 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001128 /// method declarations.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001129 /// - TypeName: The name for the type containing the methods.
Sylvestre Ledruf3477c12012-09-27 10:16:10 +00001130 /// - IsProtocol: True iff these methods are for a protocol.
1131 /// - ClassMethds: True iff these are class methods.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001132 /// - Required: When true, only "required" methods are
1133 /// listed. Similarly, when false only "optional" methods are
1134 /// listed. For classes this should always be true.
1135 /// - begin, end: The method list to output.
1136 ///
1137 /// The return value has type MethodDescriptionListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +00001138 llvm::Constant *EmitMethodDescList(Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001139 const char *Section,
Bill Wendlingbb028552012-02-07 09:25:09 +00001140 ArrayRef<llvm::Constant*> Methods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001141
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001142 /// GetOrEmitProtocol - Get the protocol object for the given
1143 /// declaration, emitting it if necessary. The return value has type
1144 /// ProtocolPtrTy.
Fariborz Jahanianda320092009-01-29 19:24:30 +00001145 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001146
1147 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1148 /// object for the given declaration, emitting it if needed. These
1149 /// forward references will be filled in with empty bodies if no
1150 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanianda320092009-01-29 19:24:30 +00001151 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001152
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001153 /// EmitProtocolExtension - Generate the protocol extension
1154 /// structure used to store optional instance and class methods, and
1155 /// protocol properties. The return value has type
1156 /// ProtocolExtensionPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001157 llvm::Constant *
1158 EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingbb028552012-02-07 09:25:09 +00001159 ArrayRef<llvm::Constant*> OptInstanceMethods,
1160 ArrayRef<llvm::Constant*> OptClassMethods,
1161 ArrayRef<llvm::Constant*> MethodTypesExt);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001162
1163 /// EmitProtocolList - Generate the list of referenced
1164 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +00001165 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardbc93372008-08-21 21:57:41 +00001166 ObjCProtocolDecl::protocol_iterator begin,
1167 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001168
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001169 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1170 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001171 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1172 bool lval=false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001173
1174public:
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001175 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001176
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001177 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001178
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001179 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001180 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001181 QualType ResultType,
1182 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001183 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001184 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001185 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001186 const ObjCMethodDecl *Method);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001187
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001188 virtual CodeGen::RValue
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001189 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001190 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001191 QualType ResultType,
1192 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001193 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001194 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001195 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001196 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001197 const CallArgList &CallArgs,
1198 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001199
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001200 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001201 const ObjCInterfaceDecl *ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001202
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001203 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1204 bool lval = false);
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001205
1206 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1207 /// untyped one.
1208 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1209 const ObjCMethodDecl *Method);
1210
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001211 virtual llvm::Constant *GetEHType(QualType T);
John McCall5a180392010-07-24 00:37:23 +00001212
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001213 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001214
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001215 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001216
Daniel Dunbar85fdea02012-02-28 15:36:15 +00001217 virtual void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {}
David Chisnall29254f42012-01-31 18:59:20 +00001218
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001219 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001220 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001221
Chris Lattner74391b42009-03-22 21:03:39 +00001222 virtual llvm::Constant *GetPropertyGetFunction();
1223 virtual llvm::Constant *GetPropertySetFunction();
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001224 virtual llvm::Constant *GetOptimizedPropertySetFunction(bool atomic,
1225 bool copy);
David Chisnall8fac25d2010-12-26 22:13:16 +00001226 virtual llvm::Constant *GetGetStructFunction();
1227 virtual llvm::Constant *GetSetStructFunction();
Fariborz Jahaniane3173022012-01-06 18:07:23 +00001228 virtual llvm::Constant *GetCppAtomicObjectFunction();
Chris Lattner74391b42009-03-22 21:03:39 +00001229 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001230
John McCallf1549f62010-07-06 01:34:17 +00001231 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1232 const ObjCAtTryStmt &S);
1233 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1234 const ObjCAtSynchronizedStmt &S);
1235 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00001236 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1237 const ObjCAtThrowStmt &S);
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 }
Fariborz Jahaniane3173022012-01-06 18:07:23 +00001499 virtual llvm::Constant *GetCppAtomicObjectFunction() {
1500 return ObjCTypes.getCppAtomicObjectFunction();
1501 }
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001502
Chris Lattner74391b42009-03-22 21:03:39 +00001503 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001504 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbar28ed0842009-02-16 18:48:45 +00001505 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001506
John McCallf1549f62010-07-06 01:34:17 +00001507 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1508 const ObjCAtTryStmt &S);
1509 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1510 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001511 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlssonf57c5b22009-02-16 22:59:18 +00001512 const ObjCAtThrowStmt &S);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001513 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001514 llvm::Value *AddrWeakObj);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001515 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001516 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001517 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001518 llvm::Value *src, llvm::Value *dest,
1519 bool threadlocal = false);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001520 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001521 llvm::Value *src, llvm::Value *dest,
1522 llvm::Value *ivarOffset);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001523 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001524 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001525 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1526 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001527 llvm::Value *size);
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001528 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1529 QualType ObjectTy,
1530 llvm::Value *BaseValue,
1531 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001532 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001533 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001534 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001535 const ObjCIvarDecl *Ivar);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001536};
Fariborz Jahanian4e1524b2012-01-29 20:27:13 +00001537
1538/// A helper class for performing the null-initialization of a return
1539/// value.
1540struct NullReturnState {
1541 llvm::BasicBlock *NullBB;
1542 llvm::BasicBlock *callBB;
1543 NullReturnState() : NullBB(0), callBB(0) {}
1544
1545 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1546 // Make blocks for the null-init and call edges.
1547 NullBB = CGF.createBasicBlock("msgSend.nullinit");
1548 callBB = CGF.createBasicBlock("msgSend.call");
1549
1550 // Check for a null receiver and, if there is one, jump to the
1551 // null-init test.
1552 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1553 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1554
1555 // Otherwise, start performing the call.
1556 CGF.EmitBlock(callBB);
1557 }
1558
Fariborz Jahanian3c267e62012-01-30 21:40:37 +00001559 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType,
1560 const CallArgList &CallArgs,
1561 const ObjCMethodDecl *Method) {
Fariborz Jahanian4e1524b2012-01-29 20:27:13 +00001562 if (!NullBB) return result;
Fariborz Jahanian3c267e62012-01-30 21:40:37 +00001563
1564 llvm::Value *NullInitPtr = 0;
1565 if (result.isScalar() && !resultType->isVoidType()) {
1566 NullInitPtr = CGF.CreateTempAlloca(result.getScalarVal()->getType());
1567 CGF.Builder.CreateStore(result.getScalarVal(), NullInitPtr);
1568 }
Fariborz Jahanian4e1524b2012-01-29 20:27:13 +00001569
1570 // Finish the call path.
1571 llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
1572 if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
1573
1574 // Emit the null-init block and perform the null-initialization there.
1575 CGF.EmitBlock(NullBB);
Fariborz Jahanian3c267e62012-01-30 21:40:37 +00001576
1577 // Release consumed arguments along the null-receiver path.
1578 if (Method) {
1579 CallArgList::const_iterator I = CallArgs.begin();
1580 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1581 e = Method->param_end(); i != e; ++i, ++I) {
1582 const ParmVarDecl *ParamDecl = (*i);
1583 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1584 RValue RV = I->RV;
1585 assert(RV.isScalar() &&
1586 "NullReturnState::complete - arg not on object");
1587 CGF.EmitARCRelease(RV.getScalarVal(), true);
1588 }
1589 }
1590 }
1591
1592 if (result.isScalar()) {
1593 if (NullInitPtr)
1594 CGF.EmitNullInitialization(NullInitPtr, resultType);
1595 // Jump to the continuation block.
1596 CGF.EmitBlock(contBB);
1597 return NullInitPtr ? RValue::get(CGF.Builder.CreateLoad(NullInitPtr))
1598 : result;
1599 }
1600
Fariborz Jahanian4e1524b2012-01-29 20:27:13 +00001601 if (!resultType->isAnyComplexType()) {
1602 assert(result.isAggregate() && "null init of non-aggregate result?");
1603 CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
1604 // Jump to the continuation block.
1605 CGF.EmitBlock(contBB);
1606 return result;
1607 }
1608
1609 // _Complex type
1610 // FIXME. Now easy to handle any other scalar type whose result is returned
1611 // in memory due to ABI limitations.
1612 CGF.EmitBlock(contBB);
1613 CodeGenFunction::ComplexPairTy CallCV = result.getComplexVal();
1614 llvm::Type *MemberType = CallCV.first->getType();
1615 llvm::Constant *ZeroCV = llvm::Constant::getNullValue(MemberType);
1616 // Create phi instruction for scalar complex value.
1617 llvm::PHINode *PHIReal = CGF.Builder.CreatePHI(MemberType, 2);
1618 PHIReal->addIncoming(ZeroCV, NullBB);
1619 PHIReal->addIncoming(CallCV.first, callBB);
1620 llvm::PHINode *PHIImag = CGF.Builder.CreatePHI(MemberType, 2);
1621 PHIImag->addIncoming(ZeroCV, NullBB);
1622 PHIImag->addIncoming(CallCV.second, callBB);
1623 return RValue::getComplex(PHIReal, PHIImag);
1624 }
1625};
1626
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001627} // end anonymous namespace
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001628
1629/* *** Helper Functions *** */
1630
1631/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Andersona1cf15f2009-07-14 23:10:40 +00001632static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001633 llvm::Constant *C,
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001634 unsigned idx0,
1635 unsigned idx1) {
1636 llvm::Value *Idxs[] = {
Owen Anderson0032b272009-08-13 21:57:51 +00001637 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1638 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001639 };
Jay Foada5c04342011-07-21 14:31:17 +00001640 return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001641}
1642
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001643/// hasObjCExceptionAttribute - Return true if this class or any super
1644/// class has the __objc_exception__ attribute.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001645static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor68584ed2009-06-18 16:11:24 +00001646 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidis40b598e2009-06-30 02:34:44 +00001647 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001648 return true;
1649 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor68584ed2009-06-18 16:11:24 +00001650 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001651 return false;
1652}
1653
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001654/* *** CGObjCMac Public Interface *** */
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001655
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001656CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00001657 ObjCTypes(cgm) {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001658 ObjCABI = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001659 EmitImageInfo();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001660}
1661
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +00001662/// GetClass - Return a reference to the class for the given interface
1663/// decl.
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001664llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001665 const ObjCInterfaceDecl *ID) {
1666 return EmitClassRef(Builder, ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001667}
1668
1669/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001670llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1671 bool lval) {
1672 return EmitSelector(Builder, Sel, lval);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001673}
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001674llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001675 *Method) {
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001676 return EmitSelector(Builder, Method->getSelector());
1677}
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001678
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001679llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00001680 if (T->isObjCIdType() ||
1681 T->isObjCQualifiedIdType()) {
1682 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor01a4cf12011-08-11 20:58:55 +00001683 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00001684 }
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001685 if (T->isObjCClassType() ||
1686 T->isObjCQualifiedClassType()) {
1687 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor01a4cf12011-08-11 20:58:55 +00001688 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001689 }
1690 if (T->isObjCObjectPointerType())
1691 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1692
John McCall5a180392010-07-24 00:37:23 +00001693 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
John McCall5a180392010-07-24 00:37:23 +00001694}
1695
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001696/// Generate a constant CFString object.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001697/*
1698 struct __builtin_CFString {
1699 const int *isa; // point to __CFConstantStringClassReference
1700 int flags;
1701 const char *str;
1702 long length;
1703 };
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001704*/
1705
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001706/// or Generate a constant NSString object.
1707/*
1708 struct __builtin_NSString {
1709 const int *isa; // point to __NSConstantStringClassReference
1710 const char *str;
1711 unsigned int length;
1712 };
1713*/
1714
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001715llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall0d13f6f2010-01-23 02:40:42 +00001716 const StringLiteral *SL) {
David Blaikie4e4d0842012-03-11 07:00:24 +00001717 return (CGM.getLangOpts().NoConstantCFStrings == 0 ?
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001718 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian4c733072010-10-19 17:19:29 +00001719 CGM.GetAddrOfConstantString(SL));
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001720}
1721
Ted Kremenekebcb57a2012-03-06 20:05:56 +00001722enum {
1723 kCFTaggedObjectID_Integer = (1 << 1) + 1
1724};
1725
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001726/// Generates a message send where the super is the receiver. This is
1727/// a message send to self with special delivery semantics indicating
1728/// which class's method should be called.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001729CodeGen::RValue
1730CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001731 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001732 QualType ResultType,
1733 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001734 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001735 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001736 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001737 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001738 const CodeGen::CallArgList &CallArgs,
1739 const ObjCMethodDecl *Method) {
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001740 // Create and init a super structure; this is a (receiver, class)
1741 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001742 llvm::Value *ObjCSuper =
John McCall604da292011-03-04 08:00:29 +00001743 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001744 llvm::Value *ReceiverAsObject =
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001745 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001746 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001747 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001748
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001749 // If this is a class message the metaclass is passed as the target.
1750 llvm::Value *Target;
1751 if (IsClassMessage) {
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001752 if (isCategoryImpl) {
1753 // Message sent to 'super' in a class method defined in a category
1754 // implementation requires an odd treatment.
1755 // If we are in a class method, we must retrieve the
1756 // _metaclass_ for the current class, pointed at by
1757 // the class's "isa" pointer. The following assumes that
1758 // isa" is the first ivar in a class (which it must be).
1759 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1760 Target = CGF.Builder.CreateStructGEP(Target, 0);
1761 Target = CGF.Builder.CreateLoad(Target);
Mike Stumpb3589f42009-07-30 22:28:39 +00001762 } else {
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001763 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1764 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1765 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1766 Target = Super;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001767 }
Fariborz Jahanian182f2682009-11-14 02:18:31 +00001768 }
1769 else if (isCategoryImpl)
1770 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1771 else {
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00001772 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1773 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1774 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001775 }
Mike Stumpf5408fe2009-05-16 07:57:57 +00001776 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1777 // ObjCTypes types.
Chris Lattner2acc6e32011-07-18 04:24:23 +00001778 llvm::Type *ClassTy =
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001779 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001780 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001781 CGF.Builder.CreateStore(Target,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001782 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall944c8432011-05-14 03:10:52 +00001783 return EmitMessageSend(CGF, Return, ResultType,
1784 EmitSelector(CGF.Builder, Sel),
1785 ObjCSuper, ObjCTypes.SuperPtrCTy,
1786 true, CallArgs, Method, ObjCTypes);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001787}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001788
1789/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001790CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001791 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001792 QualType ResultType,
1793 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001794 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001795 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001796 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001797 const ObjCMethodDecl *Method) {
John McCall944c8432011-05-14 03:10:52 +00001798 return EmitMessageSend(CGF, Return, ResultType,
1799 EmitSelector(CGF.Builder, Sel),
1800 Receiver, CGF.getContext().getObjCIdType(),
1801 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00001802}
1803
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001804CodeGen::RValue
John McCall944c8432011-05-14 03:10:52 +00001805CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1806 ReturnValueSlot Return,
1807 QualType ResultType,
1808 llvm::Value *Sel,
1809 llvm::Value *Arg0,
1810 QualType Arg0Ty,
1811 bool IsSuper,
1812 const CallArgList &CallArgs,
1813 const ObjCMethodDecl *Method,
1814 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001815 CallArgList ActualArgs;
Fariborz Jahaniand019d962009-04-24 21:07:43 +00001816 if (!IsSuper)
Benjamin Kramer578faa82011-09-27 21:06:10 +00001817 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman04c9a492011-05-02 17:57:46 +00001818 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1819 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCallf85e1932011-06-15 23:02:42 +00001820 ActualArgs.addFrom(CallArgs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001821
John McCallde5d3c72012-02-17 03:33:10 +00001822 // If we're calling a method, use the formal signature.
1823 MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001824
Anders Carlsson7e70fb22010-06-21 20:59:55 +00001825 if (Method)
1826 assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1827 CGM.getContext().getCanonicalType(ResultType) &&
1828 "Result type mismatch!");
1829
John McCallcba681a2011-05-14 21:12:11 +00001830 NullReturnState nullReturn;
1831
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001832 llvm::Constant *Fn = NULL;
John McCallde5d3c72012-02-17 03:33:10 +00001833 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
Fariborz Jahanian4e1524b2012-01-29 20:27:13 +00001834 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001835 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001836 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001837 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1838 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1839 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlssoneea64802011-10-31 16:27:11 +00001840 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
1841 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
1842 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001843 } else {
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001844 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001845 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001846 }
Fariborz Jahanian3c267e62012-01-30 21:40:37 +00001847
1848 bool requiresnullCheck = false;
David Blaikie4e4d0842012-03-11 07:00:24 +00001849 if (CGM.getLangOpts().ObjCAutoRefCount && Method)
Fariborz Jahanian3c267e62012-01-30 21:40:37 +00001850 for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(),
1851 e = Method->param_end(); i != e; ++i) {
1852 const ParmVarDecl *ParamDecl = (*i);
1853 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
1854 if (!nullReturn.NullBB)
1855 nullReturn.init(CGF, Arg0);
1856 requiresnullCheck = true;
1857 break;
1858 }
1859 }
1860
John McCallde5d3c72012-02-17 03:33:10 +00001861 Fn = llvm::ConstantExpr::getBitCast(Fn, MSI.MessengerType);
1862 RValue rvalue = CGF.EmitCall(MSI.CallInfo, Fn, Return, ActualArgs);
Fariborz Jahanian3c267e62012-01-30 21:40:37 +00001863 return nullReturn.complete(CGF, rvalue, ResultType, CallArgs,
1864 requiresnullCheck ? Method : 0);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001865}
1866
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001867static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1868 if (FQT.isObjCGCStrong())
1869 return Qualifiers::Strong;
1870
John McCallf85e1932011-06-15 23:02:42 +00001871 if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001872 return Qualifiers::Weak;
1873
Fariborz Jahanianba83c952012-02-16 00:15:02 +00001874 // check for __unsafe_unretained
1875 if (FQT.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
1876 return Qualifiers::GCNone;
1877
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001878 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1879 return Qualifiers::Strong;
1880
1881 if (const PointerType *PT = FQT->getAs<PointerType>())
1882 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1883
1884 return Qualifiers::GCNone;
1885}
1886
John McCall6b5a61b2011-02-07 10:33:21 +00001887llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1888 const CGBlockInfo &blockInfo) {
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00001889
Chris Lattner8b418682012-02-07 00:39:47 +00001890 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
David Blaikie4e4d0842012-03-11 07:00:24 +00001891 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
1892 !CGM.getLangOpts().ObjCAutoRefCount)
John McCall6b5a61b2011-02-07 10:33:21 +00001893 return nullPtr;
1894
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001895 bool hasUnion = false;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001896 SkipIvars.clear();
1897 IvarsInfo.clear();
Eli Friedmane5b46662012-11-06 22:15:52 +00001898 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
1899 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001900
Fariborz Jahanian81979822010-09-09 00:21:45 +00001901 // __isa is the first field in block descriptor and must assume by runtime's
1902 // convention that it is GC'able.
Eli Friedmane5b46662012-11-06 22:15:52 +00001903 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall6b5a61b2011-02-07 10:33:21 +00001904
1905 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1906
1907 // Calculate the basic layout of the block structure.
1908 const llvm::StructLayout *layout =
Micah Villmow25a6a842012-10-08 16:25:52 +00001909 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
John McCall6b5a61b2011-02-07 10:33:21 +00001910
1911 // Ignore the optional 'this' capture: C++ objects are not assumed
1912 // to be GC'ed.
1913
1914 // Walk the captured variables.
1915 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1916 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1917 const VarDecl *variable = ci->getVariable();
1918 QualType type = variable->getType();
1919
1920 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1921
1922 // Ignore constant captures.
1923 if (capture.isConstant()) continue;
1924
Eli Friedmane5b46662012-11-06 22:15:52 +00001925 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
John McCall6b5a61b2011-02-07 10:33:21 +00001926
1927 // __block variables are passed by their descriptor address.
1928 if (ci->isByRef()) {
Eli Friedmane5b46662012-11-06 22:15:52 +00001929 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanianc5904b42010-09-11 01:27:29 +00001930 continue;
John McCall6b5a61b2011-02-07 10:33:21 +00001931 }
1932
1933 assert(!type->isArrayType() && "array variable should not be caught");
1934 if (const RecordType *record = type->getAs<RecordType>()) {
1935 BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
Fariborz Jahaniane1a48982010-08-05 21:00:25 +00001936 continue;
1937 }
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001938
John McCall6b5a61b2011-02-07 10:33:21 +00001939 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
Eli Friedmane5b46662012-11-06 22:15:52 +00001940 unsigned fieldSize = CGM.getContext().getTypeSize(type);
John McCall6b5a61b2011-02-07 10:33:21 +00001941
1942 if (GCAttr == Qualifiers::Strong)
Eli Friedmane5b46662012-11-06 22:15:52 +00001943 IvarsInfo.push_back(GC_IVAR(fieldOffset,
1944 fieldSize / WordSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001945 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
Eli Friedmane5b46662012-11-06 22:15:52 +00001946 SkipIvars.push_back(GC_IVAR(fieldOffset,
1947 fieldSize / ByteSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001948 }
1949
1950 if (IvarsInfo.empty())
John McCall6b5a61b2011-02-07 10:33:21 +00001951 return nullPtr;
1952
1953 // Sort on byte position; captures might not be allocated in order,
1954 // and unions can do funny things.
1955 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
1956 llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001957
1958 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00001959 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
David Blaikie4e4d0842012-03-11 07:00:24 +00001960 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001961 printf("\n block variable layout for block: ");
Roman Divacky31ba6132012-09-06 15:59:27 +00001962 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling13562a12012-02-07 09:06:01 +00001963 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001964 if (!(s[i] & 0xf0))
1965 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1966 else
1967 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
1968 printf("\n");
1969 }
1970
1971 return C;
Fariborz Jahanian89ecd412010-08-04 16:57:49 +00001972}
1973
Fariborz Jahanianc441cd32012-11-04 18:19:40 +00001974/// getBlockCaptureLifetime - This routine returns life time of the captured
1975/// block variable for the purpose of block layout meta-data generation. FQT is
1976/// the type of the variable captured in the block.
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00001977Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
1978 bool ByrefLayout) {
Fariborz Jahanian44fcff92012-11-02 22:51:18 +00001979 if (CGM.getLangOpts().ObjCAutoRefCount)
1980 return FQT.getObjCLifetime();
1981
Fariborz Jahanianc441cd32012-11-04 18:19:40 +00001982 // MRR.
Fariborz Jahanian44fcff92012-11-02 22:51:18 +00001983 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00001984 return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
Fariborz Jahanian44fcff92012-11-02 22:51:18 +00001985
1986 return Qualifiers::OCL_None;
1987}
1988
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00001989void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
1990 Qualifiers::ObjCLifetime LifeTime,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00001991 CharUnits FieldOffset,
1992 CharUnits FieldSize) {
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00001993 // __block variables are passed by their descriptor address.
1994 if (IsByref)
1995 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00001996 FieldSize));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00001997 else if (LifeTime == Qualifiers::OCL_Strong)
1998 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00001999 FieldSize));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002000 else if (LifeTime == Qualifiers::OCL_Weak)
2001 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002002 FieldSize));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002003 else if (LifeTime == Qualifiers::OCL_ExplicitNone)
2004 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002005 FieldSize));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002006 else
2007 RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
2008 FieldOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002009 FieldSize));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002010}
2011
2012void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
2013 const RecordDecl *RD,
2014 ArrayRef<const FieldDecl*> RecFields,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002015 CharUnits BytePos, bool &HasUnion,
2016 bool ByrefLayout) {
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002017 bool IsUnion = (RD && RD->isUnion());
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002018 CharUnits MaxUnionSize = CharUnits::Zero();
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002019 const FieldDecl *MaxField = 0;
2020 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002021 CharUnits MaxFieldOffset = CharUnits::Zero();
2022 CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002023
2024 if (RecFields.empty())
2025 return;
2026 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
2027
2028 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
2029 const FieldDecl *Field = RecFields[i];
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002030 // Note that 'i' here is actually the field index inside RD of Field,
2031 // although this dependency is hidden.
2032 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002033 CharUnits FieldOffset =
2034 CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002035
2036 // Skip over unnamed or bitfields
2037 if (!Field->getIdentifier() || Field->isBitField()) {
2038 LastFieldBitfieldOrUnnamed = Field;
2039 LastBitfieldOrUnnamedOffset = FieldOffset;
2040 continue;
2041 }
2042
2043 LastFieldBitfieldOrUnnamed = 0;
2044 QualType FQT = Field->getType();
2045 if (FQT->isRecordType() || FQT->isUnionType()) {
2046 if (FQT->isUnionType())
2047 HasUnion = true;
2048
2049 BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(),
2050 BytePos + FieldOffset, HasUnion);
2051 continue;
2052 }
2053
2054 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2055 const ConstantArrayType *CArray =
2056 dyn_cast_or_null<ConstantArrayType>(Array);
2057 uint64_t ElCount = CArray->getSize().getZExtValue();
2058 assert(CArray && "only array with known element size is supported");
2059 FQT = CArray->getElementType();
2060 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2061 const ConstantArrayType *CArray =
2062 dyn_cast_or_null<ConstantArrayType>(Array);
2063 ElCount *= CArray->getSize().getZExtValue();
2064 FQT = CArray->getElementType();
2065 }
2066
2067 assert(!FQT->isUnionType() &&
2068 "layout for array of unions not supported");
2069 if (FQT->isRecordType() && ElCount) {
2070 int OldIndex = RunSkipBlockVars.size() - 1;
2071 const RecordType *RT = FQT->getAs<RecordType>();
2072 BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset,
2073 HasUnion);
2074
2075 // Replicate layout information for each array element. Note that
2076 // one element is already done.
2077 uint64_t ElIx = 1;
2078 for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002079 CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002080 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2081 RunSkipBlockVars.push_back(
2082 RUN_SKIP(RunSkipBlockVars[i].opcode,
2083 RunSkipBlockVars[i].block_var_bytepos + Size*ElIx,
2084 RunSkipBlockVars[i].block_var_size));
2085 }
2086 continue;
2087 }
2088 }
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002089 CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002090 if (IsUnion) {
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002091 CharUnits UnionIvarSize = FieldSize;
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002092 if (UnionIvarSize > MaxUnionSize) {
2093 MaxUnionSize = UnionIvarSize;
2094 MaxField = Field;
2095 MaxFieldOffset = FieldOffset;
2096 }
2097 } else {
2098 UpdateRunSkipBlockVars(false,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002099 getBlockCaptureLifetime(FQT, ByrefLayout),
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002100 BytePos + FieldOffset,
2101 FieldSize);
2102 }
2103 }
2104
2105 if (LastFieldBitfieldOrUnnamed) {
2106 if (LastFieldBitfieldOrUnnamed->isBitField()) {
2107 // Last field was a bitfield. Must update the info.
2108 uint64_t BitFieldSize
2109 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002110 unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
Eli Friedmane5b46662012-11-06 22:15:52 +00002111 ((BitFieldSize % ByteSizeInBits) != 0);
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002112 CharUnits Size = CharUnits::fromQuantity(UnsSize);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002113 Size += LastBitfieldOrUnnamedOffset;
2114 UpdateRunSkipBlockVars(false,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002115 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2116 ByrefLayout),
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002117 BytePos + LastBitfieldOrUnnamedOffset,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002118 Size);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002119 } else {
2120 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
2121 // Last field was unnamed. Must update skip info.
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002122 CharUnits FieldSize
2123 = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002124 UpdateRunSkipBlockVars(false,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002125 getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
2126 ByrefLayout),
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002127 BytePos + LastBitfieldOrUnnamedOffset,
2128 FieldSize);
2129 }
2130 }
2131
2132 if (MaxField)
2133 UpdateRunSkipBlockVars(false,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002134 getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002135 BytePos + MaxFieldOffset,
2136 MaxUnionSize);
2137}
2138
2139void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002140 CharUnits BytePos,
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002141 bool &HasUnion,
2142 bool ByrefLayout) {
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002143 const RecordDecl *RD = RT->getDecl();
2144 SmallVector<const FieldDecl*, 16> Fields;
2145 for (RecordDecl::field_iterator i = RD->field_begin(),
2146 e = RD->field_end(); i != e; ++i)
2147 Fields.push_back(*i);
2148 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
2149 const llvm::StructLayout *RecLayout =
2150 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
2151
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002152 BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002153}
2154
Fariborz Jahanianf22ae652012-11-01 18:32:55 +00002155/// InlineLayoutInstruction - This routine produce an inline instruction for the
2156/// block variable layout if it can. If not, it returns 0. Rules are as follow:
2157/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world,
2158/// an inline layout of value 0x0000000000000xyz is interpreted as follows:
2159/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by
2160/// y captured object of BLOCK_LAYOUT_BYREF. Followed by
2161/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero
2162/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no
2163/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured.
2164uint64_t CGObjCCommonMac::InlineLayoutInstruction(
2165 SmallVectorImpl<unsigned char> &Layout) {
2166 uint64_t Result = 0;
2167 if (Layout.size() <= 3) {
2168 unsigned size = Layout.size();
2169 unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0;
2170 unsigned char inst;
2171 enum BLOCK_LAYOUT_OPCODE opcode ;
2172 switch (size) {
2173 case 3:
2174 inst = Layout[0];
2175 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2176 if (opcode == BLOCK_LAYOUT_STRONG)
2177 strong_word_count = (inst & 0xF)+1;
2178 else
2179 return 0;
2180 inst = Layout[1];
2181 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2182 if (opcode == BLOCK_LAYOUT_BYREF)
2183 byref_word_count = (inst & 0xF)+1;
2184 else
2185 return 0;
2186 inst = Layout[2];
2187 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2188 if (opcode == BLOCK_LAYOUT_WEAK)
2189 weak_word_count = (inst & 0xF)+1;
2190 else
2191 return 0;
2192 break;
2193
2194 case 2:
2195 inst = Layout[0];
2196 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2197 if (opcode == BLOCK_LAYOUT_STRONG) {
2198 strong_word_count = (inst & 0xF)+1;
2199 inst = Layout[1];
2200 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2201 if (opcode == BLOCK_LAYOUT_BYREF)
2202 byref_word_count = (inst & 0xF)+1;
2203 else if (opcode == BLOCK_LAYOUT_WEAK)
2204 weak_word_count = (inst & 0xF)+1;
2205 else
2206 return 0;
2207 }
2208 else if (opcode == BLOCK_LAYOUT_BYREF) {
2209 byref_word_count = (inst & 0xF)+1;
2210 inst = Layout[1];
2211 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2212 if (opcode == BLOCK_LAYOUT_WEAK)
2213 weak_word_count = (inst & 0xF)+1;
2214 else
2215 return 0;
2216 }
2217 else
2218 return 0;
2219 break;
2220
2221 case 1:
2222 inst = Layout[0];
2223 opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2224 if (opcode == BLOCK_LAYOUT_STRONG)
2225 strong_word_count = (inst & 0xF)+1;
2226 else if (opcode == BLOCK_LAYOUT_BYREF)
2227 byref_word_count = (inst & 0xF)+1;
2228 else if (opcode == BLOCK_LAYOUT_WEAK)
2229 weak_word_count = (inst & 0xF)+1;
2230 else
2231 return 0;
2232 break;
2233
2234 default:
2235 return 0;
2236 }
2237
2238 // Cannot inline when any of the word counts is 15. Because this is one less
2239 // than the actual work count (so 15 means 16 actual word counts),
2240 // and we can only display 0 thru 15 word counts.
2241 if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16)
2242 return 0;
2243
2244 unsigned count =
2245 (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0);
2246
2247 if (size == count) {
2248 if (strong_word_count)
2249 Result = strong_word_count;
2250 Result <<= 4;
2251 if (byref_word_count)
2252 Result += byref_word_count;
2253 Result <<= 4;
2254 if (weak_word_count)
2255 Result += weak_word_count;
2256 }
2257 }
2258 return Result;
2259}
2260
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002261llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
2262 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2263 if (RunSkipBlockVars.empty())
2264 return nullPtr;
2265 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
2266 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
2267 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2268
2269 // Sort on byte position; captures might not be allocated in order,
2270 // and unions can do funny things.
2271 llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
2272 SmallVector<unsigned char, 16> Layout;
2273
2274 unsigned size = RunSkipBlockVars.size();
2275 for (unsigned i = 0; i < size; i++) {
2276 enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
2277 CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
2278 CharUnits end_byte_pos = start_byte_pos;
2279 unsigned j = i+1;
2280 while (j < size) {
2281 if (opcode == RunSkipBlockVars[j].opcode) {
2282 end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
2283 i++;
2284 }
2285 else
2286 break;
2287 }
2288 CharUnits size_in_bytes =
2289 end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
2290 if (j < size) {
2291 CharUnits gap =
2292 RunSkipBlockVars[j].block_var_bytepos -
2293 RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
2294 size_in_bytes += gap;
2295 }
2296 CharUnits residue_in_bytes = CharUnits::Zero();
2297 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
2298 residue_in_bytes = size_in_bytes % WordSizeInBytes;
2299 size_in_bytes -= residue_in_bytes;
2300 opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
2301 }
2302
2303 unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
2304 while (size_in_words >= 16) {
2305 // Note that value in imm. is one less that the actual
2306 // value. So, 0xf means 16 words follow!
2307 unsigned char inst = (opcode << 4) | 0xf;
2308 Layout.push_back(inst);
2309 size_in_words -= 16;
2310 }
2311 if (size_in_words > 0) {
2312 // Note that value in imm. is one less that the actual
2313 // value. So, we subtract 1 away!
2314 unsigned char inst = (opcode << 4) | (size_in_words-1);
2315 Layout.push_back(inst);
2316 }
2317 if (residue_in_bytes > CharUnits::Zero()) {
2318 unsigned char inst =
2319 (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
2320 Layout.push_back(inst);
2321 }
2322 }
2323
2324 int e = Layout.size()-1;
2325 while (e >= 0) {
2326 unsigned char inst = Layout[e--];
2327 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2328 if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
2329 Layout.pop_back();
2330 else
2331 break;
2332 }
2333
2334 uint64_t Result = InlineLayoutInstruction(Layout);
2335 if (Result != 0) {
2336 // Block variable layout instruction has been inlined.
2337 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2338 if (ComputeByrefLayout)
2339 printf("\n Inline instruction for BYREF variable layout: ");
2340 else
2341 printf("\n Inline instruction for block variable layout: ");
2342 printf("0x0%llx\n", (unsigned long long)Result);
2343 }
2344 if (WordSizeInBytes == 8) {
2345 const llvm::APInt Instruction(64, Result);
2346 return llvm::Constant::getIntegerValue(CGM.Int64Ty, Instruction);
2347 }
2348 else {
2349 const llvm::APInt Instruction(32, Result);
2350 return llvm::Constant::getIntegerValue(CGM.Int32Ty, Instruction);
2351 }
2352 }
2353
2354 unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
2355 Layout.push_back(inst);
2356 std::string BitMap;
2357 for (unsigned i = 0, e = Layout.size(); i != e; i++)
2358 BitMap += Layout[i];
2359
2360 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
2361 if (ComputeByrefLayout)
2362 printf("\n BYREF variable layout: ");
2363 else
2364 printf("\n block variable layout: ");
2365 for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
2366 unsigned char inst = BitMap[i];
2367 enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4);
2368 unsigned delta = 1;
2369 switch (opcode) {
2370 case BLOCK_LAYOUT_OPERATOR:
2371 printf("BL_OPERATOR:");
2372 delta = 0;
2373 break;
2374 case BLOCK_LAYOUT_NON_OBJECT_BYTES:
2375 printf("BL_NON_OBJECT_BYTES:");
2376 break;
2377 case BLOCK_LAYOUT_NON_OBJECT_WORDS:
2378 printf("BL_NON_OBJECT_WORD:");
2379 break;
2380 case BLOCK_LAYOUT_STRONG:
2381 printf("BL_STRONG:");
2382 break;
2383 case BLOCK_LAYOUT_BYREF:
2384 printf("BL_BYREF:");
2385 break;
2386 case BLOCK_LAYOUT_WEAK:
2387 printf("BL_WEAK:");
2388 break;
2389 case BLOCK_LAYOUT_UNRETAINED:
2390 printf("BL_UNRETAINED:");
2391 break;
2392 }
2393 // Actual value of word count is one more that what is in the imm.
2394 // field of the instruction
2395 printf("%d", (inst & 0xf) + delta);
2396 if (i < e-1)
2397 printf(", ");
2398 else
2399 printf("\n");
2400 }
2401 }
2402
2403 llvm::GlobalVariable * Entry =
2404 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
2405 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
2406 "__TEXT,__objc_classname,cstring_literals", 1, true);
2407 return getConstantGEP(VMContext, Entry, 0, 0);
2408}
2409
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002410llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
2411 const CGBlockInfo &blockInfo) {
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002412 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2413
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002414 RunSkipBlockVars.clear();
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002415 bool hasUnion = false;
2416
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002417 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
2418 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
2419 unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
2420
2421 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
2422
2423 // Calculate the basic layout of the block structure.
2424 const llvm::StructLayout *layout =
2425 CGM.getDataLayout().getStructLayout(blockInfo.StructureType);
2426
2427 // Ignore the optional 'this' capture: C++ objects are not assumed
2428 // to be GC'ed.
2429
2430 // Walk the captured variables.
2431 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
2432 ce = blockDecl->capture_end(); ci != ce; ++ci) {
2433 const VarDecl *variable = ci->getVariable();
2434 QualType type = variable->getType();
2435
2436 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
2437
2438 // Ignore constant captures.
2439 if (capture.isConstant()) continue;
2440
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002441 CharUnits fieldOffset =
2442 CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002443
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002444 assert(!type->isArrayType() && "array variable should not be caught");
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002445 if (!ci->isByRef())
2446 if (const RecordType *record = type->getAs<RecordType>()) {
2447 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
2448 continue;
2449 }
Fariborz Jahanian1da01d62012-11-07 20:00:32 +00002450 CharUnits fieldSize;
2451 if (ci->isByRef())
2452 fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
2453 else
2454 fieldSize = CGM.getContext().getTypeSizeInChars(type);
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002455 UpdateRunSkipBlockVars(ci->isByRef(), getBlockCaptureLifetime(type, false),
Fariborz Jahanianc6abe9e2012-10-30 20:05:29 +00002456 fieldOffset, fieldSize);
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002457 }
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002458 return getBitmapBlockLayout(false);
2459}
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002460
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002461
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002462llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
2463 QualType T) {
2464 assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
2465 assert(!T->isArrayType() && "__block array variable should not be caught");
2466 CharUnits fieldOffset;
2467 RunSkipBlockVars.clear();
2468 bool hasUnion = false;
2469 if (const RecordType *record = T->getAs<RecordType>()) {
2470 BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */);
2471 llvm::Constant *Result = getBitmapBlockLayout(true);
2472 return Result;
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002473 }
Fariborz Jahanian3ca23d72012-11-14 17:15:51 +00002474 llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
2475 return nullPtr;
Fariborz Jahanianc46b4352012-10-27 21:10:38 +00002476}
2477
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002478llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00002479 const ObjCProtocolDecl *PD) {
Daniel Dunbarc67876d2008-09-04 04:33:15 +00002480 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00002481 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc67876d2008-09-04 04:33:15 +00002482 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2483
Owen Anderson3c4972d2009-07-29 18:54:39 +00002484 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Douglas Gregor4c86fdb2012-01-17 18:36:30 +00002485 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002486}
2487
Fariborz Jahanianda320092009-01-29 19:24:30 +00002488void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stumpf5408fe2009-05-16 07:57:57 +00002489 // FIXME: We shouldn't need this, the protocol decl should contain enough
2490 // information to tell us whether this was a declaration or a definition.
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002491 DefinedProtocols.insert(PD->getIdentifier());
2492
2493 // If we have generated a forward reference to this protocol, emit
2494 // it now. Otherwise do nothing, the protocol objects are lazily
2495 // emitted.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002496 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002497 GetOrEmitProtocol(PD);
2498}
2499
Fariborz Jahanianda320092009-01-29 19:24:30 +00002500llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002501 if (DefinedProtocols.count(PD->getIdentifier()))
2502 return GetOrEmitProtocol(PD);
Douglas Gregorf968d832011-05-27 01:19:52 +00002503
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002504 return GetOrEmitProtocolRef(PD);
2505}
2506
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002507/*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002508// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
2509struct _objc_protocol {
2510struct _objc_protocol_extension *isa;
2511char *protocol_name;
2512struct _objc_protocol_list *protocol_list;
2513struct _objc__method_prototype_list *instance_methods;
2514struct _objc__method_prototype_list *class_methods
2515};
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002516
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002517See EmitProtocolExtension().
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002518*/
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002519llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
John McCall50651b92012-03-30 21:29:05 +00002520 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002521
2522 // Early exit if a defining object has already been generated.
2523 if (Entry && Entry->hasInitializer())
2524 return Entry;
2525
Douglas Gregor1d784b22012-01-01 19:51:50 +00002526 // Use the protocol definition, if there is one.
2527 if (const ObjCProtocolDecl *Def = PD->getDefinition())
2528 PD = Def;
2529
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002530 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00002531 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002532 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
2533
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002534 // Construct method lists.
2535 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
2536 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilsondc8dab62011-11-30 01:57:58 +00002537 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002538 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002539 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002540 ObjCMethodDecl *MD = *i;
2541 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00002542 if (!C)
2543 return GetOrEmitProtocolRef(PD);
2544
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002545 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2546 OptInstanceMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00002547 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002548 } else {
2549 InstanceMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00002550 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002551 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002552 }
2553
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002554 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002555 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002556 ObjCMethodDecl *MD = *i;
2557 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00002558 if (!C)
2559 return GetOrEmitProtocolRef(PD);
2560
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002561 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
2562 OptClassMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00002563 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002564 } else {
2565 ClassMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00002566 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002567 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002568 }
2569
Bob Wilsondc8dab62011-11-30 01:57:58 +00002570 MethodTypesExt.insert(MethodTypesExt.end(),
2571 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
2572
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002573 llvm::Constant *Values[] = {
Bob Wilsondc8dab62011-11-30 01:57:58 +00002574 EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods,
2575 MethodTypesExt),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002576 GetClassName(PD->getIdentifier()),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002577 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardbc93372008-08-21 21:57:41 +00002578 PD->protocol_begin(),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002579 PD->protocol_end()),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002580 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002581 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002582 InstanceMethods),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002583 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002584 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002585 ClassMethods)
2586 };
Owen Anderson08e25242009-07-27 22:29:56 +00002587 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002588 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002589
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002590 if (Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002591 // Already created, fix the linkage and update the initializer.
2592 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002593 Entry->setInitializer(Init);
2594 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002595 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00002596 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002597 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002598 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002599 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002600 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002601 // FIXME: Is this necessary? Why only for protocol?
2602 Entry->setAlignment(4);
John McCall50651b92012-03-30 21:29:05 +00002603
2604 Protocols[PD->getIdentifier()] = Entry;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002605 }
Chris Lattnerad64e022009-07-17 23:57:13 +00002606 CGM.AddUsedGlobal(Entry);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002607
2608 return Entry;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002609}
2610
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002611llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002612 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
2613
2614 if (!Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002615 // We use the initializer as a marker of whether this is a forward
2616 // reference or not. At module finalization we add the empty
2617 // contents for protocols which were referenced but never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002618 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00002619 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002620 llvm::GlobalValue::ExternalLinkage,
2621 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002622 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002623 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002624 // FIXME: Is this necessary? Why only for protocol?
2625 Entry->setAlignment(4);
2626 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002627
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002628 return Entry;
2629}
2630
2631/*
2632 struct _objc_protocol_extension {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002633 uint32_t size;
2634 struct objc_method_description_list *optional_instance_methods;
2635 struct objc_method_description_list *optional_class_methods;
2636 struct objc_property_list *instance_properties;
Bob Wilsondc8dab62011-11-30 01:57:58 +00002637 const char ** extendedMethodTypes;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002638 };
2639*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002640llvm::Constant *
2641CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
Bill Wendlingbb028552012-02-07 09:25:09 +00002642 ArrayRef<llvm::Constant*> OptInstanceMethods,
2643 ArrayRef<llvm::Constant*> OptClassMethods,
2644 ArrayRef<llvm::Constant*> MethodTypesExt) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002645 uint64_t Size =
Micah Villmow25a6a842012-10-08 16:25:52 +00002646 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002647 llvm::Constant *Values[] = {
2648 llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002649 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002650 + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002651 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002652 OptInstanceMethods),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002653 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002654 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002655 OptClassMethods),
2656 EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
Bob Wilsondc8dab62011-11-30 01:57:58 +00002657 ObjCTypes),
2658 EmitProtocolMethodTypes("\01L_OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
2659 MethodTypesExt, ObjCTypes)
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002660 };
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002661
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002662 // Return null if no extension bits are used.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002663 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Bob Wilsondc8dab62011-11-30 01:57:58 +00002664 Values[3]->isNullValue() && Values[4]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002665 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002666
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002667 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00002668 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002669
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002670 // No special section, but goes in llvm.used
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002671 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002672 Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002673 0, 0, true);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002674}
2675
2676/*
2677 struct objc_protocol_list {
Bill Wendling3964e622012-02-09 22:16:49 +00002678 struct objc_protocol_list *next;
2679 long count;
2680 Protocol *list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002681 };
2682*/
Daniel Dunbardbc93372008-08-21 21:57:41 +00002683llvm::Constant *
Chris Lattner5f9e2722011-07-23 10:55:15 +00002684CGObjCMac::EmitProtocolList(Twine Name,
Daniel Dunbardbc93372008-08-21 21:57:41 +00002685 ObjCProtocolDecl::protocol_iterator begin,
2686 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendling3964e622012-02-09 22:16:49 +00002687 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002688
Daniel Dunbardbc93372008-08-21 21:57:41 +00002689 for (; begin != end; ++begin)
2690 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002691
2692 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002693 if (ProtocolRefs.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002694 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002695
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002696 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002697 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002698
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002699 llvm::Constant *Values[3];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002700 // This field is only used by the runtime.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002701 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002702 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002703 ProtocolRefs.size() - 1);
2704 Values[2] =
2705 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
2706 ProtocolRefs.size()),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002707 ProtocolRefs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002708
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002709 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002710 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002711 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002712 4, false);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002713 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002714}
2715
Bill Wendlingbb028552012-02-07 09:25:09 +00002716void CGObjCCommonMac::
2717PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*,16> &PropertySet,
Bill Wendling3964e622012-02-09 22:16:49 +00002718 llvm::SmallVectorImpl<llvm::Constant*> &Properties,
Bill Wendlingbb028552012-02-07 09:25:09 +00002719 const Decl *Container,
2720 const ObjCProtocolDecl *PROTO,
2721 const ObjCCommonTypesHelper &ObjCTypes) {
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002722 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
2723 E = PROTO->protocol_end(); P != E; ++P)
2724 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
2725 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
2726 E = PROTO->prop_end(); I != E; ++I) {
David Blaikie581deb32012-06-06 20:45:41 +00002727 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002728 if (!PropertySet.insert(PD->getIdentifier()))
2729 continue;
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002730 llvm::Constant *Prop[] = {
2731 GetPropertyName(PD->getIdentifier()),
2732 GetPropertyTypeString(PD, Container)
2733 };
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002734 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
2735 }
2736}
2737
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002738/*
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002739 struct _objc_property {
Bill Wendling3964e622012-02-09 22:16:49 +00002740 const char * const name;
2741 const char * const attributes;
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002742 };
2743
2744 struct _objc_property_list {
Bill Wendling3964e622012-02-09 22:16:49 +00002745 uint32_t entsize; // sizeof (struct _objc_property)
2746 uint32_t prop_count;
2747 struct _objc_property[prop_count];
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002748 };
2749*/
Chris Lattner5f9e2722011-07-23 10:55:15 +00002750llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002751 const Decl *Container,
2752 const ObjCContainerDecl *OCD,
2753 const ObjCCommonTypesHelper &ObjCTypes) {
Bill Wendling3964e622012-02-09 22:16:49 +00002754 llvm::SmallVector<llvm::Constant*, 16> Properties;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002755 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002756 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
2757 E = OCD->prop_end(); I != E; ++I) {
David Blaikie581deb32012-06-06 20:45:41 +00002758 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00002759 PropertySet.insert(PD->getIdentifier());
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002760 llvm::Constant *Prop[] = {
2761 GetPropertyName(PD->getIdentifier()),
2762 GetPropertyTypeString(PD, Container)
2763 };
Owen Anderson08e25242009-07-27 22:29:56 +00002764 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002765 Prop));
2766 }
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00002767 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek53b94412010-09-01 01:21:15 +00002768 for (ObjCInterfaceDecl::all_protocol_iterator
2769 P = OID->all_referenced_protocol_begin(),
2770 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00002771 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2772 ObjCTypes);
2773 }
2774 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2775 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
2776 E = CD->protocol_end(); P != E; ++P)
2777 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2778 ObjCTypes);
2779 }
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002780
2781 // Return null for empty list.
2782 if (Properties.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002783 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002784
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002785 unsigned PropertySize =
Micah Villmow25a6a842012-10-08 16:25:52 +00002786 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002787 llvm::Constant *Values[3];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002788 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2789 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002790 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002791 Properties.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002792 Values[2] = llvm::ConstantArray::get(AT, Properties);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002793 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002794
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002795 llvm::GlobalVariable *GV =
2796 CreateMetadataVar(Name, Init,
2797 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002798 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002799 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002800 true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002801 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002802}
2803
Bill Wendlingbb028552012-02-07 09:25:09 +00002804llvm::Constant *
2805CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
2806 ArrayRef<llvm::Constant*> MethodTypes,
2807 const ObjCCommonTypesHelper &ObjCTypes) {
Bob Wilsondc8dab62011-11-30 01:57:58 +00002808 // Return null for empty list.
2809 if (MethodTypes.empty())
2810 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);
2811
2812 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
2813 MethodTypes.size());
2814 llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);
2815
2816 llvm::GlobalVariable *GV =
2817 CreateMetadataVar(Name, Init,
2818 (ObjCABI == 2) ? "__DATA, __objc_const" : 0,
2819 (ObjCABI == 2) ? 8 : 4,
2820 true);
2821 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.Int8PtrPtrTy);
2822}
2823
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002824/*
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002825 struct objc_method_description_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002826 int count;
2827 struct objc_method_description list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002828 };
2829*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002830llvm::Constant *
2831CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002832 llvm::Constant *Desc[] = {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002833 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002834 ObjCTypes.SelectorPtrTy),
2835 GetMethodVarType(MD)
2836 };
Douglas Gregorf968d832011-05-27 01:19:52 +00002837 if (!Desc[1])
2838 return 0;
2839
Owen Anderson08e25242009-07-27 22:29:56 +00002840 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002841 Desc);
2842}
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002843
Bill Wendlingbb028552012-02-07 09:25:09 +00002844llvm::Constant *
2845CGObjCMac::EmitMethodDescList(Twine Name, const char *Section,
2846 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002847 // Return null for empty list.
2848 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002849 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002850
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002851 llvm::Constant *Values[2];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002852 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002853 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002854 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002855 Values[1] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002856 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002857
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002858 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002859 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002860 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002861}
2862
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002863/*
2864 struct _objc_category {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002865 char *category_name;
2866 char *class_name;
2867 struct _objc_method_list *instance_methods;
2868 struct _objc_method_list *class_methods;
2869 struct _objc_protocol_list *protocols;
2870 uint32_t size; // <rdar://4585769>
2871 struct _objc_property_list *instance_properties;
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002872 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002873*/
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00002874void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Micah Villmow25a6a842012-10-08 16:25:52 +00002875 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002876
Mike Stumpf5408fe2009-05-16 07:57:57 +00002877 // FIXME: This is poor design, the OCD should have a pointer to the category
2878 // decl. Additionally, note that Category can be null for the @implementation
2879 // w/o an @interface case. Sema should just create one for us as it does for
2880 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002881 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002882 const ObjCCategoryDecl *Category =
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002883 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002884
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002885 SmallString<256> ExtName;
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002886 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2887 << OCD->getName();
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002888
Bill Wendling3964e622012-02-09 22:16:49 +00002889 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002890 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002891 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002892 // Instance methods should always be defined.
2893 InstanceMethods.push_back(GetMethodConstant(*i));
2894 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002895 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002896 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002897 // Class methods should always be defined.
2898 ClassMethods.push_back(GetMethodConstant(*i));
2899 }
2900
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002901 llvm::Constant *Values[7];
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002902 Values[0] = GetClassName(OCD->getIdentifier());
2903 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahanian679cd7f2009-04-29 20:40:05 +00002904 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002905 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002906 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002907 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002908 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002909 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002910 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002911 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002912 ClassMethods);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002913 if (Category) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002914 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002915 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002916 Category->protocol_begin(),
2917 Category->protocol_end());
2918 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002919 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002920 }
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002921 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002922
2923 // If there is no category @interface then there can be no properties.
2924 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002925 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002926 OCD, Category, ObjCTypes);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002927 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002928 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002929 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002930
Owen Anderson08e25242009-07-27 22:29:56 +00002931 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002932 Values);
2933
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002934 llvm::GlobalVariable *GV =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002935 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002936 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002937 4, true);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002938 DefinedCategories.push_back(GV);
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00002939 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00002940 // method definition entries must be clear for next implementation.
2941 MethodDefinitions.clear();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002942}
2943
John McCall621915c2012-10-17 04:53:23 +00002944enum FragileClassFlags {
2945 FragileABI_Class_Factory = 0x00001,
2946 FragileABI_Class_Meta = 0x00002,
2947 FragileABI_Class_HasCXXStructors = 0x02000,
2948 FragileABI_Class_Hidden = 0x20000
2949};
2950
2951enum NonFragileClassFlags {
2952 /// Is a meta-class.
2953 NonFragileABI_Class_Meta = 0x00001,
2954
2955 /// Is a root class.
2956 NonFragileABI_Class_Root = 0x00002,
2957
2958 /// Has a C++ constructor and destructor.
2959 NonFragileABI_Class_HasCXXStructors = 0x00004,
2960
2961 /// Has hidden visibility.
2962 NonFragileABI_Class_Hidden = 0x00010,
2963
2964 /// Has the exception attribute.
2965 NonFragileABI_Class_Exception = 0x00020,
2966
2967 /// (Obsolete) ARC-specific: this class has a .release_ivars method
2968 NonFragileABI_Class_HasIvarReleaser = 0x00040,
2969
2970 /// Class implementation was compiled under ARC.
John McCallb03527a2012-10-17 04:53:31 +00002971 NonFragileABI_Class_CompiledByARC = 0x00080,
2972
2973 /// Class has non-trivial destructors, but zero-initialization is okay.
2974 NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002975};
2976
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002977/*
2978 struct _objc_class {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002979 Class isa;
2980 Class super_class;
2981 const char *name;
2982 long version;
2983 long info;
2984 long instance_size;
2985 struct _objc_ivar_list *ivars;
2986 struct _objc_method_list *methods;
2987 struct _objc_cache *cache;
2988 struct _objc_protocol_list *protocols;
2989 // Objective-C 1.0 extensions (<rdr://4585769>)
2990 const char *ivar_layout;
2991 struct _objc_class_ext *ext;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002992 };
2993
2994 See EmitClassExtension();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002995*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002996void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002997 DefinedSymbols.insert(ID->getIdentifier());
2998
Chris Lattner8ec03f52008-11-24 03:54:41 +00002999 std::string ClassName = ID->getNameAsString();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003000 // FIXME: Gross
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003001 ObjCInterfaceDecl *Interface =
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003002 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003003 llvm::Constant *Protocols =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003004 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00003005 Interface->all_referenced_protocol_begin(),
3006 Interface->all_referenced_protocol_end());
John McCall621915c2012-10-17 04:53:23 +00003007 unsigned Flags = FragileABI_Class_Factory;
John McCallb03527a2012-10-17 04:53:31 +00003008 if (ID->hasNonZeroConstructors() || ID->hasDestructors())
John McCall621915c2012-10-17 04:53:23 +00003009 Flags |= FragileABI_Class_HasCXXStructors;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003010 unsigned Size =
Ken Dyck5f022d82011-02-09 01:59:34 +00003011 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003012
3013 // FIXME: Set CXX-structors flag.
John McCall1fb0caa2010-10-22 21:05:15 +00003014 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCall621915c2012-10-17 04:53:23 +00003015 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003016
Bill Wendling3964e622012-02-09 22:16:49 +00003017 llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003018 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00003019 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003020 // Instance methods should always be defined.
3021 InstanceMethods.push_back(GetMethodConstant(*i));
3022 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003023 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00003024 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003025 // Class methods should always be defined.
3026 ClassMethods.push_back(GetMethodConstant(*i));
3027 }
3028
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003029 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00003030 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie581deb32012-06-06 20:45:41 +00003031 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003032
3033 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
3034 ObjCPropertyDecl *PD = PID->getPropertyDecl();
3035
3036 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
3037 if (llvm::Constant *C = GetMethodConstant(MD))
3038 InstanceMethods.push_back(C);
3039 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
3040 if (llvm::Constant *C = GetMethodConstant(MD))
3041 InstanceMethods.push_back(C);
3042 }
3043 }
3044
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003045 llvm::Constant *Values[12];
Daniel Dunbar5384b092009-05-03 08:56:52 +00003046 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003047 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003048 // Record a reference to the super class.
3049 LazySymbols.insert(Super->getIdentifier());
3050
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003051 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003052 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003053 ObjCTypes.ClassPtrTy);
3054 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00003055 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003056 }
3057 Values[ 2] = GetClassName(ID->getIdentifier());
3058 // Version is always 0.
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003059 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3060 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3061 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00003062 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003063 Values[ 7] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003064 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003065 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003066 InstanceMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003067 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00003068 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003069 Values[ 9] = Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003070 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003071 Values[11] = EmitClassExtension(ID);
Owen Anderson08e25242009-07-27 22:29:56 +00003072 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003073 Values);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00003074 std::string Name("\01L_OBJC_CLASS_");
3075 Name += ClassName;
3076 const char *Section = "__OBJC,__class,regular,no_dead_strip";
3077 // Check for a forward reference.
3078 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
3079 if (GV) {
3080 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3081 "Forward metaclass reference has incorrect type.");
3082 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
3083 GV->setInitializer(Init);
3084 GV->setSection(Section);
3085 GV->setAlignment(4);
3086 CGM.AddUsedGlobal(GV);
3087 }
3088 else
3089 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003090 DefinedClasses.push_back(GV);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00003091 // method definition entries must be clear for next implementation.
3092 MethodDefinitions.clear();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003093}
3094
3095llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
3096 llvm::Constant *Protocols,
Bill Wendlingbb028552012-02-07 09:25:09 +00003097 ArrayRef<llvm::Constant*> Methods) {
John McCall621915c2012-10-17 04:53:23 +00003098 unsigned Flags = FragileABI_Class_Meta;
Micah Villmow25a6a842012-10-08 16:25:52 +00003099 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003100
John McCall1fb0caa2010-10-22 21:05:15 +00003101 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
John McCall621915c2012-10-17 04:53:23 +00003102 Flags |= FragileABI_Class_Hidden;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003103
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003104 llvm::Constant *Values[12];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003105 // The isa for the metaclass is the root of the hierarchy.
3106 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3107 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3108 Root = Super;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003109 Values[ 0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003110 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003111 ObjCTypes.ClassPtrTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003112 // The super class for the metaclass is emitted as the name of the
3113 // super class. The runtime fixes this up to point to the
3114 // *metaclass* for the super class.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003115 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003116 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003117 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003118 ObjCTypes.ClassPtrTy);
3119 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00003120 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003121 }
3122 Values[ 2] = GetClassName(ID->getIdentifier());
3123 // Version is always 0.
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003124 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
3125 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
3126 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00003127 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003128 Values[ 7] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00003129 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003130 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003131 Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003132 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00003133 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003134 Values[ 9] = Protocols;
3135 // ivar_layout for metaclass is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00003136 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003137 // The class extension is always unused for metaclasses.
Owen Andersonc9c88b42009-07-31 20:28:54 +00003138 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00003139 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003140 Values);
3141
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003142 std::string Name("\01L_OBJC_METACLASS_");
Benjamin Kramer94be8ea2012-07-31 11:45:39 +00003143 Name += ID->getName();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003144
3145 // Check for a forward reference.
3146 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
3147 if (GV) {
3148 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3149 "Forward metaclass reference has incorrect type.");
3150 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
3151 GV->setInitializer(Init);
3152 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00003153 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003154 llvm::GlobalValue::InternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00003155 Init, Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003156 }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003157 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbar58a29122009-03-09 22:18:41 +00003158 GV->setAlignment(4);
Chris Lattnerad64e022009-07-17 23:57:13 +00003159 CGM.AddUsedGlobal(GV);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003160
3161 return GV;
3162}
3163
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003164llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00003165 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003166
Mike Stumpf5408fe2009-05-16 07:57:57 +00003167 // FIXME: Should we look these up somewhere other than the module. Its a bit
3168 // silly since we only generate these while processing an implementation, so
3169 // exactly one pointer would work if know when we entered/exitted an
3170 // implementation block.
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003171
3172 // Check for an existing forward reference.
Fariborz Jahanianb0d27942009-01-07 20:11:22 +00003173 // Previously, metaclass with internal linkage may have been defined.
3174 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003175 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
3176 true)) {
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003177 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3178 "Forward metaclass reference has incorrect type.");
3179 return GV;
3180 } else {
3181 // Generate as an external reference to keep a consistent
3182 // module. This will be patched up when we emit the metaclass.
Owen Anderson1c431b32009-07-08 19:05:04 +00003183 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003184 llvm::GlobalValue::ExternalLinkage,
3185 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00003186 Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00003187 }
3188}
3189
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00003190llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
3191 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
3192
3193 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
3194 true)) {
3195 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
3196 "Forward class metadata reference has incorrect type.");
3197 return GV;
3198 } else {
3199 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
3200 llvm::GlobalValue::ExternalLinkage,
3201 0,
3202 Name);
3203 }
3204}
3205
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003206/*
3207 struct objc_class_ext {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003208 uint32_t size;
3209 const char *weak_ivar_layout;
3210 struct _objc_property_list *properties;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003211 };
3212*/
3213llvm::Constant *
3214CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003215 uint64_t Size =
Micah Villmow25a6a842012-10-08 16:25:52 +00003216 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003217
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003218 llvm::Constant *Values[3];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003219 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanianc71303d2009-04-22 23:00:43 +00003220 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003221 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00003222 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003223
3224 // Return null if no extension bits are used.
3225 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00003226 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003227
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003228 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00003229 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003230 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003231 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003232 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003233}
3234
3235/*
3236 struct objc_ivar {
Bill Wendling795b1002012-02-22 09:30:11 +00003237 char *ivar_name;
3238 char *ivar_type;
3239 int ivar_offset;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003240 };
3241
3242 struct objc_ivar_list {
Bill Wendling795b1002012-02-22 09:30:11 +00003243 int ivar_count;
3244 struct objc_ivar list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003245 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003246*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003247llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00003248 bool ForClass) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003249 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003250
3251 // When emitting the root class GCC emits ivar entries for the
3252 // actual class structure. It is not clear if we need to follow this
3253 // behavior; for now lets try and get away with not doing it. If so,
3254 // the cleanest solution would be to make up an ObjCInterfaceDecl
3255 // for the class.
3256 if (ForClass)
Owen Andersonc9c88b42009-07-31 20:28:54 +00003257 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003258
Jordy Rosedb8264e2011-07-22 02:08:32 +00003259 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003260
Jordy Rosedb8264e2011-07-22 02:08:32 +00003261 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00003262 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00003263 // Ignore unnamed bit-fields.
3264 if (!IVD->getDeclName())
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003265 continue;
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003266 llvm::Constant *Ivar[] = {
3267 GetMethodVarName(IVD->getIdentifier()),
3268 GetMethodVarType(IVD),
3269 llvm::ConstantInt::get(ObjCTypes.IntTy,
Eli Friedmane5b46662012-11-06 22:15:52 +00003270 ComputeIvarBaseOffset(CGM, OID, IVD))
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003271 };
Owen Anderson08e25242009-07-27 22:29:56 +00003272 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003273 }
3274
3275 // Return null for empty list.
3276 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00003277 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003278
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003279 llvm::Constant *Values[2];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003280 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00003281 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003282 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00003283 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003284 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003285
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003286 llvm::GlobalVariable *GV;
3287 if (ForClass)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003288 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003289 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00003290 4, true);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003291 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003292 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003293 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003294 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00003295 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003296}
3297
3298/*
3299 struct objc_method {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003300 SEL method_name;
3301 char *method_types;
3302 void *method;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003303 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003304
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003305 struct objc_method_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003306 struct objc_method_list *obsolete;
3307 int count;
3308 struct objc_method methods_list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003309 };
3310*/
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003311
3312/// GetMethodConstant - Return a struct objc_method constant for the
3313/// given method if it has been defined. The result is null if the
3314/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +00003315llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00003316 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003317 if (!Fn)
3318 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003319
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003320 llvm::Constant *Method[] = {
Owen Anderson3c4972d2009-07-29 18:54:39 +00003321 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003322 ObjCTypes.SelectorPtrTy),
3323 GetMethodVarType(MD),
3324 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
3325 };
Owen Anderson08e25242009-07-27 22:29:56 +00003326 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003327}
3328
Chris Lattner5f9e2722011-07-23 10:55:15 +00003329llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003330 const char *Section,
Bill Wendlingbb028552012-02-07 09:25:09 +00003331 ArrayRef<llvm::Constant*> Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003332 // Return null for empty list.
3333 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00003334 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003335
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003336 llvm::Constant *Values[3];
Owen Andersonc9c88b42009-07-31 20:28:54 +00003337 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003338 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00003339 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003340 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00003341 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003342 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003343
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003344 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003345 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003346}
3347
Fariborz Jahanian493dab72009-01-26 21:38:32 +00003348llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003349 const ObjCContainerDecl *CD) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00003350 SmallString<256> Name;
Fariborz Jahanian679a5022009-01-10 21:06:09 +00003351 GetNameForMethod(OMD, CD, Name);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003352
Daniel Dunbar541b63b2009-02-02 23:23:47 +00003353 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2acc6e32011-07-18 04:24:23 +00003354 llvm::FunctionType *MethodTy =
John McCallde5d3c72012-02-17 03:33:10 +00003355 Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003356 llvm::Function *Method =
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00003357 llvm::Function::Create(MethodTy,
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003358 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00003359 Name.str(),
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003360 &CGM.getModule());
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003361 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003362
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003363 return Method;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00003364}
3365
Daniel Dunbarfd65d372009-03-09 20:09:19 +00003366llvm::GlobalVariable *
Chris Lattner5f9e2722011-07-23 10:55:15 +00003367CGObjCCommonMac::CreateMetadataVar(Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +00003368 llvm::Constant *Init,
3369 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +00003370 unsigned Align,
3371 bool AddToUsed) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00003372 llvm::Type *Ty = Init->getType();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003373 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00003374 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerad64e022009-07-17 23:57:13 +00003375 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00003376 if (Section)
3377 GV->setSection(Section);
Daniel Dunbar35bd7632009-03-09 20:50:13 +00003378 if (Align)
3379 GV->setAlignment(Align);
3380 if (AddToUsed)
Chris Lattnerad64e022009-07-17 23:57:13 +00003381 CGM.AddUsedGlobal(GV);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00003382 return GV;
3383}
3384
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003385llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003386 // Abuse this interface function as a place to finalize.
3387 FinishModule();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00003388 return NULL;
3389}
3390
Chris Lattner74391b42009-03-22 21:03:39 +00003391llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00003392 return ObjCTypes.getGetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00003393}
3394
Chris Lattner74391b42009-03-22 21:03:39 +00003395llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00003396 return ObjCTypes.getSetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00003397}
3398
Ted Kremenekebcb57a2012-03-06 20:05:56 +00003399llvm::Constant *CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
3400 bool copy) {
3401 return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
3402}
3403
David Chisnall8fac25d2010-12-26 22:13:16 +00003404llvm::Constant *CGObjCMac::GetGetStructFunction() {
3405 return ObjCTypes.getCopyStructFn();
3406}
3407llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00003408 return ObjCTypes.getCopyStructFn();
3409}
3410
Fariborz Jahaniane3173022012-01-06 18:07:23 +00003411llvm::Constant *CGObjCMac::GetCppAtomicObjectFunction() {
3412 return ObjCTypes.getCppAtomicObjectFunction();
3413}
3414
Chris Lattner74391b42009-03-22 21:03:39 +00003415llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00003416 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson2abd89c2008-08-31 04:05:03 +00003417}
3418
John McCallf1549f62010-07-06 01:34:17 +00003419void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
3420 return EmitTryOrSynchronizedStmt(CGF, S);
3421}
3422
3423void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
3424 const ObjCAtSynchronizedStmt &S) {
3425 return EmitTryOrSynchronizedStmt(CGF, S);
3426}
3427
John McCallcc505292010-07-21 06:59:36 +00003428namespace {
John McCall1f0fca52010-07-21 07:22:38 +00003429 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCallcc505292010-07-21 06:59:36 +00003430 const Stmt &S;
John McCall0b251722010-08-04 05:59:32 +00003431 llvm::Value *SyncArgSlot;
John McCallcc505292010-07-21 06:59:36 +00003432 llvm::Value *CallTryExitVar;
3433 llvm::Value *ExceptionData;
3434 ObjCTypesHelper &ObjCTypes;
3435 PerformFragileFinally(const Stmt *S,
John McCall0b251722010-08-04 05:59:32 +00003436 llvm::Value *SyncArgSlot,
John McCallcc505292010-07-21 06:59:36 +00003437 llvm::Value *CallTryExitVar,
3438 llvm::Value *ExceptionData,
3439 ObjCTypesHelper *ObjCTypes)
John McCall0b251722010-08-04 05:59:32 +00003440 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCallcc505292010-07-21 06:59:36 +00003441 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
3442
John McCallad346f42011-07-12 20:27:29 +00003443 void Emit(CodeGenFunction &CGF, Flags flags) {
John McCallcc505292010-07-21 06:59:36 +00003444 // Check whether we need to call objc_exception_try_exit.
3445 // In optimized code, this branch will always be folded.
3446 llvm::BasicBlock *FinallyCallExit =
3447 CGF.createBasicBlock("finally.call_exit");
3448 llvm::BasicBlock *FinallyNoCallExit =
3449 CGF.createBasicBlock("finally.no_call_exit");
3450 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
3451 FinallyCallExit, FinallyNoCallExit);
3452
3453 CGF.EmitBlock(FinallyCallExit);
3454 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
3455 ->setDoesNotThrow();
3456
3457 CGF.EmitBlock(FinallyNoCallExit);
3458
3459 if (isa<ObjCAtTryStmt>(S)) {
3460 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCalld96a8e72010-08-11 00:16:14 +00003461 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
3462 // Save the current cleanup destination in case there's
3463 // control flow inside the finally statement.
3464 llvm::Value *CurCleanupDest =
3465 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
3466
John McCallcc505292010-07-21 06:59:36 +00003467 CGF.EmitStmt(FinallyStmt->getFinallyBody());
3468
John McCalld96a8e72010-08-11 00:16:14 +00003469 if (CGF.HaveInsertPoint()) {
3470 CGF.Builder.CreateStore(CurCleanupDest,
3471 CGF.getNormalCleanupDestSlot());
3472 } else {
3473 // Currently, the end of the cleanup must always exist.
3474 CGF.EnsureInsertPoint();
3475 }
3476 }
John McCallcc505292010-07-21 06:59:36 +00003477 } else {
3478 // Emit objc_sync_exit(expr); as finally's sole statement for
3479 // @synchronized.
John McCall0b251722010-08-04 05:59:32 +00003480 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCallcc505292010-07-21 06:59:36 +00003481 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
3482 ->setDoesNotThrow();
3483 }
3484 }
3485 };
John McCall87bb5822010-07-31 23:20:56 +00003486
3487 class FragileHazards {
3488 CodeGenFunction &CGF;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003489 SmallVector<llvm::Value*, 20> Locals;
John McCall87bb5822010-07-31 23:20:56 +00003490 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
3491
3492 llvm::InlineAsm *ReadHazard;
3493 llvm::InlineAsm *WriteHazard;
3494
3495 llvm::FunctionType *GetAsmFnType();
3496
3497 void collectLocals();
3498 void emitReadHazard(CGBuilderTy &Builder);
3499
3500 public:
3501 FragileHazards(CodeGenFunction &CGF);
John McCall0b251722010-08-04 05:59:32 +00003502
John McCall87bb5822010-07-31 23:20:56 +00003503 void emitWriteHazard();
John McCall0b251722010-08-04 05:59:32 +00003504 void emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00003505 };
3506}
3507
3508/// Create the fragile-ABI read and write hazards based on the current
3509/// state of the function, which is presumed to be immediately prior
3510/// to a @try block. These hazards are used to maintain correct
3511/// semantics in the face of optimization and the fragile ABI's
3512/// cavalier use of setjmp/longjmp.
3513FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
3514 collectLocals();
3515
3516 if (Locals.empty()) return;
3517
3518 // Collect all the blocks in the function.
3519 for (llvm::Function::iterator
3520 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
3521 BlocksBeforeTry.insert(&*I);
3522
3523 llvm::FunctionType *AsmFnTy = GetAsmFnType();
3524
3525 // Create a read hazard for the allocas. This inhibits dead-store
3526 // optimizations and forces the values to memory. This hazard is
3527 // inserted before any 'throwing' calls in the protected scope to
3528 // reflect the possibility that the variables might be read from the
3529 // catch block if the call throws.
3530 {
3531 std::string Constraint;
3532 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3533 if (I) Constraint += ',';
3534 Constraint += "*m";
3535 }
3536
3537 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3538 }
3539
3540 // Create a write hazard for the allocas. This inhibits folding
3541 // loads across the hazard. This hazard is inserted at the
3542 // beginning of the catch path to reflect the possibility that the
3543 // variables might have been written within the protected scope.
3544 {
3545 std::string Constraint;
3546 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
3547 if (I) Constraint += ',';
3548 Constraint += "=*m";
3549 }
3550
3551 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
3552 }
3553}
3554
3555/// Emit a write hazard at the current location.
3556void FragileHazards::emitWriteHazard() {
3557 if (Locals.empty()) return;
3558
Jay Foad4c7d9f12011-07-15 08:37:34 +00003559 CGF.Builder.CreateCall(WriteHazard, Locals)->setDoesNotThrow();
John McCall87bb5822010-07-31 23:20:56 +00003560}
3561
John McCall87bb5822010-07-31 23:20:56 +00003562void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
3563 assert(!Locals.empty());
Jay Foad4c7d9f12011-07-15 08:37:34 +00003564 Builder.CreateCall(ReadHazard, Locals)->setDoesNotThrow();
John McCall87bb5822010-07-31 23:20:56 +00003565}
3566
3567/// Emit read hazards in all the protected blocks, i.e. all the blocks
3568/// which have been inserted since the beginning of the try.
John McCall0b251722010-08-04 05:59:32 +00003569void FragileHazards::emitHazardsInNewBlocks() {
John McCall87bb5822010-07-31 23:20:56 +00003570 if (Locals.empty()) return;
3571
3572 CGBuilderTy Builder(CGF.getLLVMContext());
3573
3574 // Iterate through all blocks, skipping those prior to the try.
3575 for (llvm::Function::iterator
3576 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
3577 llvm::BasicBlock &BB = *FI;
3578 if (BlocksBeforeTry.count(&BB)) continue;
3579
3580 // Walk through all the calls in the block.
3581 for (llvm::BasicBlock::iterator
3582 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
3583 llvm::Instruction &I = *BI;
3584
3585 // Ignore instructions that aren't non-intrinsic calls.
3586 // These are the only calls that can possibly call longjmp.
3587 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
3588 if (isa<llvm::IntrinsicInst>(I))
3589 continue;
3590
3591 // Ignore call sites marked nounwind. This may be questionable,
3592 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
3593 llvm::CallSite CS(&I);
3594 if (CS.doesNotThrow()) continue;
3595
John McCall0b251722010-08-04 05:59:32 +00003596 // Insert a read hazard before the call. This will ensure that
3597 // any writes to the locals are performed before making the
3598 // call. If the call throws, then this is sufficient to
3599 // guarantee correctness as long as it doesn't also write to any
3600 // locals.
John McCall87bb5822010-07-31 23:20:56 +00003601 Builder.SetInsertPoint(&BB, BI);
3602 emitReadHazard(Builder);
3603 }
3604 }
3605}
3606
3607static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
3608 if (V) S.insert(V);
3609}
3610
3611void FragileHazards::collectLocals() {
3612 // Compute a set of allocas to ignore.
3613 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
3614 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
3615 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall87bb5822010-07-31 23:20:56 +00003616
3617 // Collect all the allocas currently in the function. This is
3618 // probably way too aggressive.
3619 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
3620 for (llvm::BasicBlock::iterator
3621 I = Entry.begin(), E = Entry.end(); I != E; ++I)
3622 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
3623 Locals.push_back(&*I);
3624}
3625
3626llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner5f9e2722011-07-23 10:55:15 +00003627 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall0774cb82011-05-15 01:53:33 +00003628 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
3629 tys[i] = Locals[i]->getType();
3630 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCallcc505292010-07-21 06:59:36 +00003631}
3632
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003633/*
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003634
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003635 Objective-C setjmp-longjmp (sjlj) Exception Handling
3636 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003637
John McCallf1549f62010-07-06 01:34:17 +00003638 A catch buffer is a setjmp buffer plus:
3639 - a pointer to the exception that was caught
3640 - a pointer to the previous exception data buffer
3641 - two pointers of reserved storage
3642 Therefore catch buffers form a stack, with a pointer to the top
3643 of the stack kept in thread-local storage.
3644
3645 objc_exception_try_enter pushes a catch buffer onto the EH stack.
3646 objc_exception_try_exit pops the given catch buffer, which is
3647 required to be the top of the EH stack.
3648 objc_exception_throw pops the top of the EH stack, writes the
3649 thrown exception into the appropriate field, and longjmps
3650 to the setjmp buffer. It crashes the process (with a printf
3651 and an abort()) if there are no catch buffers on the stack.
3652 objc_exception_extract just reads the exception pointer out of the
3653 catch buffer.
3654
3655 There's no reason an implementation couldn't use a light-weight
3656 setjmp here --- something like __builtin_setjmp, but API-compatible
3657 with the heavyweight setjmp. This will be more important if we ever
3658 want to implement correct ObjC/C++ exception interactions for the
3659 fragile ABI.
3660
3661 Note that for this use of setjmp/longjmp to be correct, we may need
3662 to mark some local variables volatile: if a non-volatile local
3663 variable is modified between the setjmp and the longjmp, it has
3664 indeterminate value. For the purposes of LLVM IR, it may be
3665 sufficient to make loads and stores within the @try (to variables
3666 declared outside the @try) volatile. This is necessary for
3667 optimized correctness, but is not currently being done; this is
3668 being tracked as rdar://problem/8160285
3669
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003670 The basic framework for a @try-catch-finally is as follows:
3671 {
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003672 objc_exception_data d;
3673 id _rethrow = null;
Anders Carlsson190d00e2009-02-07 21:26:04 +00003674 bool _call_try_exit = true;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003675
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003676 objc_exception_try_enter(&d);
3677 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003678 ... try body ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003679 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003680 // exception path
3681 id _caught = objc_exception_extract(&d);
3682
3683 // enter new try scope for handlers
3684 if (!setjmp(d.jmp_buf)) {
3685 ... match exception and execute catch blocks ...
3686
3687 // fell off end, rethrow.
3688 _rethrow = _caught;
3689 ... jump-through-finally to finally_rethrow ...
3690 } else {
3691 // exception in catch block
3692 _rethrow = objc_exception_extract(&d);
3693 _call_try_exit = false;
3694 ... jump-through-finally to finally_rethrow ...
3695 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003696 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00003697 ... jump-through-finally to finally_end ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003698
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003699 finally:
Anders Carlsson190d00e2009-02-07 21:26:04 +00003700 if (_call_try_exit)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003701 objc_exception_try_exit(&d);
Anders Carlsson190d00e2009-02-07 21:26:04 +00003702
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003703 ... finally block ....
Daniel Dunbar898d5082008-09-30 01:06:03 +00003704 ... dispatch to finally destination ...
3705
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003706 finally_rethrow:
Daniel Dunbar898d5082008-09-30 01:06:03 +00003707 objc_exception_throw(_rethrow);
3708
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003709 finally_end:
3710 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003711
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003712 This framework differs slightly from the one gcc uses, in that gcc
3713 uses _rethrow to determine if objc_exception_try_exit should be called
3714 and if the object should be rethrown. This breaks in the face of
3715 throwing nil and introduces unnecessary branches.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003716
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003717 We specialize this framework for a few particular circumstances:
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003718
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003719 - If there are no catch blocks, then we avoid emitting the second
3720 exception handling context.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003721
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003722 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
3723 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003724
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003725 - FIXME: If there is no @finally block we can do a few more
3726 simplifications.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003727
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003728 Rethrows and Jumps-Through-Finally
3729 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003730
John McCallf1549f62010-07-06 01:34:17 +00003731 '@throw;' is supported by pushing the currently-caught exception
3732 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003733
John McCallf1549f62010-07-06 01:34:17 +00003734 Branches through the @finally block are handled with an ordinary
3735 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
3736 exceptions are not compatible with C++ exceptions, and this is
3737 hardly the only place where this will go wrong.
Daniel Dunbar898d5082008-09-30 01:06:03 +00003738
John McCallf1549f62010-07-06 01:34:17 +00003739 @synchronized(expr) { stmt; } is emitted as if it were:
3740 id synch_value = expr;
3741 objc_sync_enter(synch_value);
3742 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003743*/
3744
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00003745void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
3746 const Stmt &S) {
3747 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallf1549f62010-07-06 01:34:17 +00003748
3749 // A destination for the fall-through edges of the catch handlers to
3750 // jump to.
3751 CodeGenFunction::JumpDest FinallyEnd =
3752 CGF.getJumpDestInCurrentScope("finally.end");
3753
3754 // A destination for the rethrow edge of the catch handlers to jump
3755 // to.
3756 CodeGenFunction::JumpDest FinallyRethrow =
3757 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003758
Daniel Dunbar1c566672009-02-24 01:43:46 +00003759 // For @synchronized, call objc_sync_enter(sync.expr). The
3760 // evaluation of the expression must occur before we enter the
John McCall0b251722010-08-04 05:59:32 +00003761 // @synchronized. We can't avoid a temp here because we need the
3762 // value to be preserved. If the backend ever does liveness
3763 // correctly after setjmp, this will be unnecessary.
3764 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar1c566672009-02-24 01:43:46 +00003765 if (!isTry) {
John McCall0b251722010-08-04 05:59:32 +00003766 llvm::Value *SyncArg =
Daniel Dunbar1c566672009-02-24 01:43:46 +00003767 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
3768 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallf1549f62010-07-06 01:34:17 +00003769 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
3770 ->setDoesNotThrow();
John McCall0b251722010-08-04 05:59:32 +00003771
3772 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
3773 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar1c566672009-02-24 01:43:46 +00003774 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00003775
John McCall0b251722010-08-04 05:59:32 +00003776 // Allocate memory for the setjmp buffer. This needs to be kept
3777 // live throughout the try and catch blocks.
3778 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
3779 "exceptiondata.ptr");
3780
John McCall87bb5822010-07-31 23:20:56 +00003781 // Create the fragile hazards. Note that this will not capture any
3782 // of the allocas required for exception processing, but will
3783 // capture the current basic block (which extends all the way to the
3784 // setjmp call) as "before the @try".
3785 FragileHazards Hazards(CGF);
3786
John McCallf1549f62010-07-06 01:34:17 +00003787 // Create a flag indicating whether the cleanup needs to call
3788 // objc_exception_try_exit. This is true except when
3789 // - no catches match and we're branching through the cleanup
3790 // just to rethrow the exception, or
3791 // - a catch matched and we're falling out of the catch handler.
John McCall0b251722010-08-04 05:59:32 +00003792 // The setjmp-safety rule here is that we should always store to this
3793 // variable in a place that dominates the branch through the cleanup
3794 // without passing through any setjmps.
John McCallf1549f62010-07-06 01:34:17 +00003795 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlsson190d00e2009-02-07 21:26:04 +00003796 "_call_try_exit");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003797
John McCall9e2213d2010-10-04 23:42:51 +00003798 // A slot containing the exception to rethrow. Only needed when we
3799 // have both a @catch and a @finally.
3800 llvm::Value *PropagatingExnVar = 0;
3801
John McCallf1549f62010-07-06 01:34:17 +00003802 // Push a normal cleanup to leave the try scope.
John McCall1f0fca52010-07-21 07:22:38 +00003803 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall0b251722010-08-04 05:59:32 +00003804 SyncArgSlot,
John McCall1f0fca52010-07-21 07:22:38 +00003805 CallTryExitVar,
3806 ExceptionData,
3807 &ObjCTypes);
John McCallf1549f62010-07-06 01:34:17 +00003808
3809 // Enter a try block:
3810 // - Call objc_exception_try_enter to push ExceptionData on top of
3811 // the EH stack.
3812 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3813 ->setDoesNotThrow();
3814
3815 // - Call setjmp on the exception data buffer.
3816 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3817 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3818 llvm::Value *SetJmpBuffer =
Jay Foad0f6ac7c2011-07-22 08:16:57 +00003819 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
John McCallf1549f62010-07-06 01:34:17 +00003820 llvm::CallInst *SetJmpResult =
3821 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3822 SetJmpResult->setDoesNotThrow();
Bill Wendling6446c3e2011-12-19 23:53:28 +00003823 SetJmpResult->setCanReturnTwice();
John McCallf1549f62010-07-06 01:34:17 +00003824
3825 // If setjmp returned 0, enter the protected block; otherwise,
3826 // branch to the handler.
Daniel Dunbar55e87422008-11-11 02:29:29 +00003827 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3828 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallf1549f62010-07-06 01:34:17 +00003829 llvm::Value *DidCatch =
John McCalld96a8e72010-08-11 00:16:14 +00003830 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3831 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson80f25672008-09-09 17:59:25 +00003832
John McCallf1549f62010-07-06 01:34:17 +00003833 // Emit the protected block.
Anders Carlsson80f25672008-09-09 17:59:25 +00003834 CGF.EmitBlock(TryBlock);
John McCall0b251722010-08-04 05:59:32 +00003835 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003836 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallf1549f62010-07-06 01:34:17 +00003837 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall0b251722010-08-04 05:59:32 +00003838
3839 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003840
John McCallf1549f62010-07-06 01:34:17 +00003841 // Emit the exception handler block.
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003842 CGF.EmitBlock(TryHandler);
Daniel Dunbar55e40722008-09-27 07:03:52 +00003843
John McCall87bb5822010-07-31 23:20:56 +00003844 // Don't optimize loads of the in-scope locals across this point.
3845 Hazards.emitWriteHazard();
3846
John McCallf1549f62010-07-06 01:34:17 +00003847 // For a @synchronized (or a @try with no catches), just branch
3848 // through the cleanup to the rethrow block.
3849 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3850 // Tell the cleanup not to re-pop the exit.
John McCall0b251722010-08-04 05:59:32 +00003851 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003852 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallf1549f62010-07-06 01:34:17 +00003853
3854 // Otherwise, we have to match against the caught exceptions.
3855 } else {
John McCall0b251722010-08-04 05:59:32 +00003856 // Retrieve the exception object. We may emit multiple blocks but
3857 // nothing can cross this so the value is already in SSA form.
3858 llvm::CallInst *Caught =
3859 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3860 ExceptionData, "caught");
3861 Caught->setDoesNotThrow();
3862
John McCallf1549f62010-07-06 01:34:17 +00003863 // Push the exception to rethrow onto the EH value stack for the
3864 // benefit of any @throws in the handlers.
3865 CGF.ObjCEHValueStack.push_back(Caught);
3866
Douglas Gregor8f5e3dd2010-04-23 22:50:49 +00003867 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003868
John McCall0b251722010-08-04 05:59:32 +00003869 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallf1549f62010-07-06 01:34:17 +00003870
John McCall0b251722010-08-04 05:59:32 +00003871 llvm::BasicBlock *CatchBlock = 0;
3872 llvm::BasicBlock *CatchHandler = 0;
3873 if (HasFinally) {
John McCall9e2213d2010-10-04 23:42:51 +00003874 // Save the currently-propagating exception before
3875 // objc_exception_try_enter clears the exception slot.
3876 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3877 "propagating_exception");
3878 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3879
John McCall0b251722010-08-04 05:59:32 +00003880 // Enter a new exception try block (in case a @catch block
3881 // throws an exception).
3882 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3883 ->setDoesNotThrow();
Anders Carlsson80f25672008-09-09 17:59:25 +00003884
John McCall0b251722010-08-04 05:59:32 +00003885 llvm::CallInst *SetJmpResult =
3886 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3887 "setjmp.result");
3888 SetJmpResult->setDoesNotThrow();
Bill Wendling6446c3e2011-12-19 23:53:28 +00003889 SetJmpResult->setCanReturnTwice();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003890
John McCall0b251722010-08-04 05:59:32 +00003891 llvm::Value *Threw =
3892 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3893
3894 CatchBlock = CGF.createBasicBlock("catch");
3895 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3896 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3897
3898 CGF.EmitBlock(CatchBlock);
3899 }
3900
3901 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003902
Daniel Dunbar55e40722008-09-27 07:03:52 +00003903 // Handle catch list. As a special case we check if everything is
3904 // matched and avoid generating code for falling off the end if
3905 // so.
3906 bool AllMatched = false;
Douglas Gregor8f5e3dd2010-04-23 22:50:49 +00003907 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3908 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson80f25672008-09-09 17:59:25 +00003909
Douglas Gregorc00d8e12010-04-26 16:46:50 +00003910 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff14108da2009-07-10 23:34:53 +00003911 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar129271a2008-09-27 07:36:24 +00003912
Anders Carlsson80f25672008-09-09 17:59:25 +00003913 // catch(...) always matches.
Daniel Dunbar55e40722008-09-27 07:03:52 +00003914 if (!CatchParam) {
3915 AllMatched = true;
3916 } else {
John McCall183700f2009-09-21 23:43:11 +00003917 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003918
John McCallf1549f62010-07-06 01:34:17 +00003919 // catch(id e) always matches under this ABI, since only
3920 // ObjC exceptions end up here in the first place.
Daniel Dunbar97f61d12008-09-27 22:21:14 +00003921 // FIXME: For the time being we also match id<X>; this should
3922 // be rejected by Sema instead.
Eli Friedman818e96f2009-07-11 00:57:02 +00003923 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbar55e40722008-09-27 07:03:52 +00003924 AllMatched = true;
Anders Carlsson80f25672008-09-09 17:59:25 +00003925 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003926
John McCallf1549f62010-07-06 01:34:17 +00003927 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003928 if (AllMatched) {
John McCallf1549f62010-07-06 01:34:17 +00003929 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3930
Anders Carlssondde0a942008-09-11 09:15:33 +00003931 if (CatchParam) {
John McCallb6bbcc92010-10-15 04:57:14 +00003932 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003933 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallf1549f62010-07-06 01:34:17 +00003934
3935 // These types work out because ConvertType(id) == i8*.
Steve Naroff7ba138a2009-03-03 19:52:17 +00003936 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlssondde0a942008-09-11 09:15:33 +00003937 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003938
Anders Carlssondde0a942008-09-11 09:15:33 +00003939 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003940
3941 // The scope of the catch variable ends right here.
3942 CatchVarCleanups.ForceCleanup();
3943
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003944 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson80f25672008-09-09 17:59:25 +00003945 break;
3946 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003947
Steve Naroff14108da2009-07-10 23:34:53 +00003948 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall506b57e2010-05-17 21:00:27 +00003949 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallf1549f62010-07-06 01:34:17 +00003950
3951 // FIXME: @catch (Class c) ?
John McCall506b57e2010-05-17 21:00:27 +00003952 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3953 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson80f25672008-09-09 17:59:25 +00003954
3955 // Check if the @catch block matches the exception object.
John McCall506b57e2010-05-17 21:00:27 +00003956 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003957
John McCallf1549f62010-07-06 01:34:17 +00003958 llvm::CallInst *Match =
Chris Lattner34b02a12009-04-22 02:26:14 +00003959 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3960 Class, Caught, "match");
John McCallf1549f62010-07-06 01:34:17 +00003961 Match->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003962
John McCallf1549f62010-07-06 01:34:17 +00003963 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3964 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003965
3966 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003967 MatchedBlock, NextCatchBlock);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003968
Anders Carlsson80f25672008-09-09 17:59:25 +00003969 // Emit the @catch block.
3970 CGF.EmitBlock(MatchedBlock);
John McCallf1549f62010-07-06 01:34:17 +00003971
3972 // Collect any cleanups for the catch variable. The scope lasts until
3973 // the end of the catch body.
John McCall0b251722010-08-04 05:59:32 +00003974 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallf1549f62010-07-06 01:34:17 +00003975
John McCallb6bbcc92010-10-15 04:57:14 +00003976 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003977 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003978
John McCallf1549f62010-07-06 01:34:17 +00003979 // Initialize the catch variable.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003980 llvm::Value *Tmp =
3981 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer578faa82011-09-27 21:06:10 +00003982 CGF.ConvertType(CatchParam->getType()));
Steve Naroff7ba138a2009-03-03 19:52:17 +00003983 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003984
Anders Carlssondde0a942008-09-11 09:15:33 +00003985 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003986
3987 // We're done with the catch variable.
3988 CatchVarCleanups.ForceCleanup();
3989
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003990 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003991
Anders Carlsson80f25672008-09-09 17:59:25 +00003992 CGF.EmitBlock(NextCatchBlock);
3993 }
3994
John McCallf1549f62010-07-06 01:34:17 +00003995 CGF.ObjCEHValueStack.pop_back();
3996
John McCall0b251722010-08-04 05:59:32 +00003997 // If nothing wanted anything to do with the caught exception,
3998 // kill the extract call.
3999 if (Caught->use_empty())
4000 Caught->eraseFromParent();
4001
4002 if (!AllMatched)
4003 CGF.EmitBranchThroughCleanup(FinallyRethrow);
4004
4005 if (HasFinally) {
4006 // Emit the exception handler for the @catch blocks.
4007 CGF.EmitBlock(CatchHandler);
4008
4009 // In theory we might now need a write hazard, but actually it's
4010 // unnecessary because there's no local-accessing code between
4011 // the try's write hazard and here.
4012 //Hazards.emitWriteHazard();
4013
John McCall9e2213d2010-10-04 23:42:51 +00004014 // Extract the new exception and save it to the
4015 // propagating-exception slot.
4016 assert(PropagatingExnVar);
4017 llvm::CallInst *NewCaught =
4018 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
4019 ExceptionData, "caught");
4020 NewCaught->setDoesNotThrow();
4021 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
4022
John McCall0b251722010-08-04 05:59:32 +00004023 // Don't pop the catch handler; the throw already did.
4024 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00004025 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar55e40722008-09-27 07:03:52 +00004026 }
Anders Carlsson80f25672008-09-09 17:59:25 +00004027 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004028
John McCall87bb5822010-07-31 23:20:56 +00004029 // Insert read hazards as required in the new blocks.
John McCall0b251722010-08-04 05:59:32 +00004030 Hazards.emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00004031
John McCallf1549f62010-07-06 01:34:17 +00004032 // Pop the cleanup.
John McCall0b251722010-08-04 05:59:32 +00004033 CGF.Builder.restoreIP(TryFallthroughIP);
4034 if (CGF.HaveInsertPoint())
4035 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallf1549f62010-07-06 01:34:17 +00004036 CGF.PopCleanupBlock();
John McCall0b251722010-08-04 05:59:32 +00004037 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00004038
John McCallf1549f62010-07-06 01:34:17 +00004039 // Emit the rethrow block.
John McCall87bb5822010-07-31 23:20:56 +00004040 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallff8e1152010-07-23 21:56:41 +00004041 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallf1549f62010-07-06 01:34:17 +00004042 if (CGF.HaveInsertPoint()) {
John McCall9e2213d2010-10-04 23:42:51 +00004043 // If we have a propagating-exception variable, check it.
4044 llvm::Value *PropagatingExn;
4045 if (PropagatingExnVar) {
4046 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall0b251722010-08-04 05:59:32 +00004047
John McCall9e2213d2010-10-04 23:42:51 +00004048 // Otherwise, just look in the buffer for the exception to throw.
4049 } else {
4050 llvm::CallInst *Caught =
4051 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
4052 ExceptionData);
4053 Caught->setDoesNotThrow();
4054 PropagatingExn = Caught;
4055 }
4056
4057 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallf1549f62010-07-06 01:34:17 +00004058 ->setDoesNotThrow();
4059 CGF.Builder.CreateUnreachable();
Fariborz Jahanianf2878e52008-11-21 19:21:53 +00004060 }
Anders Carlsson80f25672008-09-09 17:59:25 +00004061
John McCall87bb5822010-07-31 23:20:56 +00004062 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00004063}
4064
4065void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar898d5082008-09-30 01:06:03 +00004066 const ObjCAtThrowStmt &S) {
Anders Carlsson2b1e3112008-09-09 16:16:55 +00004067 llvm::Value *ExceptionAsObject;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004068
Anders Carlsson2b1e3112008-09-09 16:16:55 +00004069 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall2b014d62011-10-01 10:32:24 +00004070 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004071 ExceptionAsObject =
Benjamin Kramer578faa82011-09-27 21:06:10 +00004072 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlsson2b1e3112008-09-09 16:16:55 +00004073 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004074 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar18ccc772008-09-28 01:03:14 +00004075 "Unexpected rethrow outside @catch block.");
Anders Carlsson273558f2009-02-07 21:37:21 +00004076 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlsson2b1e3112008-09-09 16:16:55 +00004077 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004078
John McCallf1549f62010-07-06 01:34:17 +00004079 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
4080 ->setDoesNotReturn();
Anders Carlsson80f25672008-09-09 17:59:25 +00004081 CGF.Builder.CreateUnreachable();
Daniel Dunbara448fb22008-11-11 23:11:34 +00004082
4083 // Clear the insertion point to indicate we are in unreachable code.
4084 CGF.Builder.ClearInsertionPoint();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00004085}
4086
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00004087/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00004088/// object: objc_read_weak (id *src)
4089///
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00004090llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00004091 llvm::Value *AddrWeakObj) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00004092 llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004093 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
4094 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
4095 ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00004096 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00004097 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00004098 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00004099 return read_weak;
4100}
4101
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00004102/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4103/// objc_assign_weak (id src, id *dst)
4104///
4105void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00004106 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00004107 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004108 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00004109 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004110 assert(Size <= 8 && "does not support size > 8");
4111 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004112 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00004113 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4114 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00004115 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4116 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00004117 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00004118 src, dst, "weakassign");
4119 return;
4120}
4121
Fariborz Jahanian58626502008-11-19 00:59:10 +00004122/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4123/// objc_assign_global (id src, id *dst)
4124///
4125void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00004126 llvm::Value *src, llvm::Value *dst,
4127 bool threadlocal) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00004128 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004129 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00004130 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004131 assert(Size <= 8 && "does not support size > 8");
4132 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004133 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00004134 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4135 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00004136 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4137 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00004138 if (!threadlocal)
4139 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
4140 src, dst, "globalassign");
4141 else
4142 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
4143 src, dst, "threadlocalassign");
Fariborz Jahanian58626502008-11-19 00:59:10 +00004144 return;
4145}
4146
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00004147/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00004148/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00004149///
4150void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00004151 llvm::Value *src, llvm::Value *dst,
4152 llvm::Value *ivarOffset) {
4153 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2acc6e32011-07-18 04:24:23 +00004154 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004155 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00004156 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004157 assert(Size <= 8 && "does not support size > 8");
4158 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004159 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00004160 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4161 }
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00004162 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4163 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00004164 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
4165 src, dst, ivarOffset);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00004166 return;
4167}
4168
Fariborz Jahanian58626502008-11-19 00:59:10 +00004169/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4170/// objc_assign_strongCast (id src, id *dst)
4171///
4172void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00004173 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00004174 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004175 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00004176 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004177 assert(Size <= 8 && "does not support size > 8");
4178 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004179 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00004180 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
4181 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00004182 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4183 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00004184 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian58626502008-11-19 00:59:10 +00004185 src, dst, "weakassign");
4186 return;
4187}
4188
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00004189void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004190 llvm::Value *DestPtr,
4191 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00004192 llvm::Value *size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00004193 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
4194 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00004195 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00004196 DestPtr, SrcPtr, size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00004197 return;
4198}
4199
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00004200/// EmitObjCValueForIvar - Code Gen for ivar reference.
4201///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00004202LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
4203 QualType ObjectTy,
4204 llvm::Value *BaseValue,
4205 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00004206 unsigned CVRQualifiers) {
John McCallc12c5bb2010-05-15 11:32:37 +00004207 const ObjCInterfaceDecl *ID =
4208 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00004209 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
4210 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00004211}
4212
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00004213llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00004214 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00004215 const ObjCIvarDecl *Ivar) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004216 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
4217 return llvm::ConstantInt::get(
4218 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
4219 Offset);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00004220}
4221
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004222/* *** Private Interface *** */
4223
4224/// EmitImageInfo - Emit the image info marker used to encode some module
4225/// level information.
4226///
4227/// See: <rdr://4810609&4810587&4810587>
4228/// struct IMAGE_INFO {
4229/// unsigned version;
4230/// unsigned flags;
4231/// };
4232enum ImageInfoFlags {
Daniel Dunbarfce176b2010-04-25 20:39:01 +00004233 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004234 eImageInfo_GarbageCollected = (1 << 1),
4235 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00004236 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
4237
Daniel Dunbarfce176b2010-04-25 20:39:01 +00004238 // A flag indicating that the module has no instances of a @synthesize of a
4239 // superclass variable. <rdar://problem/6803242>
Bill Wendling09822512012-04-24 11:04:57 +00004240 eImageInfo_CorrectedSynthesize = (1 << 4),
4241 eImageInfo_ImageIsSimulated = (1 << 5)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004242};
4243
Daniel Dunbarfce176b2010-04-25 20:39:01 +00004244void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004245 unsigned version = 0; // Version is unused?
Bill Wendling3973acc2012-02-16 01:13:30 +00004246 const char *Section = (ObjCABI == 1) ?
4247 "__OBJC, __image_info,regular" :
4248 "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004249
Bill Wendling3973acc2012-02-16 01:13:30 +00004250 // Generate module-level named metadata to convey this information to the
4251 // linker and code-gen.
4252 llvm::Module &Mod = CGM.getModule();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004253
Bill Wendling3973acc2012-02-16 01:13:30 +00004254 // Add the ObjC ABI version to the module flags.
4255 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
4256 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
4257 version);
4258 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
4259 llvm::MDString::get(VMContext,Section));
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004260
David Blaikie4e4d0842012-03-11 07:00:24 +00004261 if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
Bill Wendling3973acc2012-02-16 01:13:30 +00004262 // Non-GC overrides those files which specify GC.
4263 Mod.addModuleFlag(llvm::Module::Override,
4264 "Objective-C Garbage Collection", (uint32_t)0);
4265 } else {
4266 // Add the ObjC garbage collection value.
4267 Mod.addModuleFlag(llvm::Module::Error,
4268 "Objective-C Garbage Collection",
4269 eImageInfo_GarbageCollected);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004270
David Blaikie4e4d0842012-03-11 07:00:24 +00004271 if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
Bill Wendling3973acc2012-02-16 01:13:30 +00004272 // Add the ObjC GC Only value.
4273 Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
4274 eImageInfo_GCOnly);
4275
4276 // Require that GC be specified and set to eImageInfo_GarbageCollected.
4277 llvm::Value *Ops[2] = {
4278 llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
4279 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
4280 eImageInfo_GarbageCollected)
4281 };
4282 Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
4283 llvm::MDNode::get(VMContext, Ops));
4284 }
4285 }
Bill Wendling09822512012-04-24 11:04:57 +00004286
4287 // Indicate whether we're compiling this to run on a simulator.
4288 const llvm::Triple &Triple = CGM.getTarget().getTriple();
4289 if (Triple.getOS() == llvm::Triple::IOS &&
4290 (Triple.getArch() == llvm::Triple::x86 ||
4291 Triple.getArch() == llvm::Triple::x86_64))
4292 Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
4293 eImageInfo_ImageIsSimulated);
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004294}
4295
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004296// struct objc_module {
4297// unsigned long version;
4298// unsigned long size;
4299// const char *name;
4300// Symtab symtab;
4301// };
4302
4303// FIXME: Get from somewhere
4304static const int ModuleVersion = 7;
4305
4306void CGObjCMac::EmitModuleInfo() {
Micah Villmow25a6a842012-10-08 16:25:52 +00004307 uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004308
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00004309 llvm::Constant *Values[] = {
4310 llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion),
4311 llvm::ConstantInt::get(ObjCTypes.LongTy, Size),
4312 // This used to be the filename, now it is unused. <rdr://4327263>
4313 GetClassName(&CGM.getContext().Idents.get("")),
4314 EmitModuleSymbols()
4315 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004316 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson08e25242009-07-27 22:29:56 +00004317 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004318 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00004319 4, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004320}
4321
4322llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004323 unsigned NumClasses = DefinedClasses.size();
4324 unsigned NumCategories = DefinedCategories.size();
4325
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004326 // Return null if no symbols were defined.
4327 if (!NumClasses && !NumCategories)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004328 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004329
Chris Lattnerc5cbb902011-06-20 04:01:35 +00004330 llvm::Constant *Values[5];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00004331 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004332 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00004333 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
4334 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004335
Daniel Dunbar86e253a2008-08-22 20:34:54 +00004336 // The runtime expects exactly the list of defined classes followed
4337 // by the list of defined categories, in a single array.
Chris Lattner0b239712012-02-06 22:16:34 +00004338 SmallVector<llvm::Constant*, 8> Symbols(NumClasses + NumCategories);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00004339 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00004340 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00004341 ObjCTypes.Int8PtrTy);
4342 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004343 Symbols[NumClasses + i] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00004344 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00004345 ObjCTypes.Int8PtrTy);
4346
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004347 Values[4] =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004348 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner0b239712012-02-06 22:16:34 +00004349 Symbols.size()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004350 Symbols);
4351
Chris Lattnerc5cbb902011-06-20 04:01:35 +00004352 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004353
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004354 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004355 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
4356 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00004357 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00004358 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004359}
4360
John McCallf85e1932011-06-15 23:02:42 +00004361llvm::Value *CGObjCMac::EmitClassRefFromId(CGBuilderTy &Builder,
4362 IdentifierInfo *II) {
4363 LazySymbols.insert(II);
4364
4365 llvm::GlobalVariable *&Entry = ClassReferences[II];
4366
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004367 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004368 llvm::Constant *Casted =
John McCallf85e1932011-06-15 23:02:42 +00004369 llvm::ConstantExpr::getBitCast(GetClassName(II),
4370 ObjCTypes.ClassPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004371 Entry =
John McCallf85e1932011-06-15 23:02:42 +00004372 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
4373 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
4374 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004375 }
John McCallf85e1932011-06-15 23:02:42 +00004376
Benjamin Kramer578faa82011-09-27 21:06:10 +00004377 return Builder.CreateLoad(Entry);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004378}
4379
John McCallf85e1932011-06-15 23:02:42 +00004380llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
4381 const ObjCInterfaceDecl *ID) {
4382 return EmitClassRefFromId(Builder, ID->getIdentifier());
4383}
4384
4385llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder) {
4386 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
4387 return EmitClassRefFromId(Builder, II);
4388}
4389
Fariborz Jahanian03b29602010-06-17 19:56:20 +00004390llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
4391 bool lvalue) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004392 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004393
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004394 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004395 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00004396 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004397 ObjCTypes.SelectorPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004398 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004399 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
4400 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00004401 4, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004402 }
4403
Fariborz Jahanian03b29602010-06-17 19:56:20 +00004404 if (lvalue)
4405 return Entry;
Benjamin Kramer578faa82011-09-27 21:06:10 +00004406 return Builder.CreateLoad(Entry);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004407}
4408
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004409llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004410 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004411
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004412 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004413 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner94010692012-02-05 02:30:40 +00004414 llvm::ConstantDataArray::getString(VMContext,
4415 Ident->getNameStart()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004416 ((ObjCABI == 2) ?
4417 "__TEXT,__objc_classname,cstring_literals" :
4418 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004419 1, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004420
Owen Andersona1cf15f2009-07-14 23:10:40 +00004421 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004422}
4423
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00004424llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
4425 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
4426 I = MethodDefinitions.find(MD);
4427 if (I != MethodDefinitions.end())
4428 return I->second;
4429
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00004430 return NULL;
4431}
4432
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00004433/// GetIvarLayoutName - Returns a unique constant for the given
4434/// ivar layout bitmap.
4435llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004436 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Andersonc9c88b42009-07-31 20:28:54 +00004437 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00004438}
4439
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004440void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Eli Friedmane5b46662012-11-06 22:15:52 +00004441 unsigned int BytePos,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004442 bool ForStrongLayout,
4443 bool &HasUnion) {
4444 const RecordDecl *RD = RT->getDecl();
4445 // FIXME - Use iterator.
David Blaikie262bc182012-04-30 02:36:29 +00004446 SmallVector<const FieldDecl*, 16> Fields;
4447 for (RecordDecl::field_iterator i = RD->field_begin(),
4448 e = RD->field_end(); i != e; ++i)
David Blaikie581deb32012-06-06 20:45:41 +00004449 Fields.push_back(*i);
Chris Lattner2acc6e32011-07-18 04:24:23 +00004450 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004451 const llvm::StructLayout *RecLayout =
Micah Villmow25a6a842012-10-08 16:25:52 +00004452 CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004453
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004454 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
4455 ForStrongLayout, HasUnion);
4456}
4457
Daniel Dunbar5a5a8032009-05-03 21:05:10 +00004458void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004459 const llvm::StructLayout *Layout,
4460 const RecordDecl *RD,
Bill Wendling795b1002012-02-22 09:30:11 +00004461 ArrayRef<const FieldDecl*> RecFields,
Eli Friedmane5b46662012-11-06 22:15:52 +00004462 unsigned int BytePos, bool ForStrongLayout,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004463 bool &HasUnion) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004464 bool IsUnion = (RD && RD->isUnion());
Eli Friedmane5b46662012-11-06 22:15:52 +00004465 uint64_t MaxUnionIvarSize = 0;
4466 uint64_t MaxSkippedUnionIvarSize = 0;
Jordy Rosedb8264e2011-07-22 02:08:32 +00004467 const FieldDecl *MaxField = 0;
4468 const FieldDecl *MaxSkippedField = 0;
4469 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Eli Friedmane5b46662012-11-06 22:15:52 +00004470 uint64_t MaxFieldOffset = 0;
4471 uint64_t MaxSkippedFieldOffset = 0;
4472 uint64_t LastBitfieldOrUnnamedOffset = 0;
4473 uint64_t FirstFieldDelta = 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004474
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004475 if (RecFields.empty())
4476 return;
Eli Friedmane5b46662012-11-06 22:15:52 +00004477 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
Douglas Gregorbcfd1f52011-09-02 00:18:52 +00004478 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
David Blaikie4e4d0842012-03-11 07:00:24 +00004479 if (!RD && CGM.getLangOpts().ObjCAutoRefCount) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004480 const FieldDecl *FirstField = RecFields[0];
4481 FirstFieldDelta =
4482 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
John McCallf85e1932011-06-15 23:02:42 +00004483 }
4484
Chris Lattnerf1690852009-03-31 08:48:01 +00004485 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Jordy Rosedb8264e2011-07-22 02:08:32 +00004486 const FieldDecl *Field = RecFields[i];
Eli Friedmane5b46662012-11-06 22:15:52 +00004487 uint64_t FieldOffset;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00004488 if (RD) {
Daniel Dunbarf8f8eba2010-04-14 17:02:21 +00004489 // Note that 'i' here is actually the field index inside RD of Field,
4490 // although this dependency is hidden.
4491 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Eli Friedmane5b46662012-11-06 22:15:52 +00004492 FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00004493 } else
John McCallf85e1932011-06-15 23:02:42 +00004494 FieldOffset =
4495 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
Daniel Dunbar25d583e2009-05-03 14:17:18 +00004496
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004497 // Skip over unnamed or bitfields
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00004498 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004499 LastFieldBitfieldOrUnnamed = Field;
4500 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004501 continue;
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00004502 }
Daniel Dunbar25d583e2009-05-03 14:17:18 +00004503
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004504 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004505 QualType FQT = Field->getType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00004506 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004507 if (FQT->isUnionType())
4508 HasUnion = true;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004509
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004510 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar25d583e2009-05-03 14:17:18 +00004511 BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004512 ForStrongLayout, HasUnion);
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004513 continue;
4514 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004515
Chris Lattnerf1690852009-03-31 08:48:01 +00004516 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004517 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00004518 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00004519 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00004520 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004521 FQT = CArray->getElementType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00004522 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
4523 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00004524 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00004525 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00004526 FQT = CArray->getElementType();
4527 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004528
4529 assert(!FQT->isUnionType() &&
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004530 "layout for array of unions not supported");
Fariborz Jahanianf96bdf42011-01-03 19:23:18 +00004531 if (FQT->isRecordType() && ElCount) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004532 int OldIndex = IvarsInfo.size() - 1;
4533 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004534
Ted Kremenek6217b802009-07-29 21:53:49 +00004535 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar25d583e2009-05-03 14:17:18 +00004536 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004537 ForStrongLayout, HasUnion);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004538
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004539 // Replicate layout information for each array element. Note that
4540 // one element is already done.
4541 uint64_t ElIx = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004542 for (int FirstIndex = IvarsInfo.size() - 1,
4543 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004544 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00004545 for (int i = OldIndex+1; i <= FirstIndex; ++i)
4546 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
4547 IvarsInfo[i].ivar_size));
4548 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
4549 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
4550 SkipIvars[i].ivar_size));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004551 }
4552 continue;
4553 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00004554 }
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004555 // At this point, we are done with Record/Union and array there of.
4556 // For other arrays we are down to its element type.
John McCall0953e762009-09-24 19:53:00 +00004557 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00004558
Eli Friedmane5b46662012-11-06 22:15:52 +00004559 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall0953e762009-09-24 19:53:00 +00004560 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
4561 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00004562 if (IsUnion) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004563 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar487993b2009-05-03 13:32:01 +00004564 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004565 MaxUnionIvarSize = UnionIvarSize;
4566 MaxField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00004567 MaxFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004568 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00004569 } else {
Eli Friedmane5b46662012-11-06 22:15:52 +00004570 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
4571 FieldSize / WordSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004572 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004573 } else if ((ForStrongLayout &&
John McCall0953e762009-09-24 19:53:00 +00004574 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
4575 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00004576 if (IsUnion) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004577 // FIXME: Why the asymmetry? We divide by word size in bits on other
4578 // side.
4579 uint64_t UnionIvarSize = FieldSize / ByteSizeInBits;
Daniel Dunbar487993b2009-05-03 13:32:01 +00004580 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004581 MaxSkippedUnionIvarSize = UnionIvarSize;
4582 MaxSkippedField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00004583 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004584 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00004585 } else {
Eli Friedmane5b46662012-11-06 22:15:52 +00004586 // FIXME: Why the asymmetry, we divide by byte size in bits here?
4587 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
4588 FieldSize / ByteSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00004589 }
4590 }
4591 }
Daniel Dunbard58edcb2009-05-03 14:10:34 +00004592
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004593 if (LastFieldBitfieldOrUnnamed) {
4594 if (LastFieldBitfieldOrUnnamed->isBitField()) {
4595 // Last field was a bitfield. Must update skip info.
Richard Smitha6b8b2c2011-10-10 18:28:20 +00004596 uint64_t BitFieldSize
4597 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004598 GC_IVAR skivar;
4599 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
Eli Friedmane5b46662012-11-06 22:15:52 +00004600 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
4601 + ((BitFieldSize % ByteSizeInBits) != 0);
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004602 SkipIvars.push_back(skivar);
4603 } else {
4604 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
4605 // Last field was unnamed. Must update skip info.
Eli Friedmane5b46662012-11-06 22:15:52 +00004606 unsigned FieldSize
4607 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004608 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
Eli Friedmane5b46662012-11-06 22:15:52 +00004609 FieldSize / ByteSizeInBits));
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00004610 }
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00004611 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004612
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00004613 if (MaxField)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004614 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00004615 MaxUnionIvarSize));
4616 if (MaxSkippedField)
Daniel Dunbar900c1982009-05-03 23:31:46 +00004617 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00004618 MaxSkippedUnionIvarSize));
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00004619}
4620
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00004621/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
4622/// the computations and returning the layout bitmap (for ivar or blocks) in
4623/// the given argument BitMap string container. Routine reads
4624/// two containers, IvarsInfo and SkipIvars which are assumed to be
4625/// filled already by the caller.
Chris Lattner94010692012-02-05 02:30:40 +00004626llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004627 unsigned int WordsToScan, WordsToSkip;
Chris Lattner8b418682012-02-07 00:39:47 +00004628 llvm::Type *PtrTy = CGM.Int8PtrTy;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004629
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004630 // Build the string of skip/scan nibbles
Chris Lattner5f9e2722011-07-23 10:55:15 +00004631 SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Eli Friedmane5b46662012-11-06 22:15:52 +00004632 unsigned int WordSize =
4633 CGM.getTypes().getDataLayout().getTypeAllocSize(PtrTy);
4634 if (IvarsInfo[0].ivar_bytepos == 0) {
4635 WordsToSkip = 0;
4636 WordsToScan = IvarsInfo[0].ivar_size;
4637 } else {
4638 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
4639 WordsToScan = IvarsInfo[0].ivar_size;
4640 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004641 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004642 unsigned int TailPrevGCObjC =
4643 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004644 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004645 // consecutive 'scanned' object pointers.
Eli Friedmane5b46662012-11-06 22:15:52 +00004646 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004647 } else {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004648 // Skip over 'gc'able object pointer which lay over each other.
4649 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
4650 continue;
4651 // Must skip over 1 or more words. We save current skip/scan values
4652 // and start a new pair.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00004653 SKIP_SCAN SkScan;
4654 SkScan.skip = WordsToSkip;
4655 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004656 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004657
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004658 // Skip the hole.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00004659 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
4660 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004661 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004662 WordsToSkip = 0;
Eli Friedmane5b46662012-11-06 22:15:52 +00004663 WordsToScan = IvarsInfo[i].ivar_size;
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004664 }
4665 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004666 if (WordsToScan > 0) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00004667 SKIP_SCAN SkScan;
4668 SkScan.skip = WordsToSkip;
4669 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004670 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004671 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004672
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004673 if (!SkipIvars.empty()) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004674 unsigned int LastIndex = SkipIvars.size()-1;
Eli Friedmane5b46662012-11-06 22:15:52 +00004675 int LastByteSkipped =
4676 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004677 LastIndex = IvarsInfo.size()-1;
Eli Friedmane5b46662012-11-06 22:15:52 +00004678 int LastByteScanned =
4679 IvarsInfo[LastIndex].ivar_bytepos +
4680 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004681 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramer54d76db2009-12-25 15:43:36 +00004682 if (LastByteSkipped > LastByteScanned) {
Eli Friedmane5b46662012-11-06 22:15:52 +00004683 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00004684 SKIP_SCAN SkScan;
Eli Friedmane5b46662012-11-06 22:15:52 +00004685 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00004686 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004687 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004688 }
4689 }
4690 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
4691 // as 0xMN.
Fariborz Jahanian81adc052009-04-24 16:17:09 +00004692 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004693 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004694 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
4695 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
4696 // 0xM0 followed by 0x0N detected.
4697 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
4698 for (int j = i+1; j < SkipScan; j++)
4699 SkipScanIvars[j] = SkipScanIvars[j+1];
4700 --SkipScan;
4701 }
4702 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004703
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004704 // Generate the string.
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004705 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004706 unsigned char byte;
4707 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
4708 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
4709 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
4710 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004711
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004712 // first skip big.
4713 for (unsigned int ix = 0; ix < skip_big; ix++)
4714 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004715
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004716 // next (skip small, scan)
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004717 if (skip_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004718 byte = skip_small << 4;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004719 if (scan_big > 0) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004720 byte |= 0xf;
4721 --scan_big;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004722 } else if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004723 byte |= scan_small;
4724 scan_small = 0;
4725 }
4726 BitMap += byte;
4727 }
4728 // next scan big
4729 for (unsigned int ix = 0; ix < scan_big; ix++)
4730 BitMap += (unsigned char)(0x0f);
4731 // last scan small
Daniel Dunbar31682fd2009-05-03 23:21:22 +00004732 if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00004733 byte = scan_small;
4734 BitMap += byte;
4735 }
4736 }
4737 // null terminate string.
Fariborz Jahanian667423a2009-03-25 22:36:49 +00004738 unsigned char zero = 0;
4739 BitMap += zero;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004740
4741 llvm::GlobalVariable * Entry =
4742 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Chris Lattner94010692012-02-05 02:30:40 +00004743 llvm::ConstantDataArray::getString(VMContext, BitMap,false),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004744 ((ObjCABI == 2) ?
4745 "__TEXT,__objc_classname,cstring_literals" :
4746 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004747 1, true);
4748 return getConstantGEP(VMContext, Entry, 0, 0);
4749}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004750
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004751/// BuildIvarLayout - Builds ivar layout bitmap for the class
4752/// implementation for the __strong or __weak case.
4753/// The layout map displays which words in ivar list must be skipped
4754/// and which must be scanned by GC (see below). String is built of bytes.
4755/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
4756/// of words to skip and right nibble is count of words to scan. So, each
4757/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
4758/// represented by a 0x00 byte which also ends the string.
4759/// 1. when ForStrongLayout is true, following ivars are scanned:
4760/// - id, Class
4761/// - object *
4762/// - __strong anything
4763///
4764/// 2. When ForStrongLayout is false, following ivars are scanned:
4765/// - __weak anything
4766///
4767llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
4768 const ObjCImplementationDecl *OMD,
4769 bool ForStrongLayout) {
4770 bool hasUnion = false;
4771
Chris Lattner8b418682012-02-07 00:39:47 +00004772 llvm::Type *PtrTy = CGM.Int8PtrTy;
David Blaikie4e4d0842012-03-11 07:00:24 +00004773 if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
4774 !CGM.getLangOpts().ObjCAutoRefCount)
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004775 return llvm::Constant::getNullValue(PtrTy);
4776
Jordy Rosedb8264e2011-07-22 02:08:32 +00004777 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
4778 SmallVector<const FieldDecl*, 32> RecFields;
David Blaikie4e4d0842012-03-11 07:00:24 +00004779 if (CGM.getLangOpts().ObjCAutoRefCount) {
Jordy Rosedb8264e2011-07-22 02:08:32 +00004780 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00004781 IVD; IVD = IVD->getNextIvar())
4782 RecFields.push_back(cast<FieldDecl>(IVD));
4783 }
4784 else {
Jordy Rosedb8264e2011-07-22 02:08:32 +00004785 SmallVector<const ObjCIvarDecl*, 32> Ivars;
John McCallf85e1932011-06-15 23:02:42 +00004786 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004787
Jordy Rosedb8264e2011-07-22 02:08:32 +00004788 // FIXME: This is not ideal; we shouldn't have to do this copy.
4789 RecFields.append(Ivars.begin(), Ivars.end());
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00004790 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004791
4792 if (RecFields.empty())
4793 return llvm::Constant::getNullValue(PtrTy);
4794
4795 SkipIvars.clear();
4796 IvarsInfo.clear();
4797
Eli Friedmane5b46662012-11-06 22:15:52 +00004798 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004799 if (IvarsInfo.empty())
4800 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00004801 // Sort on byte position in case we encounterred a union nested in
4802 // the ivar list.
4803 if (hasUnion && !IvarsInfo.empty())
4804 std::sort(IvarsInfo.begin(), IvarsInfo.end());
4805 if (hasUnion && !SkipIvars.empty())
4806 std::sort(SkipIvars.begin(), SkipIvars.end());
4807
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004808 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00004809 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004810
David Blaikie4e4d0842012-03-11 07:00:24 +00004811 if (CGM.getLangOpts().ObjCGCBitmapPrint) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004812 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian3d2ad662009-04-20 22:03:45 +00004813 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar4087f272010-08-17 22:39:59 +00004814 OMD->getClassInterface()->getName().data());
Roman Divacky31ba6132012-09-06 15:59:27 +00004815 const unsigned char *s = (const unsigned char*)BitMap.c_str();
Bill Wendling13562a12012-02-07 09:06:01 +00004816 for (unsigned i = 0, e = BitMap.size(); i < e; i++)
Fariborz Jahanian3d2ad662009-04-20 22:03:45 +00004817 if (!(s[i] & 0xf0))
4818 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
4819 else
4820 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
4821 printf("\n");
4822 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00004823 return C;
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00004824}
4825
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004826llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004827 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
4828
Chris Lattner0b239712012-02-06 22:16:34 +00004829 // FIXME: Avoid std::string in "Sel.getAsString()"
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004830 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004831 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Chris Lattner94010692012-02-05 02:30:40 +00004832 llvm::ConstantDataArray::getString(VMContext, Sel.getAsString()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004833 ((ObjCABI == 2) ?
4834 "__TEXT,__objc_methname,cstring_literals" :
4835 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004836 1, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004837
Owen Andersona1cf15f2009-07-14 23:10:40 +00004838 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004839}
4840
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004841// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004842llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004843 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4844}
4845
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00004846llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel7794bb82009-03-04 18:21:39 +00004847 std::string TypeStr;
4848 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
4849
4850 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004851
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004852 if (!Entry)
4853 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner94010692012-02-05 02:30:40 +00004854 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004855 ((ObjCABI == 2) ?
4856 "__TEXT,__objc_methtype,cstring_literals" :
4857 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004858 1, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004859
Owen Andersona1cf15f2009-07-14 23:10:40 +00004860 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004861}
4862
Bob Wilsondc8dab62011-11-30 01:57:58 +00004863llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
4864 bool Extended) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004865 std::string TypeStr;
Bill Wendlinga4dc6932012-02-09 22:45:21 +00004866 if (CGM.getContext().getObjCEncodingForMethodDecl(D, TypeStr, Extended))
Douglas Gregorf968d832011-05-27 01:19:52 +00004867 return 0;
Devang Patel7794bb82009-03-04 18:21:39 +00004868
4869 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4870
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004871 if (!Entry)
4872 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Chris Lattner94010692012-02-05 02:30:40 +00004873 llvm::ConstantDataArray::getString(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004874 ((ObjCABI == 2) ?
4875 "__TEXT,__objc_methtype,cstring_literals" :
4876 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004877 1, true);
Devang Patel7794bb82009-03-04 18:21:39 +00004878
Owen Andersona1cf15f2009-07-14 23:10:40 +00004879 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004880}
4881
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004882// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004883llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004884 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004885
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004886 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004887 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Chris Lattner94010692012-02-05 02:30:40 +00004888 llvm::ConstantDataArray::getString(VMContext,
4889 Ident->getNameStart()),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004890 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004891 1, true);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004892
Owen Andersona1cf15f2009-07-14 23:10:40 +00004893 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004894}
4895
4896// FIXME: Merge into a single cstring creation function.
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00004897// FIXME: This Decl should be more precise.
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004898llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004899CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4900 const Decl *Container) {
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00004901 std::string TypeStr;
4902 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004903 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4904}
4905
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004906void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004907 const ObjCContainerDecl *CD,
Chris Lattner5f9e2722011-07-23 10:55:15 +00004908 SmallVectorImpl<char> &Name) {
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004909 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian679a5022009-01-10 21:06:09 +00004910 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004911 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4912 << '[' << CD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004913 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004914 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramerf9780592012-02-07 11:57:45 +00004915 OS << '(' << *CID << ')';
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004916 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00004917}
4918
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004919void CGObjCMac::FinishModule() {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004920 EmitModuleInfo();
4921
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004922 // Emit the dummy bodies for any protocols which were referenced but
4923 // never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004924 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerad64e022009-07-17 23:57:13 +00004925 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4926 if (I->second->hasInitializer())
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004927 continue;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004928
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00004929 llvm::Constant *Values[5];
Owen Andersonc9c88b42009-07-31 20:28:54 +00004930 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004931 Values[1] = GetClassName(I->first);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004932 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004933 Values[3] = Values[4] =
Owen Andersonc9c88b42009-07-31 20:28:54 +00004934 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004935 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson08e25242009-07-27 22:29:56 +00004936 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004937 Values));
Chris Lattnerad64e022009-07-17 23:57:13 +00004938 CGM.AddUsedGlobal(I->second);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004939 }
4940
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004941 // Add assembler directives to add lazy undefined symbol references
4942 // for classes which are referenced but not defined. This is
4943 // important for correct linker interaction.
Daniel Dunbar33063492009-09-07 00:20:42 +00004944 //
4945 // FIXME: It would be nice if we had an LLVM construct for this.
4946 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00004947 SmallString<256> Asm;
Daniel Dunbar33063492009-09-07 00:20:42 +00004948 Asm += CGM.getModule().getModuleInlineAsm();
4949 if (!Asm.empty() && Asm.back() != '\n')
4950 Asm += '\n';
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004951
Daniel Dunbar33063492009-09-07 00:20:42 +00004952 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbar33063492009-09-07 00:20:42 +00004953 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4954 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00004955 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4956 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004957 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004958 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004959 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004960 }
4961
Bill Wendling13562a12012-02-07 09:06:01 +00004962 for (size_t i = 0, e = DefinedCategoryNames.size(); i < e; ++i) {
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004963 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4964 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4965 }
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004966
Daniel Dunbar33063492009-09-07 00:20:42 +00004967 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004968 }
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004969}
4970
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004971CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004972 : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00004973 ObjCTypes(cgm) {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004974 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004975 ObjCABI = 2;
4976}
4977
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004978/* *** */
4979
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004980ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Douglas Gregor65a1e672012-01-17 23:38:32 +00004981 : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(0)
4982{
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004983 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4984 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004985
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004986 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004987 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004988 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004989 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Chris Lattner8b418682012-02-07 00:39:47 +00004990 Int8PtrTy = CGM.Int8PtrTy;
4991 Int8PtrPtrTy = CGM.Int8PtrPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004992
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004993 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004994 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004995 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004996
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004997 // I'm not sure I like this. The implicit coordination is a bit
4998 // gross. We should solve this in a reasonable fashion because this
4999 // is a pretty common task (match some runtime data structure with
5000 // an LLVM data structure).
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005001
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005002 // FIXME: This is leaked.
5003 // FIXME: Merge with rewriter code?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005004
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005005 // struct _objc_super {
5006 // id self;
5007 // Class cls;
5008 // }
Abramo Bagnara465d41b2010-05-11 21:36:43 +00005009 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00005010 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00005011 SourceLocation(), SourceLocation(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005012 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00005013 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smithca523302012-06-10 03:12:00 +00005014 Ctx.getObjCIdType(), 0, 0, false, ICIS_NoInit));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00005015 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smithca523302012-06-10 03:12:00 +00005016 Ctx.getObjCClassType(), 0, 0, false,
5017 ICIS_NoInit));
Douglas Gregor838db382010-02-11 01:19:42 +00005018 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005019
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005020 SuperCTy = Ctx.getTagDeclType(RD);
5021 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005022
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005023 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005024 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
5025
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005026 // struct _prop_t {
5027 // char *name;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005028 // char *attributes;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005029 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00005030 PropertyTy = llvm::StructType::create("struct._prop_t",
5031 Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005032
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005033 // struct _prop_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005034 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005035 // uint32_t count_of_properties;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005036 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005037 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005038 PropertyListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005039 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
5040 llvm::ArrayType::get(PropertyTy, 0), NULL);
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005041 // struct _prop_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00005042 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005043
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005044 // struct _objc_method {
5045 // SEL _cmd;
5046 // char *method_type;
5047 // char *_imp;
5048 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00005049 MethodTy = llvm::StructType::create("struct._objc_method",
5050 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
5051 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005052
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005053 // struct _objc_cache *
Chris Lattnerc1c20112011-08-12 17:43:31 +00005054 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson96e0fc72009-07-29 22:16:19 +00005055 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00005056
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005057}
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00005058
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005059ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00005060 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005061 // struct _objc_method_description {
5062 // SEL name;
5063 // char *types;
5064 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005065 MethodDescriptionTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005066 llvm::StructType::create("struct._objc_method_description",
5067 SelectorPtrTy, Int8PtrTy, NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005068
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005069 // struct _objc_method_description_list {
5070 // int count;
5071 // struct _objc_method_description[1];
5072 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005073 MethodDescriptionListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005074 llvm::StructType::create("struct._objc_method_description_list",
5075 IntTy,
5076 llvm::ArrayType::get(MethodDescriptionTy, 0),NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005077
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005078 // struct _objc_method_description_list *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005079 MethodDescriptionListPtrTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +00005080 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005081
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005082 // Protocol description structures
5083
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005084 // struct _objc_protocol_extension {
5085 // uint32_t size; // sizeof(struct _objc_protocol_extension)
5086 // struct _objc_method_description_list *optional_instance_methods;
5087 // struct _objc_method_description_list *optional_class_methods;
5088 // struct _objc_property_list *instance_properties;
Bob Wilsondc8dab62011-11-30 01:57:58 +00005089 // const char ** extendedMethodTypes;
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005090 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005091 ProtocolExtensionTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005092 llvm::StructType::create("struct._objc_protocol_extension",
5093 IntTy, MethodDescriptionListPtrTy,
5094 MethodDescriptionListPtrTy, PropertyListPtrTy,
Bob Wilsondc8dab62011-11-30 01:57:58 +00005095 Int8PtrPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005096
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005097 // struct _objc_protocol_extension *
Owen Anderson96e0fc72009-07-29 22:16:19 +00005098 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005099
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00005100 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005101
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005102 ProtocolTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005103 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005104
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005105 ProtocolListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005106 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005107 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005108 LongTy,
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005109 llvm::ArrayType::get(ProtocolTy, 0),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00005110 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005111
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005112 // struct _objc_protocol {
5113 // struct _objc_protocol_extension *isa;
5114 // char *protocol_name;
5115 // struct _objc_protocol **_objc_protocol_list;
5116 // struct _objc_method_description_list *instance_methods;
5117 // struct _objc_method_description_list *class_methods;
5118 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005119 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
5120 llvm::PointerType::getUnqual(ProtocolListTy),
5121 MethodDescriptionListPtrTy,
5122 MethodDescriptionListPtrTy,
5123 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005124
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005125 // struct _objc_protocol_list *
Owen Anderson96e0fc72009-07-29 22:16:19 +00005126 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00005127
Owen Anderson96e0fc72009-07-29 22:16:19 +00005128 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005129
5130 // Class description structures
5131
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005132 // struct _objc_ivar {
5133 // char *ivar_name;
5134 // char *ivar_type;
5135 // int ivar_offset;
5136 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00005137 IvarTy = llvm::StructType::create("struct._objc_ivar",
5138 Int8PtrTy, Int8PtrTy, IntTy, NULL);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005139
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005140 // struct _objc_ivar_list *
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005141 IvarListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005142 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson96e0fc72009-07-29 22:16:19 +00005143 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005144
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005145 // struct _objc_method_list *
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005146 MethodListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005147 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson96e0fc72009-07-29 22:16:19 +00005148 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005149
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005150 // struct _objc_class_extension *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005151 ClassExtensionTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005152 llvm::StructType::create("struct._objc_class_extension",
5153 IntTy, Int8PtrTy, PropertyListPtrTy, NULL);
Owen Anderson96e0fc72009-07-29 22:16:19 +00005154 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005155
Chris Lattnerc1c20112011-08-12 17:43:31 +00005156 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005157
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005158 // struct _objc_class {
5159 // Class isa;
5160 // Class super_class;
5161 // char *name;
5162 // long version;
5163 // long info;
5164 // long instance_size;
5165 // struct _objc_ivar_list *ivars;
5166 // struct _objc_method_list *methods;
5167 // struct _objc_cache *cache;
5168 // struct _objc_protocol_list *protocols;
5169 // char *ivar_layout;
5170 // struct _objc_class_ext *ext;
5171 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005172 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
5173 llvm::PointerType::getUnqual(ClassTy),
5174 Int8PtrTy,
5175 LongTy,
5176 LongTy,
5177 LongTy,
5178 IvarListPtrTy,
5179 MethodListPtrTy,
5180 CachePtrTy,
5181 ProtocolListPtrTy,
5182 Int8PtrTy,
5183 ClassExtensionPtrTy,
5184 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005185
Owen Anderson96e0fc72009-07-29 22:16:19 +00005186 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005187
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005188 // struct _objc_category {
5189 // char *category_name;
5190 // char *class_name;
5191 // struct _objc_method_list *instance_method;
5192 // struct _objc_method_list *class_method;
5193 // uint32_t size; // sizeof(struct _objc_category)
5194 // struct _objc_property_list *instance_properties;// category's @property
5195 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005196 CategoryTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005197 llvm::StructType::create("struct._objc_category",
5198 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
5199 MethodListPtrTy, ProtocolListPtrTy,
5200 IntTy, PropertyListPtrTy, NULL);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00005201
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005202 // Global metadata structures
5203
Fariborz Jahanian10a42312009-01-21 00:39:53 +00005204 // struct _objc_symtab {
5205 // long sel_ref_cnt;
5206 // SEL *refs;
5207 // short cls_def_cnt;
5208 // short cat_def_cnt;
5209 // char *defs[cls_def_cnt + cat_def_cnt];
5210 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005211 SymtabTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005212 llvm::StructType::create("struct._objc_symtab",
5213 LongTy, SelectorPtrTy, ShortTy, ShortTy,
5214 llvm::ArrayType::get(Int8PtrTy, 0), NULL);
Owen Anderson96e0fc72009-07-29 22:16:19 +00005215 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00005216
Fariborz Jahaniandb286862009-01-22 00:37:21 +00005217 // struct _objc_module {
5218 // long version;
5219 // long size; // sizeof(struct _objc_module)
5220 // char *name;
5221 // struct _objc_symtab* symtab;
5222 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005223 ModuleTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005224 llvm::StructType::create("struct._objc_module",
5225 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00005226
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005227
Mike Stumpf5408fe2009-05-16 07:57:57 +00005228 // FIXME: This is the size of the setjmp buffer and should be target
5229 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson124526b2008-09-09 10:10:21 +00005230 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005231
Anders Carlsson124526b2008-09-09 10:10:21 +00005232 // Exceptions
Chris Lattner8b418682012-02-07 00:39:47 +00005233 llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005234
5235 ExceptionDataTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005236 llvm::StructType::create("struct._objc_exception_data",
Chris Lattner8b418682012-02-07 00:39:47 +00005237 llvm::ArrayType::get(CGM.Int32Ty,SetJmpBufferSize),
5238 StackPtrTy, NULL);
Anders Carlsson124526b2008-09-09 10:10:21 +00005239
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00005240}
5241
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005242ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00005243 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005244 // struct _method_list_t {
5245 // uint32_t entsize; // sizeof(struct _objc_method)
5246 // uint32_t method_count;
5247 // struct _objc_method method_list[method_count];
5248 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005249 MethodListnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005250 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
5251 llvm::ArrayType::get(MethodTy, 0), NULL);
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005252 // struct method_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00005253 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005254
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005255 // struct _protocol_t {
5256 // id isa; // NULL
5257 // const char * const protocol_name;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005258 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005259 // const struct method_list_t * const instance_methods;
5260 // const struct method_list_t * const class_methods;
5261 // const struct method_list_t *optionalInstanceMethods;
5262 // const struct method_list_t *optionalClassMethods;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005263 // const struct _prop_list_t * properties;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005264 // const uint32_t size; // sizeof(struct _protocol_t)
5265 // const uint32_t flags; // = 0
Bob Wilsondc8dab62011-11-30 01:57:58 +00005266 // const char ** extendedMethodTypes;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005267 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005268
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005269 // Holder for struct _protocol_list_t *
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005270 ProtocolListnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005271 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005272
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005273 ProtocolnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005274 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
5275 llvm::PointerType::getUnqual(ProtocolListnfABITy),
5276 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
5277 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
Bob Wilsondc8dab62011-11-30 01:57:58 +00005278 PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy,
5279 NULL);
Daniel Dunbar948e2582009-02-15 07:36:20 +00005280
5281 // struct _protocol_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00005282 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005283
Fariborz Jahanianda320092009-01-29 19:24:30 +00005284 // struct _protocol_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005285 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar948e2582009-02-15 07:36:20 +00005286 // struct _protocol_t *[protocol_count];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005287 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005288 ProtocolListnfABITy->setBody(LongTy,
5289 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
5290 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005291
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005292 // struct _objc_protocol_list*
Owen Anderson96e0fc72009-07-29 22:16:19 +00005293 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005294
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005295 // struct _ivar_t {
5296 // unsigned long int *offset; // pointer to ivar offset location
5297 // char *name;
5298 // char *type;
5299 // uint32_t alignment;
5300 // uint32_t size;
5301 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005302 IvarnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005303 llvm::StructType::create("struct._ivar_t",
5304 llvm::PointerType::getUnqual(LongTy),
5305 Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005306
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005307 // struct _ivar_list_t {
5308 // uint32 entsize; // sizeof(struct _ivar_t)
5309 // uint32 count;
5310 // struct _iver_t list[count];
5311 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005312 IvarListnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005313 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
5314 llvm::ArrayType::get(IvarnfABITy, 0), NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005315
Owen Anderson96e0fc72009-07-29 22:16:19 +00005316 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005317
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005318 // struct _class_ro_t {
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00005319 // uint32_t const flags;
5320 // uint32_t const instanceStart;
5321 // uint32_t const instanceSize;
5322 // uint32_t const reserved; // only when building for 64bit targets
5323 // const uint8_t * const ivarLayout;
5324 // const char *const name;
5325 // const struct _method_list_t * const baseMethods;
5326 // const struct _objc_protocol_list *const baseProtocols;
5327 // const struct _ivar_list_t *const ivars;
5328 // const uint8_t * const weakIvarLayout;
5329 // const struct _prop_list_t * const properties;
5330 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005331
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005332 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattnerc1c20112011-08-12 17:43:31 +00005333 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
5334 IntTy, IntTy, IntTy, Int8PtrTy,
5335 Int8PtrTy, MethodListnfABIPtrTy,
5336 ProtocolListnfABIPtrTy,
5337 IvarListnfABIPtrTy,
5338 Int8PtrTy, PropertyListPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005339
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005340 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005341 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall0774cb82011-05-15 01:53:33 +00005342 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
5343 ->getPointerTo();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005344
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005345 // struct _class_t {
5346 // struct _class_t *isa;
5347 // struct _class_t * const superclass;
5348 // void *cache;
5349 // IMP *vtable;
5350 // struct class_ro_t *ro;
5351 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005352
Chris Lattnerc1c20112011-08-12 17:43:31 +00005353 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005354 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
5355 llvm::PointerType::getUnqual(ClassnfABITy),
5356 CachePtrTy,
5357 llvm::PointerType::getUnqual(ImpnfABITy),
5358 llvm::PointerType::getUnqual(ClassRonfABITy),
5359 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005360
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005361 // LLVM for struct _class_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00005362 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005363
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00005364 // struct _category_t {
5365 // const char * const name;
5366 // struct _class_t *const cls;
5367 // const struct _method_list_t * const instance_methods;
5368 // const struct _method_list_t * const class_methods;
5369 // const struct _protocol_list_t * const protocols;
5370 // const struct _prop_list_t * const properties;
Fariborz Jahanian45c2ba02009-01-23 17:41:22 +00005371 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00005372 CategorynfABITy = llvm::StructType::create("struct._category_t",
5373 Int8PtrTy, ClassnfABIPtrTy,
5374 MethodListnfABIPtrTy,
5375 MethodListnfABIPtrTy,
5376 ProtocolListnfABIPtrTy,
5377 PropertyListPtrTy,
5378 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005379
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00005380 // New types for nonfragile abi messaging.
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005381 CodeGen::CodeGenTypes &Types = CGM.getTypes();
5382 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005383
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00005384 // MessageRefTy - LLVM for:
5385 // struct _message_ref_t {
5386 // IMP messenger;
5387 // SEL name;
5388 // };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005389
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005390 // First the clang type for struct _message_ref_t
Abramo Bagnara465d41b2010-05-11 21:36:43 +00005391 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00005392 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00005393 SourceLocation(), SourceLocation(),
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005394 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00005395 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smithca523302012-06-10 03:12:00 +00005396 Ctx.VoidPtrTy, 0, 0, false, ICIS_NoInit));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00005397 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smithca523302012-06-10 03:12:00 +00005398 Ctx.getObjCSelType(), 0, 0, false,
5399 ICIS_NoInit));
Douglas Gregor838db382010-02-11 01:19:42 +00005400 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005401
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005402 MessageRefCTy = Ctx.getTagDeclType(RD);
5403 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
5404 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005405
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00005406 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00005407 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005408
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00005409 // SuperMessageRefTy - LLVM for:
5410 // struct _super_message_ref_t {
5411 // SUPER_IMP messenger;
5412 // SEL name;
5413 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005414 SuperMessageRefTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005415 llvm::StructType::create("struct._super_message_ref_t",
5416 ImpnfABITy, SelectorPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005417
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00005418 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005419 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00005420
Daniel Dunbare588b992009-03-01 04:46:24 +00005421
5422 // struct objc_typeinfo {
5423 // const void** vtable; // objc_ehtype_vtable + 2
5424 // const char* name; // c++ typeinfo string
5425 // Class cls;
5426 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +00005427 EHTypeTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00005428 llvm::StructType::create("struct._objc_typeinfo",
5429 llvm::PointerType::getUnqual(Int8PtrTy),
5430 Int8PtrTy, ClassnfABIPtrTy, NULL);
Owen Anderson96e0fc72009-07-29 22:16:19 +00005431 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00005432}
5433
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005434llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005435 FinishNonFragileABIModule();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005436
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005437 return NULL;
5438}
5439
Bill Wendlingbb028552012-02-07 09:25:09 +00005440void CGObjCNonFragileABIMac::
5441AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container,
5442 const char *SymbolName,
5443 const char *SectionName) {
Daniel Dunbar463b8762009-05-15 21:48:48 +00005444 unsigned NumClasses = Container.size();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005445
Daniel Dunbar463b8762009-05-15 21:48:48 +00005446 if (!NumClasses)
5447 return;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005448
Chris Lattner0b239712012-02-06 22:16:34 +00005449 SmallVector<llvm::Constant*, 8> Symbols(NumClasses);
Daniel Dunbar463b8762009-05-15 21:48:48 +00005450 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00005451 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar463b8762009-05-15 21:48:48 +00005452 ObjCTypes.Int8PtrTy);
Chris Lattner0b239712012-02-06 22:16:34 +00005453 llvm::Constant *Init =
Owen Anderson96e0fc72009-07-29 22:16:19 +00005454 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Chris Lattner0b239712012-02-06 22:16:34 +00005455 Symbols.size()),
Daniel Dunbar463b8762009-05-15 21:48:48 +00005456 Symbols);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005457
Daniel Dunbar463b8762009-05-15 21:48:48 +00005458 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005459 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar463b8762009-05-15 21:48:48 +00005460 llvm::GlobalValue::InternalLinkage,
5461 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005462 SymbolName);
Micah Villmow25a6a842012-10-08 16:25:52 +00005463 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Daniel Dunbar463b8762009-05-15 21:48:48 +00005464 GV->setSection(SectionName);
Chris Lattnerad64e022009-07-17 23:57:13 +00005465 CGM.AddUsedGlobal(GV);
Daniel Dunbar463b8762009-05-15 21:48:48 +00005466}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005467
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005468void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
5469 // nonfragile abi has no module definition.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005470
Daniel Dunbar463b8762009-05-15 21:48:48 +00005471 // Build list of all implemented class addresses in array
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00005472 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005473 AddModuleClassList(DefinedClasses,
Daniel Dunbar463b8762009-05-15 21:48:48 +00005474 "\01L_OBJC_LABEL_CLASS_$",
5475 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005476
Bill Wendling13562a12012-02-07 09:06:01 +00005477 for (unsigned i = 0, e = DefinedClasses.size(); i < e; i++) {
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005478 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
5479 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
5480 continue;
5481 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005482 }
5483
Bill Wendling13562a12012-02-07 09:06:01 +00005484 for (unsigned i = 0, e = DefinedMetaClasses.size(); i < e; i++) {
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00005485 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
5486 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
5487 continue;
5488 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
5489 }
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005490
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005491 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005492 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
5493 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005494
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00005495 // Build list of all implemented category addresses in array
5496 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005497 AddModuleClassList(DefinedCategories,
Daniel Dunbar463b8762009-05-15 21:48:48 +00005498 "\01L_OBJC_LABEL_CATEGORY_$",
5499 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005500 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005501 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
5502 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005503
Daniel Dunbarfce176b2010-04-25 20:39:01 +00005504 EmitImageInfo();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005505}
5506
John McCall944c8432011-05-14 03:10:52 +00005507/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
5508/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005509/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00005510/// message dispatch call for all the rest.
John McCall944c8432011-05-14 03:10:52 +00005511bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
5512 // At various points we've experimented with using vtable-based
5513 // dispatch for all methods.
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00005514 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00005515 case CodeGenOptions::Legacy:
Fariborz Jahanian776dbf92010-04-19 17:53:30 +00005516 return false;
John McCall944c8432011-05-14 03:10:52 +00005517 case CodeGenOptions::NonLegacy:
5518 return true;
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00005519 case CodeGenOptions::Mixed:
5520 break;
5521 }
5522
5523 // If so, see whether this selector is in the white-list of things which must
5524 // use the new dispatch convention. We lazily build a dense set for this.
John McCall944c8432011-05-14 03:10:52 +00005525 if (VTableDispatchMethods.empty()) {
5526 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
5527 VTableDispatchMethods.insert(GetNullarySelector("class"));
5528 VTableDispatchMethods.insert(GetNullarySelector("self"));
5529 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
5530 VTableDispatchMethods.insert(GetNullarySelector("length"));
5531 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005532
John McCall944c8432011-05-14 03:10:52 +00005533 // These are vtable-based if GC is disabled.
5534 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikie4e4d0842012-03-11 07:00:24 +00005535 if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
John McCall944c8432011-05-14 03:10:52 +00005536 VTableDispatchMethods.insert(GetNullarySelector("retain"));
5537 VTableDispatchMethods.insert(GetNullarySelector("release"));
5538 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
5539 }
5540
5541 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
5542 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
5543 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
5544 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
5545 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
5546 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
5547 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
5548
5549 // These are vtable-based if GC is enabled.
5550 // Optimistically use vtable dispatch for hybrid compiles.
David Blaikie4e4d0842012-03-11 07:00:24 +00005551 if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
John McCall944c8432011-05-14 03:10:52 +00005552 VTableDispatchMethods.insert(GetNullarySelector("hash"));
5553 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
5554
5555 // "countByEnumeratingWithState:objects:count"
5556 IdentifierInfo *KeyIdents[] = {
5557 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
5558 &CGM.getContext().Idents.get("objects"),
5559 &CGM.getContext().Idents.get("count")
5560 };
5561 VTableDispatchMethods.insert(
5562 CGM.getContext().Selectors.getSelector(3, KeyIdents));
5563 }
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00005564 }
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00005565
John McCall944c8432011-05-14 03:10:52 +00005566 return VTableDispatchMethods.count(Sel);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00005567}
5568
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005569/// BuildClassRoTInitializer - generate meta-data for:
5570/// struct _class_ro_t {
5571/// uint32_t const flags;
5572/// uint32_t const instanceStart;
5573/// uint32_t const instanceSize;
5574/// uint32_t const reserved; // only when building for 64bit targets
5575/// const uint8_t * const ivarLayout;
5576/// const char *const name;
5577/// const struct _method_list_t * const baseMethods;
Fariborz Jahanianda320092009-01-29 19:24:30 +00005578/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005579/// const struct _ivar_list_t *const ivars;
5580/// const uint8_t * const weakIvarLayout;
5581/// const struct _prop_list_t * const properties;
5582/// }
5583///
5584llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005585 unsigned flags,
5586 unsigned InstanceStart,
5587 unsigned InstanceSize,
5588 const ObjCImplementationDecl *ID) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005589 std::string ClassName = ID->getNameAsString();
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005590 llvm::Constant *Values[10]; // 11 for 64bit targets!
John McCallf85e1932011-06-15 23:02:42 +00005591
David Blaikie4e4d0842012-03-11 07:00:24 +00005592 if (CGM.getLangOpts().ObjCAutoRefCount)
John McCall621915c2012-10-17 04:53:23 +00005593 flags |= NonFragileABI_Class_CompiledByARC;
John McCallf85e1932011-06-15 23:02:42 +00005594
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005595 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
5596 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
5597 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005598 // FIXME. For 64bit targets add 0 here.
John McCall621915c2012-10-17 04:53:23 +00005599 Values[ 3] = (flags & NonFragileABI_Class_Meta)
5600 ? GetIvarLayoutName(0, ObjCTypes)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005601 : BuildIvarLayout(ID, true);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005602 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005603 // const struct _method_list_t * const baseMethods;
5604 std::vector<llvm::Constant*> Methods;
5605 std::string MethodListName("\01l_OBJC_$_");
John McCall621915c2012-10-17 04:53:23 +00005606 if (flags & NonFragileABI_Class_Meta) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005607 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005608 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005609 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005610 // Class methods should always be defined.
5611 Methods.push_back(GetMethodConstant(*i));
5612 }
5613 } else {
5614 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005615 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005616 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005617 // Instance methods should always be defined.
5618 Methods.push_back(GetMethodConstant(*i));
5619 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005620 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005621 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
David Blaikie581deb32012-06-06 20:45:41 +00005622 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005623
Fariborz Jahanian939abce2009-01-28 22:46:49 +00005624 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
5625 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005626
Fariborz Jahanian939abce2009-01-28 22:46:49 +00005627 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
5628 if (llvm::Constant *C = GetMethodConstant(MD))
5629 Methods.push_back(C);
5630 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
5631 if (llvm::Constant *C = GetMethodConstant(MD))
5632 Methods.push_back(C);
5633 }
5634 }
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005635 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005636 Values[ 5] = EmitMethodList(MethodListName,
5637 "__DATA, __objc_const", Methods);
5638
Fariborz Jahanianda320092009-01-29 19:24:30 +00005639 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5640 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005641 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005642 + OID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00005643 OID->all_referenced_protocol_begin(),
5644 OID->all_referenced_protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005645
John McCall621915c2012-10-17 04:53:23 +00005646 if (flags & NonFragileABI_Class_Meta) {
Owen Andersonc9c88b42009-07-31 20:28:54 +00005647 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
John McCall621915c2012-10-17 04:53:23 +00005648 Values[ 8] = GetIvarLayoutName(0, ObjCTypes);
Owen Andersonc9c88b42009-07-31 20:28:54 +00005649 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
John McCall621915c2012-10-17 04:53:23 +00005650 } else {
5651 Values[ 7] = EmitIvarList(ID);
5652 Values[ 8] = BuildIvarLayout(ID, false);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005653 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
5654 ID, ID->getClassInterface(), ObjCTypes);
John McCall621915c2012-10-17 04:53:23 +00005655 }
Owen Anderson08e25242009-07-27 22:29:56 +00005656 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005657 Values);
5658 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005659 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
5660 llvm::GlobalValue::InternalLinkage,
5661 Init,
John McCall621915c2012-10-17 04:53:23 +00005662 (flags & NonFragileABI_Class_Meta) ?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005663 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
5664 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005665 CLASS_RO_GV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00005666 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005667 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005668 return CLASS_RO_GV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005669
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005670}
5671
5672/// BuildClassMetaData - This routine defines that to-level meta-data
5673/// for the given ClassName for:
5674/// struct _class_t {
5675/// struct _class_t *isa;
5676/// struct _class_t * const superclass;
5677/// void *cache;
5678/// IMP *vtable;
5679/// struct class_ro_t *ro;
5680/// }
5681///
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005682llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005683 std::string &ClassName,
5684 llvm::Constant *IsAGV,
5685 llvm::Constant *SuperClassGV,
5686 llvm::Constant *ClassRoGV,
5687 bool HiddenVisibility) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005688 llvm::Constant *Values[] = {
5689 IsAGV,
5690 SuperClassGV,
5691 ObjCEmptyCacheVar, // &ObjCEmptyCacheVar
5692 ObjCEmptyVtableVar, // &ObjCEmptyVtableVar
5693 ClassRoGV // &CLASS_RO_GV
5694 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005695 if (!Values[1])
5696 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005697 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005698 Values);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005699 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
5700 GV->setInitializer(Init);
Fariborz Jahaniandd0db2a2009-01-31 01:07:39 +00005701 GV->setSection("__DATA, __objc_data");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005702 GV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00005703 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005704 if (HiddenVisibility)
5705 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005706 return GV;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005707}
5708
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005709bool
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00005710CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005711 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005712}
5713
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005714void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00005715 uint32_t &InstanceStart,
5716 uint32_t &InstanceSize) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005717 const ASTRecordLayout &RL =
Daniel Dunbarb4c79e02009-05-04 21:26:30 +00005718 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005719
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00005720 // InstanceSize is really instance end.
Ken Dyckec299032011-02-11 02:20:09 +00005721 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00005722
5723 // If there are no fields, the start is the same as the end.
5724 if (!RL.getFieldCount())
5725 InstanceStart = InstanceSize;
5726 else
Ken Dyckfb67ccd2011-04-14 00:43:09 +00005727 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbarb02532a2009-04-19 23:41:48 +00005728}
5729
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005730void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
5731 std::string ClassName = ID->getNameAsString();
5732 if (!ObjCEmptyCacheVar) {
5733 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005734 CGM.getModule(),
5735 ObjCTypes.CacheTy,
5736 false,
5737 llvm::GlobalValue::ExternalLinkage,
5738 0,
5739 "_objc_empty_cache");
5740
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005741 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005742 CGM.getModule(),
5743 ObjCTypes.ImpnfABITy,
5744 false,
5745 llvm::GlobalValue::ExternalLinkage,
5746 0,
5747 "_objc_empty_vtable");
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005748 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005749 assert(ID->getClassInterface() &&
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005750 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbar6c1aac82009-04-20 20:18:54 +00005751 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005752 uint32_t InstanceStart =
Micah Villmow25a6a842012-10-08 16:25:52 +00005753 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005754 uint32_t InstanceSize = InstanceStart;
John McCall621915c2012-10-17 04:53:23 +00005755 uint32_t flags = NonFragileABI_Class_Meta;
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005756 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
5757 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005758
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005759 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005760
John McCallb03527a2012-10-17 04:53:31 +00005761 // Build the flags for the metaclass.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005762 bool classIsHidden =
John McCall1fb0caa2010-10-22 21:05:15 +00005763 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005764 if (classIsHidden)
John McCall621915c2012-10-17 04:53:23 +00005765 flags |= NonFragileABI_Class_Hidden;
John McCallb03527a2012-10-17 04:53:31 +00005766
5767 // FIXME: why is this flag set on the metaclass?
5768 // ObjC metaclasses have no fields and don't really get constructed.
5769 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCall621915c2012-10-17 04:53:23 +00005770 flags |= NonFragileABI_Class_HasCXXStructors;
John McCallb03527a2012-10-17 04:53:31 +00005771 if (!ID->hasNonZeroConstructors())
5772 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5773 }
5774
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005775 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005776 // class is root
John McCall621915c2012-10-17 04:53:23 +00005777 flags |= NonFragileABI_Class_Root;
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005778 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005779 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005780 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005781 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00005782 const ObjCInterfaceDecl *Root = ID->getClassInterface();
5783 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
5784 Root = Super;
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005785 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005786 if (Root->isWeakImported())
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00005787 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00005788 // work on super class metadata symbol.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005789 std::string SuperClassName =
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00005790 ObjCMetaClassName +
5791 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005792 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005793 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005794 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00005795 }
5796 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
5797 InstanceStart,
5798 InstanceSize,ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005799 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005800 llvm::GlobalVariable *MetaTClass =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005801 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
5802 classIsHidden);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005803 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005804
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005805 // Metadata for the class
John McCall621915c2012-10-17 04:53:23 +00005806 flags = 0;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005807 if (classIsHidden)
John McCall621915c2012-10-17 04:53:23 +00005808 flags |= NonFragileABI_Class_Hidden;
John McCallb03527a2012-10-17 04:53:31 +00005809
5810 if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
John McCall621915c2012-10-17 04:53:23 +00005811 flags |= NonFragileABI_Class_HasCXXStructors;
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005812
John McCallb03527a2012-10-17 04:53:31 +00005813 // Set a flag to enable a runtime optimization when a class has
5814 // fields that require destruction but which don't require
5815 // anything except zero-initialization during construction. This
5816 // is most notably true of __strong and __weak types, but you can
5817 // also imagine there being C++ types with non-trivial default
5818 // constructors that merely set all fields to null.
5819 if (!ID->hasNonZeroConstructors())
5820 flags |= NonFragileABI_Class_HasCXXDestructorOnly;
5821 }
5822
Douglas Gregor68584ed2009-06-18 16:11:24 +00005823 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
John McCall621915c2012-10-17 04:53:23 +00005824 flags |= NonFragileABI_Class_Exception;
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005825
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005826 if (!ID->getClassInterface()->getSuperClass()) {
John McCall621915c2012-10-17 04:53:23 +00005827 flags |= NonFragileABI_Class_Root;
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005828 SuperClassGV = 0;
Chris Lattnerb7b58b12009-04-19 06:02:28 +00005829 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005830 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00005831 std::string RootClassName =
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005832 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005833 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005834 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005835 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005836 }
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005837 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005838 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00005839 InstanceStart,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005840 InstanceSize,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00005841 ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005842
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005843 TClassName = ObjCClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005844 llvm::GlobalVariable *ClassMD =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005845 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5846 classIsHidden);
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00005847 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005848
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005849 // Determine if this class is also "non-lazy".
5850 if (ImplementationIsNonLazy(ID))
5851 DefinedNonLazyClasses.push_back(ClassMD);
5852
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005853 // Force the definition of the EHType if necessary.
John McCall621915c2012-10-17 04:53:23 +00005854 if (flags & NonFragileABI_Class_Exception)
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005855 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00005856 // Make sure method definition entries are all clear for next implementation.
5857 MethodDefinitions.clear();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005858}
5859
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005860/// GenerateProtocolRef - This routine is called to generate code for
5861/// a protocol reference expression; as in:
5862/// @code
5863/// @protocol(Proto1);
5864/// @endcode
5865/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5866/// which will hold address of the protocol meta-data.
5867///
5868llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005869 const ObjCProtocolDecl *PD) {
5870
Fariborz Jahanian960cd062009-04-10 18:47:34 +00005871 // This routine is called for @protocol only. So, we must build definition
5872 // of protocol's meta-data (not a reference to it!)
5873 //
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005874 llvm::Constant *Init =
5875 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Douglas Gregor4c86fdb2012-01-17 18:36:30 +00005876 ObjCTypes.getExternalProtocolPtrTy());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005877
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005878 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar4087f272010-08-17 22:39:59 +00005879 ProtocolName += PD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005880
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005881 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5882 if (PTGV)
Benjamin Kramer578faa82011-09-27 21:06:10 +00005883 return Builder.CreateLoad(PTGV);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005884 PTGV = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005885 CGM.getModule(),
5886 Init->getType(), false,
5887 llvm::GlobalValue::WeakAnyLinkage,
5888 Init,
5889 ProtocolName);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005890 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5891 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005892 CGM.AddUsedGlobal(PTGV);
Benjamin Kramer578faa82011-09-27 21:06:10 +00005893 return Builder.CreateLoad(PTGV);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005894}
5895
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005896/// GenerateCategory - Build metadata for a category implementation.
5897/// struct _category_t {
5898/// const char * const name;
5899/// struct _class_t *const cls;
5900/// const struct _method_list_t * const instance_methods;
5901/// const struct _method_list_t * const class_methods;
5902/// const struct _protocol_list_t * const protocols;
5903/// const struct _prop_list_t * const properties;
5904/// }
5905///
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005906void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005907 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005908 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005909 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5910 "_$_" + OCD->getNameAsString());
5911 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005912 Interface->getNameAsString());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005913
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005914 llvm::Constant *Values[6];
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005915 Values[0] = GetClassName(OCD->getIdentifier());
5916 // meta-class entry symbol
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005917 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005918 if (Interface->isWeakImported())
Fariborz Jahanian2cdcc4c2009-11-17 22:02:21 +00005919 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5920
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005921 Values[1] = ClassGV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005922 std::vector<llvm::Constant*> Methods;
5923 std::string MethodListName(Prefix);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005924 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005925 "_$_" + OCD->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005926
5927 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005928 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005929 // Instance methods should always be defined.
5930 Methods.push_back(GetMethodConstant(*i));
5931 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005932
5933 Values[2] = EmitMethodList(MethodListName,
5934 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005935 Methods);
5936
5937 MethodListName = Prefix;
5938 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5939 OCD->getNameAsString();
5940 Methods.clear();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005941 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005942 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005943 // Class methods should always be defined.
5944 Methods.push_back(GetMethodConstant(*i));
5945 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005946
5947 Values[3] = EmitMethodList(MethodListName,
5948 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005949 Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005950 const ObjCCategoryDecl *Category =
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00005951 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005952 if (Category) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00005953 SmallString<256> ExtName;
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005954 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5955 << OCD->getName();
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005956 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005957 + Interface->getName() + "_$_"
5958 + Category->getName(),
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005959 Category->protocol_begin(),
5960 Category->protocol_end());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005961 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5962 OCD, Category, ObjCTypes);
Mike Stumpb3589f42009-07-30 22:28:39 +00005963 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00005964 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5965 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005966 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005967
5968 llvm::Constant *Init =
5969 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005970 Values);
5971 llvm::GlobalVariable *GCATV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005972 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005973 false,
5974 llvm::GlobalValue::InternalLinkage,
5975 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005976 ExtCatName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005977 GCATV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00005978 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005979 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerad64e022009-07-17 23:57:13 +00005980 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005981 DefinedCategories.push_back(GCATV);
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005982
5983 // Determine if this category is also "non-lazy".
5984 if (ImplementationIsNonLazy(OCD))
5985 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00005986 // method definition entries must be clear for next implementation.
5987 MethodDefinitions.clear();
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005988}
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005989
5990/// GetMethodConstant - Return a struct objc_method constant for the
5991/// given method if it has been defined. The result is null if the
5992/// method has not been defined. The return value has type MethodPtrTy.
5993llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005994 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00005995 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005996 if (!Fn)
5997 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005998
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005999 llvm::Constant *Method[] = {
Owen Anderson3c4972d2009-07-29 18:54:39 +00006000 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006001 ObjCTypes.SelectorPtrTy),
6002 GetMethodVarType(MD),
6003 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
6004 };
Owen Anderson08e25242009-07-27 22:29:56 +00006005 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006006}
6007
6008/// EmitMethodList - Build meta-data for method declarations
6009/// struct _method_list_t {
6010/// uint32_t entsize; // sizeof(struct _objc_method)
6011/// uint32_t method_count;
6012/// struct _objc_method method_list[method_count];
6013/// }
6014///
Bill Wendlingbb028552012-02-07 09:25:09 +00006015llvm::Constant *
6016CGObjCNonFragileABIMac::EmitMethodList(Twine Name,
6017 const char *Section,
6018 ArrayRef<llvm::Constant*> Methods) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006019 // Return null for empty list.
6020 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00006021 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006022
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006023 llvm::Constant *Values[3];
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006024 // sizeof(struct _objc_method)
Micah Villmow25a6a842012-10-08 16:25:52 +00006025 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006026 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006027 // method_count
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006028 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00006029 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006030 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00006031 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006032 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006033
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006034 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00006035 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006036 llvm::GlobalValue::InternalLinkage, Init, Name);
Micah Villmow25a6a842012-10-08 16:25:52 +00006037 GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006038 GV->setSection(Section);
Chris Lattnerad64e022009-07-17 23:57:13 +00006039 CGM.AddUsedGlobal(GV);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006040 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00006041}
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006042
Fariborz Jahanianed157d32009-02-10 20:21:06 +00006043/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
6044/// the given ivar.
Daniel Dunbare83be122010-04-02 21:14:02 +00006045llvm::GlobalVariable *
6046CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
6047 const ObjCIvarDecl *Ivar) {
6048 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbara81419d2009-05-05 00:36:57 +00006049 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregor6ab35242009-04-09 21:40:53 +00006050 '.' + Ivar->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006051 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanianed157d32009-02-10 20:21:06 +00006052 CGM.getModule().getGlobalVariable(Name);
6053 if (!IvarOffsetGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006054 IvarOffsetGV =
Owen Anderson1c431b32009-07-08 19:05:04 +00006055 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanianed157d32009-02-10 20:21:06 +00006056 false,
6057 llvm::GlobalValue::ExternalLinkage,
6058 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00006059 Name);
Fariborz Jahanianed157d32009-02-10 20:21:06 +00006060 return IvarOffsetGV;
6061}
6062
Daniel Dunbare83be122010-04-02 21:14:02 +00006063llvm::Constant *
6064CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
6065 const ObjCIvarDecl *Ivar,
Eli Friedmane5b46662012-11-06 22:15:52 +00006066 unsigned long int Offset) {
Daniel Dunbar737c5022009-04-19 00:44:02 +00006067 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006068 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Eli Friedmane5b46662012-11-06 22:15:52 +00006069 Offset));
Fariborz Jahanian09796d62009-01-31 02:43:27 +00006070 IvarOffsetGV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006071 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbar737c5022009-04-19 00:44:02 +00006072
Mike Stumpf5408fe2009-05-16 07:57:57 +00006073 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
6074 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbar737c5022009-04-19 00:44:02 +00006075 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6076 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall1fb0caa2010-10-22 21:05:15 +00006077 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00006078 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar04d40782009-04-14 06:00:08 +00006079 else
Fariborz Jahanian77c9fd22009-04-06 18:30:00 +00006080 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendling1f382512011-05-04 21:37:25 +00006081 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanian45012a72009-02-03 00:09:52 +00006082 return IvarOffsetGV;
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00006083}
6084
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006085/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar11394522009-04-18 08:51:00 +00006086/// implementation. The return value has type
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006087/// IvarListnfABIPtrTy.
6088/// struct _ivar_t {
6089/// unsigned long int *offset; // pointer to ivar offset location
6090/// char *name;
6091/// char *type;
6092/// uint32_t alignment;
6093/// uint32_t size;
6094/// }
6095/// struct _ivar_list_t {
6096/// uint32 entsize; // sizeof(struct _ivar_t)
6097/// uint32 count;
6098/// struct _iver_t list[count];
6099/// }
6100///
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00006101
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006102llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006103 const ObjCImplementationDecl *ID) {
6104
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006105 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006106
Jordy Rosedb8264e2011-07-22 02:08:32 +00006107 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006108 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006109
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00006110 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006111
Jordy Rosedb8264e2011-07-22 02:08:32 +00006112 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00006113 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00006114 // Ignore unnamed bit-fields.
6115 if (!IVD->getDeclName())
6116 continue;
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006117 llvm::Constant *Ivar[5];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006118 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00006119 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00006120 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
6121 Ivar[2] = GetMethodVarType(IVD);
Chris Lattner2acc6e32011-07-18 04:24:23 +00006122 llvm::Type *FieldTy =
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00006123 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Micah Villmow25a6a842012-10-08 16:25:52 +00006124 unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006125 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006126 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006127 Align = llvm::Log2_32(Align);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006128 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbar91636d62009-04-20 00:33:43 +00006129 // NOTE. Size of a bitfield does not match gcc's, because of the
6130 // way bitfields are treated special in each. But I am told that
6131 // 'size' for bitfield ivars is ignored by the runtime so it does
6132 // not matter. If it matters, there is enough info to get the
6133 // bitfield right!
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006134 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson08e25242009-07-27 22:29:56 +00006135 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006136 }
6137 // Return null for empty list.
6138 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00006139 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006140
6141 llvm::Constant *Values[3];
Micah Villmow25a6a842012-10-08 16:25:52 +00006142 unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006143 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
6144 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00006145 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006146 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00006147 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006148 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006149 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
6150 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00006151 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00006152 llvm::GlobalValue::InternalLinkage,
6153 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006154 Prefix + OID->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00006155 GV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006156 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00006157 GV->setSection("__DATA, __objc_const");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006158
Chris Lattnerad64e022009-07-17 23:57:13 +00006159 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00006160 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006161}
6162
6163llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006164 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00006165 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006166
Fariborz Jahanianda320092009-01-29 19:24:30 +00006167 if (!Entry) {
6168 // We use the initializer as a marker of whether this is a forward
6169 // reference or not. At module finalization we add the empty
6170 // contents for protocols which were referenced but never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006171 Entry =
6172 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
6173 llvm::GlobalValue::ExternalLinkage,
6174 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006175 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianda320092009-01-29 19:24:30 +00006176 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00006177 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006178
Fariborz Jahanianda320092009-01-29 19:24:30 +00006179 return Entry;
6180}
6181
6182/// GetOrEmitProtocol - Generate the protocol meta-data:
6183/// @code
6184/// struct _protocol_t {
6185/// id isa; // NULL
6186/// const char * const protocol_name;
6187/// const struct _protocol_list_t * protocol_list; // super protocols
6188/// const struct method_list_t * const instance_methods;
6189/// const struct method_list_t * const class_methods;
6190/// const struct method_list_t *optionalInstanceMethods;
6191/// const struct method_list_t *optionalClassMethods;
6192/// const struct _prop_list_t * properties;
6193/// const uint32_t size; // sizeof(struct _protocol_t)
6194/// const uint32_t flags; // = 0
Bob Wilsondc8dab62011-11-30 01:57:58 +00006195/// const char ** extendedMethodTypes;
Fariborz Jahanianda320092009-01-29 19:24:30 +00006196/// }
6197/// @endcode
6198///
6199
6200llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006201 const ObjCProtocolDecl *PD) {
John McCall50651b92012-03-30 21:29:05 +00006202 llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006203
Fariborz Jahanianda320092009-01-29 19:24:30 +00006204 // Early exit if a defining object has already been generated.
6205 if (Entry && Entry->hasInitializer())
6206 return Entry;
6207
Douglas Gregor1d784b22012-01-01 19:51:50 +00006208 // Use the protocol definition, if there is one.
6209 if (const ObjCProtocolDecl *Def = PD->getDefinition())
6210 PD = Def;
6211
Fariborz Jahanianda320092009-01-29 19:24:30 +00006212 // Construct method lists.
6213 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
6214 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Bob Wilsondc8dab62011-11-30 01:57:58 +00006215 std::vector<llvm::Constant*> MethodTypesExt, OptMethodTypesExt;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006216 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00006217 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00006218 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006219 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00006220 if (!C)
6221 return GetOrEmitProtocolRef(PD);
6222
Fariborz Jahanianda320092009-01-29 19:24:30 +00006223 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6224 OptInstanceMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00006225 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanianda320092009-01-29 19:24:30 +00006226 } else {
6227 InstanceMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00006228 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006229 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00006230 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006231
6232 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00006233 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00006234 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006235 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00006236 if (!C)
6237 return GetOrEmitProtocolRef(PD);
6238
Fariborz Jahanianda320092009-01-29 19:24:30 +00006239 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6240 OptClassMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00006241 OptMethodTypesExt.push_back(GetMethodVarType(MD, true));
Fariborz Jahanianda320092009-01-29 19:24:30 +00006242 } else {
6243 ClassMethods.push_back(C);
Bob Wilsondc8dab62011-11-30 01:57:58 +00006244 MethodTypesExt.push_back(GetMethodVarType(MD, true));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006245 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00006246 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006247
Bob Wilsondc8dab62011-11-30 01:57:58 +00006248 MethodTypesExt.insert(MethodTypesExt.end(),
6249 OptMethodTypesExt.begin(), OptMethodTypesExt.end());
6250
6251 llvm::Constant *Values[11];
Fariborz Jahanianda320092009-01-29 19:24:30 +00006252 // isa is NULL
Owen Andersonc9c88b42009-07-31 20:28:54 +00006253 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006254 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006255 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
6256 PD->protocol_begin(),
6257 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006258
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006259 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006260 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00006261 "__DATA, __objc_const",
6262 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006263 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006264 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00006265 "__DATA, __objc_const",
6266 ClassMethods);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006267 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006268 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00006269 "__DATA, __objc_const",
6270 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006271 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006272 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00006273 "__DATA, __objc_const",
6274 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006275 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00006276 0, PD, ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006277 uint32_t Size =
Micah Villmow25a6a842012-10-08 16:25:52 +00006278 CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006279 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Andersonc9c88b42009-07-31 20:28:54 +00006280 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Bob Wilsondc8dab62011-11-30 01:57:58 +00006281 Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_"
6282 + PD->getName(),
6283 MethodTypesExt, ObjCTypes);
Owen Anderson08e25242009-07-27 22:29:56 +00006284 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanianda320092009-01-29 19:24:30 +00006285 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006286
Fariborz Jahanianda320092009-01-29 19:24:30 +00006287 if (Entry) {
6288 // Already created, fix the linkage and update the initializer.
Mike Stump286acbd2009-03-07 16:33:28 +00006289 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006290 Entry->setInitializer(Init);
6291 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006292 Entry =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006293 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
6294 false, llvm::GlobalValue::WeakAnyLinkage, Init,
6295 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00006296 Entry->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006297 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanianda320092009-01-29 19:24:30 +00006298 Entry->setSection("__DATA,__datacoal_nt,coalesced");
John McCall50651b92012-03-30 21:29:05 +00006299
6300 Protocols[PD->getIdentifier()] = Entry;
Fariborz Jahanianda320092009-01-29 19:24:30 +00006301 }
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00006302 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00006303 CGM.AddUsedGlobal(Entry);
6304
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00006305 // Use this protocol meta-data to build protocol list table in section
6306 // __DATA, __objc_protolist
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006307 llvm::GlobalVariable *PTGV =
6308 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
6309 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
6310 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00006311 PTGV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006312 CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbar0bf21992009-04-15 02:56:18 +00006313 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00006314 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00006315 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006316 return Entry;
6317}
6318
6319/// EmitProtocolList - Generate protocol list meta-data:
6320/// @code
6321/// struct _protocol_list_t {
6322/// long protocol_count; // Note, this is 32/64 bit
6323/// struct _protocol_t[protocol_count];
6324/// }
6325/// @endcode
6326///
6327llvm::Constant *
Chris Lattner5f9e2722011-07-23 10:55:15 +00006328CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006329 ObjCProtocolDecl::protocol_iterator begin,
6330 ObjCProtocolDecl::protocol_iterator end) {
Bill Wendling3964e622012-02-09 22:16:49 +00006331 llvm::SmallVector<llvm::Constant*, 16> ProtocolRefs;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006332
Fariborz Jahanianda320092009-01-29 19:24:30 +00006333 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006334 if (begin == end)
Owen Andersonc9c88b42009-07-31 20:28:54 +00006335 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006336
Daniel Dunbar948e2582009-02-15 07:36:20 +00006337 // FIXME: We shouldn't need to do this lookup here, should we?
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00006338 SmallString<256> TmpName;
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006339 Name.toVector(TmpName);
6340 llvm::GlobalVariable *GV =
6341 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006342 if (GV)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006343 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006344
Daniel Dunbar948e2582009-02-15 07:36:20 +00006345 for (; begin != end; ++begin)
6346 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
6347
Fariborz Jahanianda320092009-01-29 19:24:30 +00006348 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00006349 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006350 ObjCTypes.ProtocolnfABIPtrTy));
6351
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006352 llvm::Constant *Values[2];
Owen Andersona1cf15f2009-07-14 23:10:40 +00006353 Values[0] =
Owen Anderson4a28d5d2009-07-24 23:12:58 +00006354 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006355 Values[1] =
Bill Wendling3964e622012-02-09 22:16:49 +00006356 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
6357 ProtocolRefs.size()),
6358 ProtocolRefs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006359
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006360 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Owen Anderson1c431b32009-07-08 19:05:04 +00006361 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanianda320092009-01-29 19:24:30 +00006362 llvm::GlobalValue::InternalLinkage,
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006363 Init, Name);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006364 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00006365 GV->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006366 CGM.getDataLayout().getABITypeAlignment(Init->getType()));
Chris Lattnerad64e022009-07-17 23:57:13 +00006367 CGM.AddUsedGlobal(GV);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006368 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar948e2582009-02-15 07:36:20 +00006369 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00006370}
6371
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006372/// GetMethodDescriptionConstant - This routine build following meta-data:
6373/// struct _objc_method {
6374/// SEL _cmd;
6375/// char *method_type;
6376/// char *_imp;
6377/// }
6378
6379llvm::Constant *
6380CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006381 llvm::Constant *Desc[3];
Owen Andersona1cf15f2009-07-14 23:10:40 +00006382 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006383 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
6384 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006385 Desc[1] = GetMethodVarType(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00006386 if (!Desc[1])
6387 return 0;
6388
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00006389 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00006390 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00006391 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00006392}
Fariborz Jahanian45012a72009-02-03 00:09:52 +00006393
6394/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
6395/// This code gen. amounts to generating code for:
6396/// @code
6397/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
6398/// @encode
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006399///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00006400LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall506b57e2010-05-17 21:00:27 +00006401 CodeGen::CodeGenFunction &CGF,
6402 QualType ObjectTy,
6403 llvm::Value *BaseValue,
6404 const ObjCIvarDecl *Ivar,
6405 unsigned CVRQualifiers) {
6406 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Fariborz Jahaniancd285d02012-02-20 22:42:22 +00006407 llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
6408 if (llvm::LoadInst *LI = dyn_cast<llvm::LoadInst>(Offset))
6409 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6410 llvm::MDNode::get(VMContext,
6411 ArrayRef<llvm::Value*>()));
Daniel Dunbar97776872009-04-22 07:32:20 +00006412 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
Fariborz Jahaniancd285d02012-02-20 22:42:22 +00006413 Offset);
Fariborz Jahanian45012a72009-02-03 00:09:52 +00006414}
6415
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00006416llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006417 CodeGen::CodeGenFunction &CGF,
6418 const ObjCInterfaceDecl *Interface,
6419 const ObjCIvarDecl *Ivar) {
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00006420 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00006421}
6422
John McCallb1e81442011-05-13 23:16:18 +00006423static void appendSelectorForMessageRefTable(std::string &buffer,
6424 Selector selector) {
6425 if (selector.isUnarySelector()) {
6426 buffer += selector.getNameForSlot(0);
6427 return;
6428 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006429
John McCallb1e81442011-05-13 23:16:18 +00006430 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
6431 buffer += selector.getNameForSlot(i);
6432 buffer += '_';
6433 }
6434}
6435
John McCall944c8432011-05-14 03:10:52 +00006436/// Emit a "v-table" message send. We emit a weak hidden-visibility
6437/// struct, initially containing the selector pointer and a pointer to
6438/// a "fixup" variant of the appropriate objc_msgSend. To call, we
6439/// load and call the function pointer, passing the address of the
6440/// struct as the second parameter. The runtime determines whether
6441/// the selector is currently emitted using vtable dispatch; if so, it
6442/// substitutes a stub function which simply tail-calls through the
6443/// appropriate vtable slot, and if not, it substitues a stub function
6444/// which tail-calls objc_msgSend. Both stubs adjust the selector
6445/// argument to correctly point to the selector.
6446RValue
6447CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
6448 ReturnValueSlot returnSlot,
6449 QualType resultType,
6450 Selector selector,
6451 llvm::Value *arg0,
6452 QualType arg0Type,
6453 bool isSuper,
6454 const CallArgList &formalArgs,
6455 const ObjCMethodDecl *method) {
John McCallb1e81442011-05-13 23:16:18 +00006456 // Compute the actual arguments.
6457 CallArgList args;
6458
John McCall944c8432011-05-14 03:10:52 +00006459 // First argument: the receiver / super-call structure.
John McCallb1e81442011-05-13 23:16:18 +00006460 if (!isSuper)
John McCall944c8432011-05-14 03:10:52 +00006461 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
6462 args.add(RValue::get(arg0), arg0Type);
John McCallb1e81442011-05-13 23:16:18 +00006463
John McCall944c8432011-05-14 03:10:52 +00006464 // Second argument: a pointer to the message ref structure. Leave
6465 // the actual argument value blank for now.
John McCallb1e81442011-05-13 23:16:18 +00006466 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
6467
6468 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
6469
John McCallde5d3c72012-02-17 03:33:10 +00006470 MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);
John McCallb1e81442011-05-13 23:16:18 +00006471
John McCallcba681a2011-05-14 21:12:11 +00006472 NullReturnState nullReturn;
6473
John McCall944c8432011-05-14 03:10:52 +00006474 // Find the function to call and the mangled name for the message
6475 // ref structure. Using a different mangled name wouldn't actually
6476 // be a problem; it would just be a waste.
6477 //
6478 // The runtime currently never uses vtable dispatch for anything
6479 // except normal, non-super message-sends.
6480 // FIXME: don't use this for that.
John McCallb1e81442011-05-13 23:16:18 +00006481 llvm::Constant *fn = 0;
6482 std::string messageRefName("\01l_");
John McCallde5d3c72012-02-17 03:33:10 +00006483 if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
John McCallb1e81442011-05-13 23:16:18 +00006484 if (isSuper) {
6485 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
6486 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00006487 } else {
John McCallcba681a2011-05-14 21:12:11 +00006488 nullReturn.init(CGF, arg0);
John McCallb1e81442011-05-13 23:16:18 +00006489 fn = ObjCTypes.getMessageSendStretFixupFn();
6490 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00006491 }
John McCallb1e81442011-05-13 23:16:18 +00006492 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
6493 fn = ObjCTypes.getMessageSendFpretFixupFn();
6494 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stumpb3589f42009-07-30 22:28:39 +00006495 } else {
John McCallb1e81442011-05-13 23:16:18 +00006496 if (isSuper) {
6497 fn = ObjCTypes.getMessageSendSuper2FixupFn();
6498 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00006499 } else {
John McCallb1e81442011-05-13 23:16:18 +00006500 fn = ObjCTypes.getMessageSendFixupFn();
6501 messageRefName += "objc_msgSend_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00006502 }
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00006503 }
John McCallb1e81442011-05-13 23:16:18 +00006504 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
6505 messageRefName += '_';
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006506
John McCallb1e81442011-05-13 23:16:18 +00006507 // Append the selector name, except use underscores anywhere we
6508 // would have used colons.
6509 appendSelectorForMessageRefTable(messageRefName, selector);
6510
6511 llvm::GlobalVariable *messageRef
6512 = CGM.getModule().getGlobalVariable(messageRefName);
6513 if (!messageRef) {
John McCall944c8432011-05-14 03:10:52 +00006514 // Build the message ref structure.
John McCallb1e81442011-05-13 23:16:18 +00006515 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
Chris Lattnerc5cbb902011-06-20 04:01:35 +00006516 llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
John McCallb1e81442011-05-13 23:16:18 +00006517 messageRef = new llvm::GlobalVariable(CGM.getModule(),
6518 init->getType(),
6519 /*constant*/ false,
6520 llvm::GlobalValue::WeakAnyLinkage,
6521 init,
6522 messageRefName);
6523 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
6524 messageRef->setAlignment(16);
6525 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
6526 }
Fariborz Jahanian3c52d362012-01-30 23:39:30 +00006527
6528 bool requiresnullCheck = false;
David Blaikie4e4d0842012-03-11 07:00:24 +00006529 if (CGM.getLangOpts().ObjCAutoRefCount && method)
Fariborz Jahanian3c52d362012-01-30 23:39:30 +00006530 for (ObjCMethodDecl::param_const_iterator i = method->param_begin(),
6531 e = method->param_end(); i != e; ++i) {
6532 const ParmVarDecl *ParamDecl = (*i);
6533 if (ParamDecl->hasAttr<NSConsumedAttr>()) {
6534 if (!nullReturn.NullBB)
6535 nullReturn.init(CGF, arg0);
6536 requiresnullCheck = true;
6537 break;
6538 }
6539 }
6540
John McCallb1e81442011-05-13 23:16:18 +00006541 llvm::Value *mref =
6542 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
6543
John McCall944c8432011-05-14 03:10:52 +00006544 // Update the message ref argument.
John McCallb1e81442011-05-13 23:16:18 +00006545 args[1].RV = RValue::get(mref);
6546
6547 // Load the function to call from the message ref table.
6548 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
6549 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
6550
John McCallde5d3c72012-02-17 03:33:10 +00006551 callee = CGF.Builder.CreateBitCast(callee, MSI.MessengerType);
John McCallb1e81442011-05-13 23:16:18 +00006552
John McCallde5d3c72012-02-17 03:33:10 +00006553 RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
Fariborz Jahanian3c52d362012-01-30 23:39:30 +00006554 return nullReturn.complete(CGF, result, resultType, formalArgs,
6555 requiresnullCheck ? method : 0);
Fariborz Jahanian46551122009-02-04 00:22:57 +00006556}
6557
6558/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbard6c93d72009-09-17 04:01:22 +00006559CodeGen::RValue
6560CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00006561 ReturnValueSlot Return,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00006562 QualType ResultType,
6563 Selector Sel,
6564 llvm::Value *Receiver,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00006565 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00006566 const ObjCInterfaceDecl *Class,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00006567 const ObjCMethodDecl *Method) {
John McCall944c8432011-05-14 03:10:52 +00006568 return isVTableDispatchedSelector(Sel)
6569 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006570 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00006571 false, CallArgs, Method)
6572 : EmitMessageSend(CGF, Return, ResultType,
6573 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006574 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00006575 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian46551122009-02-04 00:22:57 +00006576}
6577
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00006578llvm::GlobalVariable *
Fariborz Jahanian0f902942009-04-14 18:41:56 +00006579CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00006580 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
6581
Daniel Dunbardfff2302009-03-02 05:18:14 +00006582 if (!GV) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006583 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Anderson1c431b32009-07-08 19:05:04 +00006584 false, llvm::GlobalValue::ExternalLinkage,
6585 0, Name);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00006586 }
6587
6588 return GV;
6589}
6590
John McCallf85e1932011-06-15 23:02:42 +00006591llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CGBuilderTy &Builder,
6592 IdentifierInfo *II) {
6593 llvm::GlobalVariable *&Entry = ClassReferences[II];
6594
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006595 if (!Entry) {
John McCallf85e1932011-06-15 23:02:42 +00006596 std::string ClassName(getClassSymbolPrefix() + II->getName().str());
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00006597 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006598 Entry =
John McCallf85e1932011-06-15 23:02:42 +00006599 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
6600 false, llvm::GlobalValue::InternalLinkage,
6601 ClassGV,
6602 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006603 Entry->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006604 CGM.getDataLayout().getABITypeAlignment(
John McCallf85e1932011-06-15 23:02:42 +00006605 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00006606 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00006607 CGM.AddUsedGlobal(Entry);
Daniel Dunbar11394522009-04-18 08:51:00 +00006608 }
John McCallf85e1932011-06-15 23:02:42 +00006609
Benjamin Kramer578faa82011-09-27 21:06:10 +00006610 return Builder.CreateLoad(Entry);
Daniel Dunbar11394522009-04-18 08:51:00 +00006611}
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006612
John McCallf85e1932011-06-15 23:02:42 +00006613llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
6614 const ObjCInterfaceDecl *ID) {
6615 return EmitClassRefFromId(Builder, ID->getIdentifier());
6616}
6617
6618llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
6619 CGBuilderTy &Builder) {
6620 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
6621 return EmitClassRefFromId(Builder, II);
6622}
6623
Daniel Dunbar11394522009-04-18 08:51:00 +00006624llvm::Value *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006625CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00006626 const ObjCInterfaceDecl *ID) {
6627 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006628
Daniel Dunbar11394522009-04-18 08:51:00 +00006629 if (!Entry) {
6630 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6631 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006632 Entry =
6633 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00006634 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006635 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00006636 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar11394522009-04-18 08:51:00 +00006637 Entry->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006638 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006639 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00006640 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00006641 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006642 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006643
Benjamin Kramer578faa82011-09-27 21:06:10 +00006644 return Builder.CreateLoad(Entry);
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006645}
6646
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006647/// EmitMetaClassRef - Return a Value * of the address of _class_t
6648/// meta-data
6649///
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006650llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
6651 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006652 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
6653 if (Entry)
Benjamin Kramer578faa82011-09-27 21:06:10 +00006654 return Builder.CreateLoad(Entry);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006655
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006656 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00006657 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006658 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00006659 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006660 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006661 MetaClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00006662 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006663 Entry->setAlignment(
Micah Villmow25a6a842012-10-08 16:25:52 +00006664 CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006665 ObjCTypes.ClassnfABIPtrTy));
6666
Daniel Dunbar33af70f2009-04-15 19:03:14 +00006667 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00006668 CGM.AddUsedGlobal(Entry);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006669
Benjamin Kramer578faa82011-09-27 21:06:10 +00006670 return Builder.CreateLoad(Entry);
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006671}
6672
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006673/// GetClass - Return a reference to the class for the given interface
6674/// decl.
6675llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
6676 const ObjCInterfaceDecl *ID) {
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00006677 if (ID->isWeakImported()) {
Fariborz Jahanian269f8bc2009-11-17 22:42:00 +00006678 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
6679 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
6680 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
6681 }
6682
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00006683 return EmitClassRef(Builder, ID);
6684}
6685
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006686/// Generates a message send where the super is the receiver. This is
6687/// a message send to self with special delivery semantics indicating
6688/// which class's method should be called.
6689CodeGen::RValue
6690CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00006691 ReturnValueSlot Return,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006692 QualType ResultType,
6693 Selector Sel,
6694 const ObjCInterfaceDecl *Class,
6695 bool isCategoryImpl,
6696 llvm::Value *Receiver,
6697 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00006698 const CodeGen::CallArgList &CallArgs,
6699 const ObjCMethodDecl *Method) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006700 // ...
6701 // Create and init a super structure; this is a (receiver, class)
6702 // pair we will pass to objc_msgSendSuper.
6703 llvm::Value *ObjCSuper =
John McCall604da292011-03-04 08:00:29 +00006704 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006705
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006706 llvm::Value *ReceiverAsObject =
6707 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
6708 CGF.Builder.CreateStore(ReceiverAsObject,
6709 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006710
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006711 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00006712 llvm::Value *Target;
Fariborz Jahanianb9966bd2012-10-10 23:11:18 +00006713 if (IsClassMessage)
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00006714 Target = EmitMetaClassRef(CGF.Builder, Class);
Fariborz Jahanianb9966bd2012-10-10 23:11:18 +00006715 else
Daniel Dunbar11394522009-04-18 08:51:00 +00006716 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006717
Mike Stumpf5408fe2009-05-16 07:57:57 +00006718 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
6719 // ObjCTypes types.
Chris Lattner2acc6e32011-07-18 04:24:23 +00006720 llvm::Type *ClassTy =
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006721 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
6722 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
6723 CGF.Builder.CreateStore(Target,
6724 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006725
John McCall944c8432011-05-14 03:10:52 +00006726 return (isVTableDispatchedSelector(Sel))
6727 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006728 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00006729 true, CallArgs, Method)
6730 : EmitMessageSend(CGF, Return, ResultType,
6731 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006732 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00006733 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00006734}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006735
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006736llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian03b29602010-06-17 19:56:20 +00006737 Selector Sel, bool lval) {
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006738 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006739
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006740 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006741 llvm::Constant *Casted =
6742 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
6743 ObjCTypes.SelectorPtrTy);
6744 Entry =
6745 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
6746 llvm::GlobalValue::InternalLinkage,
6747 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00006748 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00006749 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006750 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006751
Fariborz Jahanian03b29602010-06-17 19:56:20 +00006752 if (lval)
6753 return Entry;
Pete Cooperb6d71142011-11-10 21:45:06 +00006754 llvm::LoadInst* LI = Builder.CreateLoad(Entry);
6755
6756 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
6757 llvm::MDNode::get(VMContext,
6758 ArrayRef<llvm::Value*>()));
6759 return LI;
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006760}
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006761/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00006762/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006763///
6764void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00006765 llvm::Value *src,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00006766 llvm::Value *dst,
6767 llvm::Value *ivarOffset) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00006768 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006769 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00006770 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006771 assert(Size <= 8 && "does not support size > 8");
6772 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6773 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00006774 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6775 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006776 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6777 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00006778 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
6779 src, dst, ivarOffset);
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006780 return;
6781}
6782
6783/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
6784/// objc_assign_strongCast (id src, id *dst)
6785///
6786void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006787 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00006788 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00006789 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006790 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00006791 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006792 assert(Size <= 8 && "does not support size > 8");
6793 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006794 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00006795 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6796 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006797 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6798 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00006799 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006800 src, dst, "weakassign");
6801 return;
6802}
6803
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00006804void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006805 CodeGen::CodeGenFunction &CGF,
6806 llvm::Value *DestPtr,
6807 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00006808 llvm::Value *Size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00006809 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
6810 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00006811 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00006812 DestPtr, SrcPtr, Size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00006813 return;
6814}
6815
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006816/// EmitObjCWeakRead - Code gen for loading value of a __weak
6817/// object: objc_read_weak (id *src)
6818///
6819llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006820 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00006821 llvm::Value *AddrWeakObj) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00006822 llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006823 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
6824 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00006825 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006826 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00006827 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006828 return read_weak;
6829}
6830
6831/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
6832/// objc_assign_weak (id src, id *dst)
6833///
6834void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00006835 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00006836 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006837 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00006838 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006839 assert(Size <= 8 && "does not support size > 8");
6840 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6841 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00006842 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6843 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006844 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6845 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00006846 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006847 src, dst, "weakassign");
6848 return;
6849}
6850
6851/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
6852/// objc_assign_global (id src, id *dst)
6853///
6854void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00006855 llvm::Value *src, llvm::Value *dst,
6856 bool threadlocal) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00006857 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006858 if (!isa<llvm::PointerType>(SrcTy)) {
Micah Villmow25a6a842012-10-08 16:25:52 +00006859 unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00006860 assert(Size <= 8 && "does not support size > 8");
6861 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
6862 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00006863 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6864 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006865 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6866 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00006867 if (!threadlocal)
6868 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
6869 src, dst, "globalassign");
6870 else
6871 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
6872 src, dst, "threadlocalassign");
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006873 return;
6874}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006875
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006876void
John McCallf1549f62010-07-06 01:34:17 +00006877CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6878 const ObjCAtSynchronizedStmt &S) {
David Chisnall05dc91b2011-03-25 17:46:35 +00006879 EmitAtSynchronizedStmt(CGF, S,
6880 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6881 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallf1549f62010-07-06 01:34:17 +00006882}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006883
John McCall5a180392010-07-24 00:37:23 +00006884llvm::Constant *
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00006885CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall5a180392010-07-24 00:37:23 +00006886 // There's a particular fixed type info for 'id'.
6887 if (T->isObjCIdType() ||
6888 T->isObjCQualifiedIdType()) {
6889 llvm::Constant *IDEHType =
6890 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6891 if (!IDEHType)
6892 IDEHType =
6893 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6894 false,
6895 llvm::GlobalValue::ExternalLinkage,
6896 0, "OBJC_EHTYPE_id");
6897 return IDEHType;
6898 }
6899
6900 // All other types should be Objective-C interface pointer types.
6901 const ObjCObjectPointerType *PT =
6902 T->getAs<ObjCObjectPointerType>();
6903 assert(PT && "Invalid @catch type.");
6904 const ObjCInterfaceType *IT = PT->getInterfaceType();
6905 assert(IT && "Invalid @catch type.");
6906 return GetInterfaceEHType(IT->getDecl(), false);
6907}
6908
John McCallf1549f62010-07-06 01:34:17 +00006909void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6910 const ObjCAtTryStmt &S) {
David Chisnall05dc91b2011-03-25 17:46:35 +00006911 EmitTryCatchStmt(CGF, S,
6912 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6913 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6914 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006915}
6916
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006917/// EmitThrowStmt - Generate code for a throw statement.
6918void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6919 const ObjCAtThrowStmt &S) {
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006920 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall2b014d62011-10-01 10:32:24 +00006921 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer578faa82011-09-27 21:06:10 +00006922 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Jay Foad4c7d9f12011-07-15 08:37:34 +00006923 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall7ec404c2010-10-16 08:21:07 +00006924 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006925 } else {
Jay Foad4c7d9f12011-07-15 08:37:34 +00006926 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall7ec404c2010-10-16 08:21:07 +00006927 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006928 }
6929
John McCall7ec404c2010-10-16 08:21:07 +00006930 CGF.Builder.CreateUnreachable();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006931 CGF.Builder.ClearInsertionPoint();
6932}
Daniel Dunbare588b992009-03-01 04:46:24 +00006933
John McCall5a180392010-07-24 00:37:23 +00006934llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006935CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006936 bool ForDefinition) {
Daniel Dunbare588b992009-03-01 04:46:24 +00006937 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbare588b992009-03-01 04:46:24 +00006938
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006939 // If we don't need a definition, return the entry if found or check
6940 // if we use an external reference.
6941 if (!ForDefinition) {
6942 if (Entry)
6943 return Entry;
Daniel Dunbar7e075cb2009-04-07 06:43:45 +00006944
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006945 // If this type (or a super class) has the __objc_exception__
6946 // attribute, emit an external reference.
Douglas Gregor68584ed2009-06-18 16:11:24 +00006947 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006948 return Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00006949 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006950 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006951 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006952 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006953 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006954 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006955
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006956 // Otherwise we need to either make a new entry or fill in the
6957 // initializer.
6958 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006959 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbare588b992009-03-01 04:46:24 +00006960 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006961 llvm::GlobalVariable *VTableGV =
Daniel Dunbare588b992009-03-01 04:46:24 +00006962 CGM.getModule().getGlobalVariable(VTableName);
6963 if (!VTableGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006964 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6965 false,
Daniel Dunbare588b992009-03-01 04:46:24 +00006966 llvm::GlobalValue::ExternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00006967 0, VTableName);
Daniel Dunbare588b992009-03-01 04:46:24 +00006968
Chris Lattner8b418682012-02-07 00:39:47 +00006969 llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
Daniel Dunbare588b992009-03-01 04:46:24 +00006970
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006971 llvm::Constant *Values[] = {
6972 llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
6973 GetClassName(ID->getIdentifier()),
6974 GetClassGlobal(ClassName)
6975 };
Owen Andersona1cf15f2009-07-14 23:10:40 +00006976 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00006977 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbare588b992009-03-01 04:46:24 +00006978
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006979 if (Entry) {
6980 Entry->setInitializer(Init);
6981 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00006982 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006983 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006984 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006985 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006986 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006987 }
6988
David Blaikie4e4d0842012-03-11 07:00:24 +00006989 if (CGM.getLangOpts().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006990 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Micah Villmow25a6a842012-10-08 16:25:52 +00006991 Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00006992 ObjCTypes.EHTypeTy));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006993
6994 if (ForDefinition) {
6995 Entry->setSection("__DATA,__objc_const");
6996 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6997 } else {
6998 Entry->setSection("__DATA,__datacoal_nt,coalesced");
6999 }
Daniel Dunbare588b992009-03-01 04:46:24 +00007000
7001 return Entry;
7002}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00007003
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00007004/* *** */
7005
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00007006CodeGen::CGObjCRuntime *
7007CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
John McCall260611a2012-06-20 06:18:46 +00007008 switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
7009 case ObjCRuntime::FragileMacOSX:
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00007010 return new CGObjCMac(CGM);
John McCall260611a2012-06-20 06:18:46 +00007011
7012 case ObjCRuntime::MacOSX:
7013 case ObjCRuntime::iOS:
7014 return new CGObjCNonFragileABIMac(CGM);
7015
David Chisnall11d3f4c2012-07-03 20:49:52 +00007016 case ObjCRuntime::GNUstep:
7017 case ObjCRuntime::GCC:
John McCallf7226fb2012-07-12 02:07:58 +00007018 case ObjCRuntime::ObjFW:
John McCall260611a2012-06-20 06:18:46 +00007019 llvm_unreachable("these runtimes are not Mac runtimes");
7020 }
7021 llvm_unreachable("bad runtime");
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00007022}