blob: 1db50a8f578ea21013df2498fb21019170874042 [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"
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +000039#include "llvm/Target/TargetData.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
Daniel Dunbar97776872009-04-22 07:32:20 +000045
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000046namespace {
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000047
Daniel Dunbar6bff2512009-08-03 17:06:42 +000048typedef std::vector<llvm::Constant*> ConstantVector;
Daniel Dunbarae226fa2008-08-27 02:31:56 +000049
Daniel Dunbar6bff2512009-08-03 17:06:42 +000050// FIXME: We should find a nicer way to make the labels for metadata, string
51// concatenation is lame.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000052
Fariborz Jahanianee0af742009-01-21 22:04:16 +000053class ObjCCommonTypesHelper {
Owen Andersona1cf15f2009-07-14 23:10:40 +000054protected:
55 llvm::LLVMContext &VMContext;
Daniel Dunbar6bff2512009-08-03 17:06:42 +000056
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000057private:
John McCall0774cb82011-05-15 01:53:33 +000058 // The types of these functions don't really matter because we
59 // should always bitcast before calling them.
60
61 /// id objc_msgSend (id, SEL, ...)
62 ///
63 /// The default messenger, used for sends whose ABI is unchanged from
64 /// the all-integer/pointer case.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000065 llvm::Constant *getMessageSendFn() const {
John McCallf85e1932011-06-15 23:02:42 +000066 // Add the non-lazy-bind attribute, since objc_msgSend is likely to
67 // be called a lot.
Chris Lattner9cbe4f02011-07-09 17:41:47 +000068 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall0774cb82011-05-15 01:53:33 +000069 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
70 params, true),
John McCallf85e1932011-06-15 23:02:42 +000071 "objc_msgSend",
72 llvm::Attribute::NonLazyBind);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000073 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000074
John McCall0774cb82011-05-15 01:53:33 +000075 /// void objc_msgSend_stret (id, SEL, ...)
76 ///
77 /// The messenger used when the return value is an aggregate returned
78 /// by indirect reference in the first argument, and therefore the
79 /// self and selector parameters are shifted over by one.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000080 llvm::Constant *getMessageSendStretFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +000081 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall0774cb82011-05-15 01:53:33 +000082 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy,
83 params, true),
84 "objc_msgSend_stret");
Daniel Dunbar6bff2512009-08-03 17:06:42 +000085
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000086 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000087
John McCall0774cb82011-05-15 01:53:33 +000088 /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
89 ///
90 /// The messenger used when the return value is returned on the x87
91 /// floating-point stack; without a special entrypoint, the nil case
92 /// would be unbalanced.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000093 llvm::Constant *getMessageSendFpretFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +000094 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall0774cb82011-05-15 01:53:33 +000095 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(
Owen Anderson0032b272009-08-13 21:57:51 +000096 llvm::Type::getDoubleTy(VMContext),
John McCall0774cb82011-05-15 01:53:33 +000097 params, true),
98 "objc_msgSend_fpret");
Daniel Dunbar6bff2512009-08-03 17:06:42 +000099
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000100 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000101
Anders Carlssoneea64802011-10-31 16:27:11 +0000102 /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
103 ///
104 /// The messenger used when the return value is returned in two values on the
105 /// x87 floating point stack; without a special entrypoint, the nil case
106 /// would be unbalanced. Only used on 64-bit X86.
107 llvm::Constant *getMessageSendFp2retFn() const {
108 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
109 llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
110 llvm::Type *resultType =
111 llvm::StructType::get(longDoubleType, longDoubleType, NULL);
112
113 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType,
114 params, true),
115 "objc_msgSend_fp2ret");
116 }
117
John McCall0774cb82011-05-15 01:53:33 +0000118 /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
119 ///
120 /// The messenger used for super calls, which have different dispatch
121 /// semantics. The class passed is the superclass of the current
122 /// class.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000123 llvm::Constant *getMessageSendSuperFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000124 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000125 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000126 params, true),
127 "objc_msgSendSuper");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000128 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000129
John McCall0774cb82011-05-15 01:53:33 +0000130 /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
131 ///
132 /// A slightly different messenger used for super calls. The class
133 /// passed is the current class.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000134 llvm::Constant *getMessageSendSuperFn2() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000135 llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000136 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000137 params, true),
138 "objc_msgSendSuper2");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000139 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000140
John McCall0774cb82011-05-15 01:53:33 +0000141 /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
142 /// SEL op, ...)
143 ///
144 /// The messenger used for super calls which return an aggregate indirectly.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000145 llvm::Constant *getMessageSendSuperStretFn() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000146 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000147 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000148 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000149 "objc_msgSendSuper_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000150 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000151
John McCall0774cb82011-05-15 01:53:33 +0000152 /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
153 /// SEL op, ...)
154 ///
155 /// objc_msgSendSuper_stret with the super2 semantics.
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000156 llvm::Constant *getMessageSendSuperStretFn2() const {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000157 llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000158 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000159 llvm::FunctionType::get(CGM.VoidTy, params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000160 "objc_msgSendSuper2_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000161 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000162
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000163 llvm::Constant *getMessageSendSuperFpretFn() const {
164 // There is no objc_msgSendSuper_fpret? How can that work?
165 return getMessageSendSuperFn();
166 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000167
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000168 llvm::Constant *getMessageSendSuperFpretFn2() const {
169 // There is no objc_msgSendSuper_fpret? How can that work?
170 return getMessageSendSuperFn2();
171 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000172
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000173protected:
174 CodeGen::CodeGenModule &CGM;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000175
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000176public:
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000177 llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
178 llvm::Type *Int8PtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000179
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000180 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000181 llvm::Type *ObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000182
Fariborz Jahanian6d657c42008-11-18 20:18:11 +0000183 /// PtrObjectPtrTy - LLVM type for id *
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000184 llvm::Type *PtrObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000185
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000186 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000187 llvm::Type *SelectorPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000188 /// ProtocolPtrTy - LLVM type for external protocol handles
189 /// (typeof(Protocol))
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000190 llvm::Type *ExternalProtocolPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000191
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000192 // SuperCTy - clang type for struct objc_super.
193 QualType SuperCTy;
194 // SuperPtrCTy - clang type for struct objc_super *.
195 QualType SuperPtrCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000196
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000197 /// SuperTy - LLVM type for struct objc_super.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000198 llvm::StructType *SuperTy;
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000199 /// SuperPtrTy - LLVM type for struct objc_super *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000200 llvm::Type *SuperPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000201
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000202 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
203 /// in GCC parlance).
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000204 llvm::StructType *PropertyTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000205
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000206 /// PropertyListTy - LLVM type for struct objc_property_list
207 /// (_prop_list_t in GCC parlance).
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000208 llvm::StructType *PropertyListTy;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000209 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000210 llvm::Type *PropertyListPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000211
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000212 // MethodTy - LLVM type for struct objc_method.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000213 llvm::StructType *MethodTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000214
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000215 /// CacheTy - LLVM type for struct objc_cache.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000216 llvm::Type *CacheTy;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000217 /// CachePtrTy - LLVM type for struct objc_cache *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000218 llvm::Type *CachePtrTy;
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +0000219
Chris Lattner72db6c32009-04-22 02:44:54 +0000220 llvm::Constant *getGetPropertyFn() {
221 CodeGen::CodeGenTypes &Types = CGM.getTypes();
222 ASTContext &Ctx = CGM.getContext();
223 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
Chris Lattner5f9e2722011-07-23 10:55:15 +0000224 SmallVector<CanQualType,4> Params;
John McCallead608a2010-02-26 00:48:12 +0000225 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
226 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattner72db6c32009-04-22 02:44:54 +0000227 Params.push_back(IdType);
228 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000229 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000230 Params.push_back(Ctx.BoolTy);
Chris Lattner2acc6e32011-07-18 04:24:23 +0000231 llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000232 Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000233 FunctionType::ExtInfo()),
234 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000235 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
236 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000237
Chris Lattner72db6c32009-04-22 02:44:54 +0000238 llvm::Constant *getSetPropertyFn() {
239 CodeGen::CodeGenTypes &Types = CGM.getTypes();
240 ASTContext &Ctx = CGM.getContext();
241 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
Chris Lattner5f9e2722011-07-23 10:55:15 +0000242 SmallVector<CanQualType,6> Params;
John McCallead608a2010-02-26 00:48:12 +0000243 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
244 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattner72db6c32009-04-22 02:44:54 +0000245 Params.push_back(IdType);
246 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000247 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000248 Params.push_back(IdType);
249 Params.push_back(Ctx.BoolTy);
250 Params.push_back(Ctx.BoolTy);
Chris Lattner2acc6e32011-07-18 04:24:23 +0000251 llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000252 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000253 FunctionType::ExtInfo()),
254 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000255 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
256 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000257
Fariborz Jahanian6cc59062010-04-12 18:18:10 +0000258
259 llvm::Constant *getCopyStructFn() {
260 CodeGen::CodeGenTypes &Types = CGM.getTypes();
261 ASTContext &Ctx = CGM.getContext();
262 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
Chris Lattner5f9e2722011-07-23 10:55:15 +0000263 SmallVector<CanQualType,5> Params;
Fariborz Jahanian6cc59062010-04-12 18:18:10 +0000264 Params.push_back(Ctx.VoidPtrTy);
265 Params.push_back(Ctx.VoidPtrTy);
266 Params.push_back(Ctx.LongTy);
267 Params.push_back(Ctx.BoolTy);
268 Params.push_back(Ctx.BoolTy);
Chris Lattner2acc6e32011-07-18 04:24:23 +0000269 llvm::FunctionType *FTy =
Fariborz Jahanian6cc59062010-04-12 18:18:10 +0000270 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
271 FunctionType::ExtInfo()),
272 false);
273 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
274 }
275
Chris Lattner72db6c32009-04-22 02:44:54 +0000276 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000277 CodeGen::CodeGenTypes &Types = CGM.getTypes();
278 ASTContext &Ctx = CGM.getContext();
Chris Lattner72db6c32009-04-22 02:44:54 +0000279 // void objc_enumerationMutation (id)
Chris Lattner5f9e2722011-07-23 10:55:15 +0000280 SmallVector<CanQualType,1> Params;
John McCallead608a2010-02-26 00:48:12 +0000281 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Chris Lattner2acc6e32011-07-18 04:24:23 +0000282 llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000283 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000284 FunctionType::ExtInfo()),
285 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000286 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
287 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000288
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000289 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattner72db6c32009-04-22 02:44:54 +0000290 llvm::Constant *getGcReadWeakFn() {
291 // id objc_read_weak (id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000292 llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000293 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000294 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000295 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000296 }
297
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000298 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner96508e12009-04-17 22:12:36 +0000299 llvm::Constant *getGcAssignWeakFn() {
300 // id objc_assign_weak (id, id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000301 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Chris Lattner96508e12009-04-17 22:12:36 +0000302 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000303 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattner96508e12009-04-17 22:12:36 +0000304 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
305 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000306
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000307 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000308 llvm::Constant *getGcAssignGlobalFn() {
309 // id objc_assign_global(id, id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000310 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000311 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000312 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000313 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
314 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000315
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000316 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
317 llvm::Constant *getGcAssignThreadLocalFn() {
318 // id objc_assign_threadlocal(id src, id * dest)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000319 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000320 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000321 llvm::FunctionType::get(ObjectPtrTy, args, false);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000322 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
323 }
324
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000325 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000326 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +0000327 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000328 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
329 CGM.PtrDiffTy };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000330 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000331 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000332 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
333 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000334
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000335 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
336 llvm::Constant *GcMemmoveCollectableFn() {
337 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000338 llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy };
John McCall0774cb82011-05-15 01:53:33 +0000339 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000340 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
341 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000342
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000343 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000344 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000345 // id objc_assign_strongCast(id, id *)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000346 llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000347 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000348 llvm::FunctionType::get(ObjectPtrTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000349 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
350 }
Anders Carlssonf57c5b22009-02-16 22:59:18 +0000351
352 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000353 llvm::Constant *getExceptionThrowFn() {
354 // void objc_exception_throw(id)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000355 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerbbccd612009-04-22 02:38:11 +0000356 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000357 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000358 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
359 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000360
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000361 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
362 llvm::Constant *getExceptionRethrowFn() {
363 // void objc_exception_rethrow(void)
John McCall0774cb82011-05-15 01:53:33 +0000364 llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000365 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
366 }
367
Daniel Dunbar1c566672009-02-24 01:43:46 +0000368 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000369 llvm::Constant *getSyncEnterFn() {
370 // void objc_sync_enter (id)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000371 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000372 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000373 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000374 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
375 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000376
Daniel Dunbar1c566672009-02-24 01:43:46 +0000377 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000378 llvm::Constant *getSyncExitFn() {
379 // void objc_sync_exit (id)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000380 llvm::Type *args[] = { ObjectPtrTy };
Chris Lattnerbbccd612009-04-22 02:38:11 +0000381 llvm::FunctionType *FTy =
John McCall0774cb82011-05-15 01:53:33 +0000382 llvm::FunctionType::get(CGM.VoidTy, args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000383 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
384 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000385
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000386 llvm::Constant *getSendFn(bool IsSuper) const {
387 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
388 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000389
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000390 llvm::Constant *getSendFn2(bool IsSuper) const {
391 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
392 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000393
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000394 llvm::Constant *getSendStretFn(bool IsSuper) const {
395 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
396 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000397
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000398 llvm::Constant *getSendStretFn2(bool IsSuper) const {
399 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
400 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000401
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000402 llvm::Constant *getSendFpretFn(bool IsSuper) const {
403 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
404 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000405
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000406 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
407 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
408 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000409
Anders Carlssoneea64802011-10-31 16:27:11 +0000410 llvm::Constant *getSendFp2retFn(bool IsSuper) const {
411 return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
412 }
413
414 llvm::Constant *getSendFp2RetFn2(bool IsSuper) const {
415 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
416 }
417
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000418 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
419 ~ObjCCommonTypesHelper(){}
420};
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000421
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000422/// ObjCTypesHelper - Helper class that encapsulates lazy
423/// construction of varies types used during ObjC generation.
424class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000425public:
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000426 /// SymtabTy - LLVM type for struct objc_symtab.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000427 llvm::StructType *SymtabTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000428 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000429 llvm::Type *SymtabPtrTy;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000430 /// ModuleTy - LLVM type for struct objc_module.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000431 llvm::StructType *ModuleTy;
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000432
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000433 /// ProtocolTy - LLVM type for struct objc_protocol.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000434 llvm::StructType *ProtocolTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000435 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000436 llvm::Type *ProtocolPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000437 /// ProtocolExtensionTy - LLVM type for struct
438 /// objc_protocol_extension.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000439 llvm::StructType *ProtocolExtensionTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000440 /// ProtocolExtensionTy - LLVM type for struct
441 /// objc_protocol_extension *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000442 llvm::Type *ProtocolExtensionPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000443 /// MethodDescriptionTy - LLVM type for struct
444 /// objc_method_description.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000445 llvm::StructType *MethodDescriptionTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000446 /// MethodDescriptionListTy - LLVM type for struct
447 /// objc_method_description_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000448 llvm::StructType *MethodDescriptionListTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000449 /// MethodDescriptionListPtrTy - LLVM type for struct
450 /// objc_method_description_list *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000451 llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000452 /// ProtocolListTy - LLVM type for struct objc_property_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000453 llvm::StructType *ProtocolListTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000454 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000455 llvm::Type *ProtocolListPtrTy;
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000456 /// CategoryTy - LLVM type for struct objc_category.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000457 llvm::StructType *CategoryTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000458 /// ClassTy - LLVM type for struct objc_class.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000459 llvm::StructType *ClassTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000460 /// ClassPtrTy - LLVM type for struct objc_class *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000461 llvm::Type *ClassPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000462 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000463 llvm::StructType *ClassExtensionTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000464 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000465 llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000466 // IvarTy - LLVM type for struct objc_ivar.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000467 llvm::StructType *IvarTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000468 /// IvarListTy - LLVM type for struct objc_ivar_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000469 llvm::Type *IvarListTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000470 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000471 llvm::Type *IvarListPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000472 /// MethodListTy - LLVM type for struct objc_method_list.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000473 llvm::Type *MethodListTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000474 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000475 llvm::Type *MethodListPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000476
Anders Carlsson124526b2008-09-09 10:10:21 +0000477 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000478 llvm::Type *ExceptionDataTy;
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +0000479
Anders Carlsson124526b2008-09-09 10:10:21 +0000480 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000481 llvm::Constant *getExceptionTryEnterFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000482 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000483 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000484 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000485 "objc_exception_try_enter");
Chris Lattner34b02a12009-04-22 02:26:14 +0000486 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000487
488 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000489 llvm::Constant *getExceptionTryExitFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000490 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Andersona1cf15f2009-07-14 23:10:40 +0000491 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000492 llvm::FunctionType::get(CGM.VoidTy, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000493 "objc_exception_try_exit");
Chris Lattner34b02a12009-04-22 02:26:14 +0000494 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000495
496 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000497 llvm::Constant *getExceptionExtractFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000498 llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000499 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000500 params, false),
Chris Lattner34b02a12009-04-22 02:26:14 +0000501 "objc_exception_extract");
Chris Lattner34b02a12009-04-22 02:26:14 +0000502 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000503
Anders Carlsson124526b2008-09-09 10:10:21 +0000504 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000505 llvm::Constant *getExceptionMatchFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000506 llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000507 return CGM.CreateRuntimeFunction(
John McCall0774cb82011-05-15 01:53:33 +0000508 llvm::FunctionType::get(CGM.Int32Ty, params, false),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000509 "objc_exception_match");
510
Chris Lattner34b02a12009-04-22 02:26:14 +0000511 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000512
Anders Carlsson124526b2008-09-09 10:10:21 +0000513 /// SetJmpFn - LLVM _setjmp function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000514 llvm::Constant *getSetJmpFn() {
John McCall0774cb82011-05-15 01:53:33 +0000515 // This is specifically the prototype for x86.
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000516 llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
John McCall0774cb82011-05-15 01:53:33 +0000517 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty,
518 params, false),
Bill Wendlinga9e269e2011-11-29 00:10:10 +0000519 "_setjmp",
520 llvm::Attribute::ReturnsTwice);
Chris Lattner34b02a12009-04-22 02:26:14 +0000521 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000522
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000523public:
524 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000525 ~ObjCTypesHelper() {}
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000526};
527
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000528/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000529/// modern abi
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000530class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000531public:
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000532
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000533 // MethodListnfABITy - LLVM for struct _method_list_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000534 llvm::StructType *MethodListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000535
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000536 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000537 llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000538
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000539 // ProtocolnfABITy = LLVM for struct _protocol_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000540 llvm::StructType *ProtocolnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000541
Daniel Dunbar948e2582009-02-15 07:36:20 +0000542 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000543 llvm::Type *ProtocolnfABIPtrTy;
Daniel Dunbar948e2582009-02-15 07:36:20 +0000544
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000545 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000546 llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000547
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000548 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000549 llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000550
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000551 // ClassnfABITy - LLVM for struct _class_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000552 llvm::StructType *ClassnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000553
Fariborz Jahanianaa23b572009-01-23 23:53:38 +0000554 // ClassnfABIPtrTy - LLVM for struct _class_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000555 llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000556
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000557 // IvarnfABITy - LLVM for struct _ivar_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000558 llvm::StructType *IvarnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000559
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000560 // IvarListnfABITy - LLVM for struct _ivar_list_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000561 llvm::StructType *IvarListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000562
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000563 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000564 llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000565
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000566 // ClassRonfABITy - LLVM for struct _class_ro_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000567 llvm::StructType *ClassRonfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000568
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000569 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000570 llvm::Type *ImpnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000571
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000572 // CategorynfABITy - LLVM for struct _category_t
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000573 llvm::StructType *CategorynfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000574
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000575 // New types for nonfragile abi messaging.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000576
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000577 // MessageRefTy - LLVM for:
578 // struct _message_ref_t {
579 // IMP messenger;
580 // SEL name;
581 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000582 llvm::StructType *MessageRefTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000583 // MessageRefCTy - clang type for struct _message_ref_t
584 QualType MessageRefCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000585
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000586 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000587 llvm::Type *MessageRefPtrTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000588 // MessageRefCPtrTy - clang type for struct _message_ref_t*
589 QualType MessageRefCPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000590
Fariborz Jahanianef163782009-02-05 01:13:09 +0000591 // MessengerTy - Type of the messenger (shown as IMP above)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000592 llvm::FunctionType *MessengerTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000593
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000594 // SuperMessageRefTy - LLVM for:
595 // struct _super_message_ref_t {
596 // SUPER_IMP messenger;
597 // SEL name;
598 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000599 llvm::StructType *SuperMessageRefTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000600
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000601 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000602 llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000603
Chris Lattner1c02f862009-04-22 02:53:24 +0000604 llvm::Constant *getMessageSendFixupFn() {
605 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000606 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000607 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000608 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000609 "objc_msgSend_fixup");
610 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000611
Chris Lattner1c02f862009-04-22 02:53:24 +0000612 llvm::Constant *getMessageSendFpretFixupFn() {
613 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000614 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000615 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000616 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000617 "objc_msgSend_fpret_fixup");
618 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000619
Chris Lattner1c02f862009-04-22 02:53:24 +0000620 llvm::Constant *getMessageSendStretFixupFn() {
621 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000622 llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000623 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000624 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000625 "objc_msgSend_stret_fixup");
626 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000627
Chris Lattner1c02f862009-04-22 02:53:24 +0000628 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000629 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000630 // struct _super_message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000631 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000632 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000633 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000634 "objc_msgSendSuper2_fixup");
635 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000636
Chris Lattner1c02f862009-04-22 02:53:24 +0000637 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000638 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000639 // struct _super_message_ref_t*, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000640 llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000641 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000642 params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000643 "objc_msgSendSuper2_stret_fixup");
644 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000645
Chris Lattner8a569112009-04-22 02:15:23 +0000646 llvm::Constant *getObjCEndCatchFn() {
John McCall0774cb82011-05-15 01:53:33 +0000647 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
Chris Lattner8a569112009-04-22 02:15:23 +0000648 "objc_end_catch");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000649
Chris Lattner8a569112009-04-22 02:15:23 +0000650 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000651
Chris Lattner8a569112009-04-22 02:15:23 +0000652 llvm::Constant *getObjCBeginCatchFn() {
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000653 llvm::Type *params[] = { Int8PtrTy };
Owen Anderson96e0fc72009-07-29 22:16:19 +0000654 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
John McCall0774cb82011-05-15 01:53:33 +0000655 params, false),
Chris Lattner8a569112009-04-22 02:15:23 +0000656 "objc_begin_catch");
657 }
Daniel Dunbare588b992009-03-01 04:46:24 +0000658
Chris Lattner9cbe4f02011-07-09 17:41:47 +0000659 llvm::StructType *EHTypeTy;
660 llvm::Type *EHTypePtrTy;
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +0000661
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000662 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
663 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000664};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000665
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000666class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000667public:
668 // FIXME - accessibility
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000669 class GC_IVAR {
Fariborz Jahanian820e0202009-03-11 00:07:04 +0000670 public:
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000671 unsigned ivar_bytepos;
672 unsigned ivar_size;
673 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000674 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar0941b492009-04-23 01:29:05 +0000675
676 // Allow sorting based on byte pos.
677 bool operator<(const GC_IVAR &b) const {
678 return ivar_bytepos < b.ivar_bytepos;
679 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000680 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000681
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000682 class SKIP_SCAN {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000683 public:
684 unsigned skip;
685 unsigned scan;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000686 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000687 : skip(_skip), scan(_scan) {}
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000688 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000689
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000690protected:
691 CodeGen::CodeGenModule &CGM;
Owen Anderson69243822009-07-13 04:10:07 +0000692 llvm::LLVMContext &VMContext;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000693 // FIXME! May not be needing this after all.
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000694 unsigned ObjCABI;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000695
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000696 // gc ivar layout bitmap calculation helper caches.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000697 SmallVector<GC_IVAR, 16> SkipIvars;
698 SmallVector<GC_IVAR, 16> IvarsInfo;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000699
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000700 /// LazySymbols - Symbols to generate a lazy reference for. See
701 /// DefinedSymbols and FinishModule().
Daniel Dunbar33063492009-09-07 00:20:42 +0000702 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000703
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000704 /// DefinedSymbols - External symbols which are defined by this
705 /// module. The symbols in this list and LazySymbols are used to add
706 /// special linker symbols which ensure that Objective-C modules are
707 /// linked properly.
Daniel Dunbar33063492009-09-07 00:20:42 +0000708 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000709
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000710 /// ClassNames - uniqued class names.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000711 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000712
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000713 /// MethodVarNames - uniqued method variable names.
714 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000715
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +0000716 /// DefinedCategoryNames - list of category names in form Class_Category.
717 llvm::SetVector<std::string> DefinedCategoryNames;
718
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000719 /// MethodVarTypes - uniqued method type signatures. We have to use
720 /// a StringMap here because have no other unique reference.
721 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000722
Daniel Dunbarc45ef602008-08-26 21:51:14 +0000723 /// MethodDefinitions - map of methods which have been defined in
724 /// this translation unit.
725 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000726
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000727 /// PropertyNames - uniqued method variable names.
728 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000729
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000730 /// ClassReferences - uniqued class references.
731 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000732
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000733 /// SelectorReferences - uniqued selector references.
734 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000735
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000736 /// Protocols - Protocols for which an objc_protocol structure has
737 /// been emitted. Forward declarations are handled by creating an
738 /// empty structure whose initializer is filled in when/if defined.
739 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000740
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000741 /// DefinedProtocols - Protocols which have actually been
742 /// defined. We should not need this, see FIXME in GenerateProtocol.
743 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000744
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000745 /// DefinedClasses - List of defined classes.
746 std::vector<llvm::GlobalValue*> DefinedClasses;
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000747
748 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
749 std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000750
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000751 /// DefinedCategories - List of defined categories.
752 std::vector<llvm::GlobalValue*> DefinedCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000753
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000754 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
755 std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000756
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000757 /// GetNameForMethod - Return a name for the given method.
758 /// \param[out] NameOut - The return value.
759 void GetNameForMethod(const ObjCMethodDecl *OMD,
760 const ObjCContainerDecl *CD,
Chris Lattner5f9e2722011-07-23 10:55:15 +0000761 SmallVectorImpl<char> &NameOut);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000762
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000763 /// GetMethodVarName - Return a unique constant for the given
764 /// selector's name. The return value has type char *.
765 llvm::Constant *GetMethodVarName(Selector Sel);
766 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000767
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000768 /// GetMethodVarType - Return a unique constant for the given
769 /// selector's name. The return value has type char *.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000770
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000771 // FIXME: This is a horrible name.
772 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +0000773 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000774
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000775 /// GetPropertyName - Return a unique constant for the given
776 /// name. The return value has type char *.
777 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000778
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000779 // FIXME: This can be dropped once string functions are unified.
780 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
781 const Decl *Container);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000782
Fariborz Jahanian058a1b72009-01-24 20:21:50 +0000783 /// GetClassName - Return a unique constant for the given selector's
784 /// name. The return value has type char *.
785 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000786
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +0000787 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
788
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000789 /// BuildIvarLayout - Builds ivar layout bitmap for the class
790 /// implementation for the __strong or __weak case.
791 ///
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000792 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
793 bool ForStrongLayout);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +0000794
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +0000795 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000796
Daniel Dunbard58edcb2009-05-03 14:10:34 +0000797 void BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000798 unsigned int BytePos, bool ForStrongLayout,
799 bool &HasUnion);
Daniel Dunbar5a5a8032009-05-03 21:05:10 +0000800 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000801 const llvm::StructLayout *Layout,
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000802 const RecordDecl *RD,
Jordy Rosedb8264e2011-07-22 02:08:32 +0000803 const SmallVectorImpl<const FieldDecl*> &RecFields,
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000804 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahanian81adc052009-04-24 16:17:09 +0000805 bool &HasUnion);
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000806
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +0000807 /// GetIvarLayoutName - Returns a unique constant for the given
808 /// ivar layout bitmap.
809 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
810 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000811
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000812 /// EmitPropertyList - Emit the given property list. The return
813 /// value has type PropertyListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000814 llvm::Constant *EmitPropertyList(Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000815 const Decl *Container,
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000816 const ObjCContainerDecl *OCD,
817 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000818
Fariborz Jahanian191dcd72009-12-12 21:26:21 +0000819 /// PushProtocolProperties - Push protocol's property on the input stack.
820 void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
821 std::vector<llvm::Constant*> &Properties,
822 const Decl *Container,
823 const ObjCProtocolDecl *PROTO,
824 const ObjCCommonTypesHelper &ObjCTypes);
825
Fariborz Jahanianda320092009-01-29 19:24:30 +0000826 /// GetProtocolRef - Return a reference to the internal protocol
827 /// description, creating an empty one if it has not been
828 /// defined. The return value has type ProtocolPtrTy.
829 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanianb21f07e2009-03-08 20:18:37 +0000830
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000831 /// CreateMetadataVar - Create a global variable with internal
832 /// linkage for use by the Objective-C runtime.
833 ///
834 /// This is a convenience wrapper which not only creates the
835 /// variable, but also sets the section and alignment and adds the
Chris Lattnerad64e022009-07-17 23:57:13 +0000836 /// global to the "llvm.used" list.
Daniel Dunbar35bd7632009-03-09 20:50:13 +0000837 ///
838 /// \param Name - The variable name.
839 /// \param Init - The variable initializer; this is also used to
840 /// define the type of the variable.
841 /// \param Section - The section the variable should go into, or 0.
842 /// \param Align - The alignment for the variable, or 0.
843 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbarc1583062009-04-14 17:42:51 +0000844 /// "llvm.used".
Chris Lattner5f9e2722011-07-23 10:55:15 +0000845 llvm::GlobalVariable *CreateMetadataVar(Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000846 llvm::Constant *Init,
847 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +0000848 unsigned Align,
849 bool AddToUsed);
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000850
John McCall944c8432011-05-14 03:10:52 +0000851 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
852 ReturnValueSlot Return,
853 QualType ResultType,
854 llvm::Value *Sel,
855 llvm::Value *Arg0,
856 QualType Arg0Ty,
857 bool IsSuper,
858 const CallArgList &CallArgs,
859 const ObjCMethodDecl *OMD,
860 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +0000861
Daniel Dunbarfce176b2010-04-25 20:39:01 +0000862 /// EmitImageInfo - Emit the image info marker used to encode some module
863 /// level information.
864 void EmitImageInfo();
865
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000866public:
Owen Anderson69243822009-07-13 04:10:07 +0000867 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
Mike Stump1eb44332009-09-09 15:08:12 +0000868 CGM(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000869
David Chisnall0d13f6f2010-01-23 02:40:42 +0000870 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000871
Fariborz Jahanian493dab72009-01-26 21:38:32 +0000872 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
873 const ObjCContainerDecl *CD=0);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000874
Fariborz Jahanianda320092009-01-29 19:24:30 +0000875 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000876
Fariborz Jahanianda320092009-01-29 19:24:30 +0000877 /// GetOrEmitProtocol - Get the protocol object for the given
878 /// declaration, emitting it if necessary. The return value has type
879 /// ProtocolPtrTy.
880 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000881
Fariborz Jahanianda320092009-01-29 19:24:30 +0000882 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
883 /// object for the given declaration, emitting it if needed. These
884 /// forward references will be filled in with empty bodies if no
885 /// definition is seen. The return value has type ProtocolPtrTy.
886 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCall6b5a61b2011-02-07 10:33:21 +0000887 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
888 const CGBlockInfo &blockInfo);
Fariborz Jahanian89ecd412010-08-04 16:57:49 +0000889
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000890};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000891
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000892class CGObjCMac : public CGObjCCommonMac {
893private:
894 ObjCTypesHelper ObjCTypes;
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000895
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000896 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000897 /// information.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000898 void EmitModuleInfo();
899
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000900 /// EmitModuleSymols - Emit module symbols, the list of defined
901 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000902 llvm::Constant *EmitModuleSymbols();
903
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000904 /// FinishModule - Write out global data structures at the end of
905 /// processing a translation unit.
906 void FinishModule();
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000907
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000908 /// EmitClassExtension - Generate the class extension structure used
909 /// to store the weak ivar layout and properties. The return value
910 /// has type ClassExtensionPtrTy.
911 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
912
913 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
914 /// for the given class.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000915 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000916 const ObjCInterfaceDecl *ID);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +0000917
John McCallf85e1932011-06-15 23:02:42 +0000918 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
919 IdentifierInfo *II);
920
921 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
922
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +0000923 /// EmitSuperClassRef - Emits reference to class's main metadata class.
924 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000925
926 /// EmitIvarList - Emit the ivar list for the given
927 /// implementation. If ForClass is true the list of class ivars
928 /// (i.e. metaclass ivars) is emitted, otherwise the list of
929 /// interface ivars will be emitted. The return value has type
930 /// IvarListPtrTy.
931 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +0000932 bool ForClass);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000933
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000934 /// EmitMetaClass - Emit a forward reference to the class structure
935 /// for the metaclass of the given interface. The return value has
936 /// type ClassPtrTy.
937 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
938
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000939 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000940 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000941 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
942 llvm::Constant *Protocols,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000943 const ConstantVector &Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000944
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000945 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000946
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000947 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000948
949 /// EmitMethodList - Emit the method list for the given
Daniel Dunbaraf05bb92008-08-26 08:29:31 +0000950 /// implementation. The return value has type MethodListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000951 llvm::Constant *EmitMethodList(Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000952 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000953 const ConstantVector &Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000954
955 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000956 /// method declarations.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000957 /// - TypeName: The name for the type containing the methods.
958 /// - IsProtocol: True iff these methods are for a protocol.
959 /// - ClassMethds: True iff these are class methods.
960 /// - Required: When true, only "required" methods are
961 /// listed. Similarly, when false only "optional" methods are
962 /// listed. For classes this should always be true.
963 /// - begin, end: The method list to output.
964 ///
965 /// The return value has type MethodDescriptionListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000966 llvm::Constant *EmitMethodDescList(Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000967 const char *Section,
968 const ConstantVector &Methods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000969
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000970 /// GetOrEmitProtocol - Get the protocol object for the given
971 /// declaration, emitting it if necessary. The return value has type
972 /// ProtocolPtrTy.
Fariborz Jahanianda320092009-01-29 19:24:30 +0000973 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000974
975 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
976 /// object for the given declaration, emitting it if needed. These
977 /// forward references will be filled in with empty bodies if no
978 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanianda320092009-01-29 19:24:30 +0000979 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000980
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000981 /// EmitProtocolExtension - Generate the protocol extension
982 /// structure used to store optional instance and class methods, and
983 /// protocol properties. The return value has type
984 /// ProtocolExtensionPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000985 llvm::Constant *
986 EmitProtocolExtension(const ObjCProtocolDecl *PD,
987 const ConstantVector &OptInstanceMethods,
988 const ConstantVector &OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000989
990 /// EmitProtocolList - Generate the list of referenced
991 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000992 llvm::Constant *EmitProtocolList(Twine Name,
Daniel Dunbardbc933702008-08-21 21:57:41 +0000993 ObjCProtocolDecl::protocol_iterator begin,
994 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000995
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000996 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
997 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +0000998 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
999 bool lval=false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001000
1001public:
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001002 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001003
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001004 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001005
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001006 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001007 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001008 QualType ResultType,
1009 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001010 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001011 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001012 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001013 const ObjCMethodDecl *Method);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001014
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001015 virtual CodeGen::RValue
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001016 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001017 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001018 QualType ResultType,
1019 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001020 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001021 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001022 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001023 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001024 const CallArgList &CallArgs,
1025 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001026
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001027 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001028 const ObjCInterfaceDecl *ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001029
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001030 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1031 bool lval = false);
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001032
1033 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1034 /// untyped one.
1035 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1036 const ObjCMethodDecl *Method);
1037
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001038 virtual llvm::Constant *GetEHType(QualType T);
John McCall5a180392010-07-24 00:37:23 +00001039
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001040 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001041
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001042 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001043
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001044 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001045 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001046
Chris Lattner74391b42009-03-22 21:03:39 +00001047 virtual llvm::Constant *GetPropertyGetFunction();
1048 virtual llvm::Constant *GetPropertySetFunction();
David Chisnall8fac25d2010-12-26 22:13:16 +00001049 virtual llvm::Constant *GetGetStructFunction();
1050 virtual llvm::Constant *GetSetStructFunction();
Chris Lattner74391b42009-03-22 21:03:39 +00001051 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001052
John McCallf1549f62010-07-06 01:34:17 +00001053 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1054 const ObjCAtTryStmt &S);
1055 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1056 const ObjCAtSynchronizedStmt &S);
1057 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00001058 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1059 const ObjCAtThrowStmt &S);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001060 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001061 llvm::Value *AddrWeakObj);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001062 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001063 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001064 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001065 llvm::Value *src, llvm::Value *dest,
1066 bool threadlocal = false);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00001067 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001068 llvm::Value *src, llvm::Value *dest,
1069 llvm::Value *ivarOffset);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001070 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1071 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001072 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1073 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001074 llvm::Value *size);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001075
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001076 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1077 QualType ObjectTy,
1078 llvm::Value *BaseValue,
1079 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001080 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001081 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001082 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001083 const ObjCIvarDecl *Ivar);
Fariborz Jahanian6f40e222011-05-17 22:21:16 +00001084
1085 /// GetClassGlobal - Return the global variable for the Objective-C
1086 /// class of the given name.
1087 virtual llvm::GlobalVariable *GetClassGlobal(const std::string &Name) {
David Blaikieb219cfc2011-09-23 05:06:16 +00001088 llvm_unreachable("CGObjCMac::GetClassGlobal");
Fariborz Jahanian6f40e222011-05-17 22:21:16 +00001089 }
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001090};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001091
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001092class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001093private:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001094 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001095 llvm::GlobalVariable* ObjCEmptyCacheVar;
1096 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001097
Daniel Dunbar11394522009-04-18 08:51:00 +00001098 /// SuperClassReferences - uniqued super class references.
1099 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001100
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001101 /// MetaClassReferences - uniqued meta class references.
1102 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbare588b992009-03-01 04:46:24 +00001103
1104 /// EHTypeReferences - uniqued class ehtype references.
1105 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001106
John McCall944c8432011-05-14 03:10:52 +00001107 /// VTableDispatchMethods - List of methods for which we generate
1108 /// vtable-based message dispatch.
1109 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001110
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00001111 /// DefinedMetaClasses - List of defined meta-classes.
1112 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1113
John McCall944c8432011-05-14 03:10:52 +00001114 /// isVTableDispatchedSelector - Returns true if SEL is a
1115 /// vtable-based selector.
1116 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001117
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001118 /// FinishNonFragileABIModule - Write out global data structures at the end of
1119 /// processing a translation unit.
1120 void FinishNonFragileABIModule();
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001121
Daniel Dunbar463b8762009-05-15 21:48:48 +00001122 /// AddModuleClassList - Add the given list of class pointers to the
1123 /// module with the provided symbol and section names.
1124 void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
1125 const char *SymbolName,
1126 const char *SectionName);
1127
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001128 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1129 unsigned InstanceStart,
1130 unsigned InstanceSize,
1131 const ObjCImplementationDecl *ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001132 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001133 llvm::Constant *IsAGV,
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001134 llvm::Constant *SuperClassGV,
Fariborz Jahaniancf555162009-01-31 00:59:10 +00001135 llvm::Constant *ClassRoGV,
1136 bool HiddenVisibility);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001137
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001138 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001139
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00001140 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001141
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001142 /// EmitMethodList - Emit the method list for the given
1143 /// implementation. The return value has type MethodListnfABITy.
Chris Lattner5f9e2722011-07-23 10:55:15 +00001144 llvm::Constant *EmitMethodList(Twine Name,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001145 const char *Section,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00001146 const ConstantVector &Methods);
1147 /// EmitIvarList - Emit the ivar list for the given
1148 /// implementation. If ForClass is true the list of class ivars
1149 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1150 /// interface ivars will be emitted. The return value has type
1151 /// IvarListnfABIPtrTy.
1152 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001153
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001154 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00001155 const ObjCIvarDecl *Ivar,
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00001156 unsigned long int offset);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001157
Fariborz Jahanianda320092009-01-29 19:24:30 +00001158 /// GetOrEmitProtocol - Get the protocol object for the given
1159 /// declaration, emitting it if necessary. The return value has type
1160 /// ProtocolPtrTy.
1161 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001162
Fariborz Jahanianda320092009-01-29 19:24:30 +00001163 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1164 /// object for the given declaration, emitting it if needed. These
1165 /// forward references will be filled in with empty bodies if no
1166 /// definition is seen. The return value has type ProtocolPtrTy.
1167 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001168
Fariborz Jahanianda320092009-01-29 19:24:30 +00001169 /// EmitProtocolList - Generate the list of referenced
1170 /// protocols. The return value has type ProtocolListPtrTy.
Chris Lattner5f9e2722011-07-23 10:55:15 +00001171 llvm::Constant *EmitProtocolList(Twine Name,
Fariborz Jahanianda320092009-01-29 19:24:30 +00001172 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian46551122009-02-04 00:22:57 +00001173 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001174
John McCall944c8432011-05-14 03:10:52 +00001175 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1176 ReturnValueSlot Return,
1177 QualType ResultType,
1178 Selector Sel,
1179 llvm::Value *Receiver,
1180 QualType Arg0Ty,
1181 bool IsSuper,
1182 const CallArgList &CallArgs,
1183 const ObjCMethodDecl *Method);
Fariborz Jahanian6f40e222011-05-17 22:21:16 +00001184
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00001185 /// GetClassGlobal - Return the global variable for the Objective-C
1186 /// class of the given name.
Fariborz Jahanian0f902942009-04-14 18:41:56 +00001187 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Fariborz Jahanian6f40e222011-05-17 22:21:16 +00001188
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001189 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar11394522009-04-18 08:51:00 +00001190 /// for the given class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001191 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00001192 const ObjCInterfaceDecl *ID);
John McCallf85e1932011-06-15 23:02:42 +00001193
1194 llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
1195 IdentifierInfo *II);
1196
1197 llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001198
Daniel Dunbar11394522009-04-18 08:51:00 +00001199 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1200 /// for the given super class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001201 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1202 const ObjCInterfaceDecl *ID);
1203
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001204 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1205 /// meta-data
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001206 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001207 const ObjCInterfaceDecl *ID);
1208
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001209 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1210 /// the given ivar.
1211 ///
Daniel Dunbar5e88bea2009-04-19 00:31:15 +00001212 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001213 const ObjCInterfaceDecl *ID,
1214 const ObjCIvarDecl *Ivar);
1215
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00001216 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1217 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001218 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1219 bool lval=false);
Daniel Dunbare588b992009-03-01 04:46:24 +00001220
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001221 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbare588b992009-03-01 04:46:24 +00001222 /// interface. The return value has type EHTypePtrTy.
John McCall5a180392010-07-24 00:37:23 +00001223 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001224 bool ForDefinition);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001225
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001226 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001227 return "OBJC_METACLASS_$_";
1228 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001229
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001230 const char *getClassSymbolPrefix() const {
1231 return "OBJC_CLASS_$_";
1232 }
1233
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00001234 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001235 uint32_t &InstanceStart,
1236 uint32_t &InstanceSize);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001237
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001238 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001239 Selector GetNullarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001240 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1241 return CGM.getContext().Selectors.getSelector(0, &II);
1242 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001243
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001244 Selector GetUnarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001245 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1246 return CGM.getContext().Selectors.getSelector(1, &II);
1247 }
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001248
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001249 /// ImplementationIsNonLazy - Check whether the given category or
1250 /// class implementation is "non-lazy".
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00001251 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001252
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001253public:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001254 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001255 // FIXME. All stubs for now!
1256 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001257
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001258 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001259 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001260 QualType ResultType,
1261 Selector Sel,
1262 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001263 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001264 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001265 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001266
1267 virtual CodeGen::RValue
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001268 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001269 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001270 QualType ResultType,
1271 Selector Sel,
1272 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001273 bool isCategoryImpl,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001274 llvm::Value *Receiver,
1275 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001276 const CallArgList &CallArgs,
1277 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001278
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001279 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001280 const ObjCInterfaceDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001281
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001282 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1283 bool lvalue = false)
1284 { return EmitSelector(Builder, Sel, lvalue); }
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001285
1286 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1287 /// untyped one.
1288 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1289 const ObjCMethodDecl *Method)
1290 { return EmitSelector(Builder, Method->getSelector()); }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001291
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00001292 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001293
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001294 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001295 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00001296 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001297
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001298 virtual llvm::Constant *GetEHType(QualType T);
John McCall5a180392010-07-24 00:37:23 +00001299
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001300 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001301 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001302 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001303 virtual llvm::Constant *GetPropertySetFunction() {
1304 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001305 }
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001306
David Chisnall8fac25d2010-12-26 22:13:16 +00001307 virtual llvm::Constant *GetSetStructFunction() {
1308 return ObjCTypes.getCopyStructFn();
1309 }
1310 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001311 return ObjCTypes.getCopyStructFn();
1312 }
1313
Chris Lattner74391b42009-03-22 21:03:39 +00001314 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001315 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbar28ed0842009-02-16 18:48:45 +00001316 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001317
John McCallf1549f62010-07-06 01:34:17 +00001318 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1319 const ObjCAtTryStmt &S);
1320 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1321 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001322 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlssonf57c5b22009-02-16 22:59:18 +00001323 const ObjCAtThrowStmt &S);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001324 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001325 llvm::Value *AddrWeakObj);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001326 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001327 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001328 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001329 llvm::Value *src, llvm::Value *dest,
1330 bool threadlocal = false);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001331 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001332 llvm::Value *src, llvm::Value *dest,
1333 llvm::Value *ivarOffset);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001334 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001335 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001336 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1337 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001338 llvm::Value *size);
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001339 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1340 QualType ObjectTy,
1341 llvm::Value *BaseValue,
1342 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001343 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001344 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001345 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001346 const ObjCIvarDecl *Ivar);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001347};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001348
John McCallcba681a2011-05-14 21:12:11 +00001349/// A helper class for performing the null-initialization of a return
1350/// value.
1351struct NullReturnState {
1352 llvm::BasicBlock *NullBB;
Fariborz Jahanian6c29eda2011-10-26 20:53:59 +00001353 llvm::BasicBlock *callBB;
1354 NullReturnState() : NullBB(0), callBB(0) {}
John McCallcba681a2011-05-14 21:12:11 +00001355
1356 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1357 // Make blocks for the null-init and call edges.
1358 NullBB = CGF.createBasicBlock("msgSend.nullinit");
Fariborz Jahanian6c29eda2011-10-26 20:53:59 +00001359 callBB = CGF.createBasicBlock("msgSend.call");
John McCallcba681a2011-05-14 21:12:11 +00001360
1361 // Check for a null receiver and, if there is one, jump to the
1362 // null-init test.
1363 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1364 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1365
1366 // Otherwise, start performing the call.
1367 CGF.EmitBlock(callBB);
1368 }
1369
1370 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType) {
1371 if (!NullBB) return result;
1372
1373 // Finish the call path.
1374 llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
1375 if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
1376
1377 // Emit the null-init block and perform the null-initialization there.
1378 CGF.EmitBlock(NullBB);
Fariborz Jahanian6c29eda2011-10-26 20:53:59 +00001379 if (!resultType->isAnyComplexType()) {
1380 assert(result.isAggregate() && "null init of non-aggregate result?");
1381 CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
1382 // Jump to the continuation block.
1383 CGF.EmitBlock(contBB);
1384 return result;
1385 }
John McCallcba681a2011-05-14 21:12:11 +00001386
Fariborz Jahanian6c29eda2011-10-26 20:53:59 +00001387 // _Complex type
1388 // FIXME. Now easy to handle any other scalar type whose result is returned
1389 // in memory due to ABI limitations.
John McCallcba681a2011-05-14 21:12:11 +00001390 CGF.EmitBlock(contBB);
Fariborz Jahanian6c29eda2011-10-26 20:53:59 +00001391 CodeGenFunction::ComplexPairTy CallCV = result.getComplexVal();
1392 llvm::Type *MemberType = CallCV.first->getType();
1393 llvm::Constant *ZeroCV = llvm::Constant::getNullValue(MemberType);
1394 // Create phi instruction for scalar complex value.
1395 llvm::PHINode *PHIReal = CGF.Builder.CreatePHI(MemberType, 2);
1396 PHIReal->addIncoming(ZeroCV, NullBB);
1397 PHIReal->addIncoming(CallCV.first, callBB);
1398 llvm::PHINode *PHIImag = CGF.Builder.CreatePHI(MemberType, 2);
1399 PHIImag->addIncoming(ZeroCV, NullBB);
1400 PHIImag->addIncoming(CallCV.second, callBB);
1401 return RValue::getComplex(PHIReal, PHIImag);
John McCallcba681a2011-05-14 21:12:11 +00001402 }
1403};
1404
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001405} // end anonymous namespace
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001406
1407/* *** Helper Functions *** */
1408
1409/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Andersona1cf15f2009-07-14 23:10:40 +00001410static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001411 llvm::Constant *C,
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001412 unsigned idx0,
1413 unsigned idx1) {
1414 llvm::Value *Idxs[] = {
Owen Anderson0032b272009-08-13 21:57:51 +00001415 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1416 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001417 };
Jay Foada5c04342011-07-21 14:31:17 +00001418 return llvm::ConstantExpr::getGetElementPtr(C, Idxs);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001419}
1420
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001421/// hasObjCExceptionAttribute - Return true if this class or any super
1422/// class has the __objc_exception__ attribute.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001423static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor68584ed2009-06-18 16:11:24 +00001424 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidis40b598e2009-06-30 02:34:44 +00001425 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001426 return true;
1427 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor68584ed2009-06-18 16:11:24 +00001428 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001429 return false;
1430}
1431
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001432/* *** CGObjCMac Public Interface *** */
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001433
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001434CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00001435 ObjCTypes(cgm) {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001436 ObjCABI = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001437 EmitImageInfo();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001438}
1439
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +00001440/// GetClass - Return a reference to the class for the given interface
1441/// decl.
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001442llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001443 const ObjCInterfaceDecl *ID) {
1444 return EmitClassRef(Builder, ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001445}
1446
1447/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001448llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1449 bool lval) {
1450 return EmitSelector(Builder, Sel, lval);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001451}
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001452llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001453 *Method) {
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001454 return EmitSelector(Builder, Method->getSelector());
1455}
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001456
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001457llvm::Constant *CGObjCMac::GetEHType(QualType T) {
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00001458 if (T->isObjCIdType() ||
1459 T->isObjCQualifiedIdType()) {
1460 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor01a4cf12011-08-11 20:58:55 +00001461 CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00001462 }
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001463 if (T->isObjCClassType() ||
1464 T->isObjCQualifiedClassType()) {
1465 return CGM.GetAddrOfRTTIDescriptor(
Douglas Gregor01a4cf12011-08-11 20:58:55 +00001466 CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00001467 }
1468 if (T->isObjCObjectPointerType())
1469 return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);
1470
John McCall5a180392010-07-24 00:37:23 +00001471 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
1472 return 0;
1473}
1474
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001475/// Generate a constant CFString object.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001476/*
1477 struct __builtin_CFString {
1478 const int *isa; // point to __CFConstantStringClassReference
1479 int flags;
1480 const char *str;
1481 long length;
1482 };
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001483*/
1484
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001485/// or Generate a constant NSString object.
1486/*
1487 struct __builtin_NSString {
1488 const int *isa; // point to __NSConstantStringClassReference
1489 const char *str;
1490 unsigned int length;
1491 };
1492*/
1493
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001494llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall0d13f6f2010-01-23 02:40:42 +00001495 const StringLiteral *SL) {
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001496 return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
1497 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian4c733072010-10-19 17:19:29 +00001498 CGM.GetAddrOfConstantString(SL));
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001499}
1500
1501/// Generates a message send where the super is the receiver. This is
1502/// a message send to self with special delivery semantics indicating
1503/// which class's method should be called.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001504CodeGen::RValue
1505CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001506 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001507 QualType ResultType,
1508 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001509 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001510 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001511 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001512 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001513 const CodeGen::CallArgList &CallArgs,
1514 const ObjCMethodDecl *Method) {
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001515 // Create and init a super structure; this is a (receiver, class)
1516 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001517 llvm::Value *ObjCSuper =
John McCall604da292011-03-04 08:00:29 +00001518 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001519 llvm::Value *ReceiverAsObject =
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001520 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001521 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001522 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001523
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001524 // If this is a class message the metaclass is passed as the target.
1525 llvm::Value *Target;
1526 if (IsClassMessage) {
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001527 if (isCategoryImpl) {
1528 // Message sent to 'super' in a class method defined in a category
1529 // implementation requires an odd treatment.
1530 // If we are in a class method, we must retrieve the
1531 // _metaclass_ for the current class, pointed at by
1532 // the class's "isa" pointer. The following assumes that
1533 // isa" is the first ivar in a class (which it must be).
1534 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1535 Target = CGF.Builder.CreateStructGEP(Target, 0);
1536 Target = CGF.Builder.CreateLoad(Target);
Mike Stumpb3589f42009-07-30 22:28:39 +00001537 } else {
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001538 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1539 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1540 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1541 Target = Super;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001542 }
Fariborz Jahanian182f2682009-11-14 02:18:31 +00001543 }
1544 else if (isCategoryImpl)
1545 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1546 else {
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00001547 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1548 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1549 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001550 }
Mike Stumpf5408fe2009-05-16 07:57:57 +00001551 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1552 // ObjCTypes types.
Chris Lattner2acc6e32011-07-18 04:24:23 +00001553 llvm::Type *ClassTy =
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001554 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001555 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001556 CGF.Builder.CreateStore(Target,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001557 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall944c8432011-05-14 03:10:52 +00001558 return EmitMessageSend(CGF, Return, ResultType,
1559 EmitSelector(CGF.Builder, Sel),
1560 ObjCSuper, ObjCTypes.SuperPtrCTy,
1561 true, CallArgs, Method, ObjCTypes);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001562}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001563
1564/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001565CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001566 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001567 QualType ResultType,
1568 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001569 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001570 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001571 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001572 const ObjCMethodDecl *Method) {
John McCall944c8432011-05-14 03:10:52 +00001573 return EmitMessageSend(CGF, Return, ResultType,
1574 EmitSelector(CGF.Builder, Sel),
1575 Receiver, CGF.getContext().getObjCIdType(),
1576 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00001577}
1578
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001579CodeGen::RValue
John McCall944c8432011-05-14 03:10:52 +00001580CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1581 ReturnValueSlot Return,
1582 QualType ResultType,
1583 llvm::Value *Sel,
1584 llvm::Value *Arg0,
1585 QualType Arg0Ty,
1586 bool IsSuper,
1587 const CallArgList &CallArgs,
1588 const ObjCMethodDecl *Method,
1589 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001590 CallArgList ActualArgs;
Fariborz Jahaniand019d962009-04-24 21:07:43 +00001591 if (!IsSuper)
Benjamin Kramer578faa82011-09-27 21:06:10 +00001592 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
Eli Friedman04c9a492011-05-02 17:57:46 +00001593 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1594 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
John McCallf85e1932011-06-15 23:02:42 +00001595 ActualArgs.addFrom(CallArgs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001596
Daniel Dunbar541b63b2009-02-02 23:23:47 +00001597 CodeGenTypes &Types = CGM.getTypes();
John McCall04a67a62010-02-05 21:31:56 +00001598 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindola264ba482010-03-30 20:24:48 +00001599 FunctionType::ExtInfo());
Chris Lattner2acc6e32011-07-18 04:24:23 +00001600 llvm::FunctionType *FTy =
Daniel Dunbar67939662009-09-17 04:01:40 +00001601 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001602
Anders Carlsson7e70fb22010-06-21 20:59:55 +00001603 if (Method)
1604 assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1605 CGM.getContext().getCanonicalType(ResultType) &&
1606 "Result type mismatch!");
1607
John McCallcba681a2011-05-14 21:12:11 +00001608 NullReturnState nullReturn;
1609
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001610 llvm::Constant *Fn = NULL;
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001611 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
John McCallcba681a2011-05-14 21:12:11 +00001612 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001613 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001614 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001615 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1616 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1617 : ObjCTypes.getSendFpretFn(IsSuper);
Anders Carlssoneea64802011-10-31 16:27:11 +00001618 } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
1619 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
1620 : ObjCTypes.getSendFp2retFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001621 } else {
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001622 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001623 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001624 }
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001625 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
John McCallcba681a2011-05-14 21:12:11 +00001626 RValue rvalue = CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
1627 return nullReturn.complete(CGF, rvalue, ResultType);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001628}
1629
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001630static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1631 if (FQT.isObjCGCStrong())
1632 return Qualifiers::Strong;
1633
John McCallf85e1932011-06-15 23:02:42 +00001634 if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001635 return Qualifiers::Weak;
1636
1637 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1638 return Qualifiers::Strong;
1639
1640 if (const PointerType *PT = FQT->getAs<PointerType>())
1641 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1642
1643 return Qualifiers::GCNone;
1644}
1645
John McCall6b5a61b2011-02-07 10:33:21 +00001646llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1647 const CGBlockInfo &blockInfo) {
1648 llvm::Constant *nullPtr =
Fariborz Jahanian44034db2010-08-04 18:44:59 +00001649 llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
John McCall6b5a61b2011-02-07 10:33:21 +00001650
Douglas Gregore289d812011-09-13 17:21:33 +00001651 if (CGM.getLangOptions().getGC() == LangOptions::NonGC &&
John McCallf85e1932011-06-15 23:02:42 +00001652 !CGM.getLangOptions().ObjCAutoRefCount)
John McCall6b5a61b2011-02-07 10:33:21 +00001653 return nullPtr;
1654
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001655 bool hasUnion = false;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001656 SkipIvars.clear();
1657 IvarsInfo.clear();
Douglas Gregorbcfd1f52011-09-02 00:18:52 +00001658 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
1659 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001660
Fariborz Jahanian81979822010-09-09 00:21:45 +00001661 // __isa is the first field in block descriptor and must assume by runtime's
1662 // convention that it is GC'able.
1663 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall6b5a61b2011-02-07 10:33:21 +00001664
1665 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1666
1667 // Calculate the basic layout of the block structure.
1668 const llvm::StructLayout *layout =
1669 CGM.getTargetData().getStructLayout(blockInfo.StructureType);
1670
1671 // Ignore the optional 'this' capture: C++ objects are not assumed
1672 // to be GC'ed.
1673
1674 // Walk the captured variables.
1675 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1676 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1677 const VarDecl *variable = ci->getVariable();
1678 QualType type = variable->getType();
1679
1680 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1681
1682 // Ignore constant captures.
1683 if (capture.isConstant()) continue;
1684
1685 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
1686
1687 // __block variables are passed by their descriptor address.
1688 if (ci->isByRef()) {
1689 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanianc5904b42010-09-11 01:27:29 +00001690 continue;
John McCall6b5a61b2011-02-07 10:33:21 +00001691 }
1692
1693 assert(!type->isArrayType() && "array variable should not be caught");
1694 if (const RecordType *record = type->getAs<RecordType>()) {
1695 BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
Fariborz Jahaniane1a48982010-08-05 21:00:25 +00001696 continue;
1697 }
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001698
John McCall6b5a61b2011-02-07 10:33:21 +00001699 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
1700 unsigned fieldSize = CGM.getContext().getTypeSize(type);
1701
1702 if (GCAttr == Qualifiers::Strong)
1703 IvarsInfo.push_back(GC_IVAR(fieldOffset,
1704 fieldSize / WordSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001705 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
John McCall6b5a61b2011-02-07 10:33:21 +00001706 SkipIvars.push_back(GC_IVAR(fieldOffset,
1707 fieldSize / ByteSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001708 }
1709
1710 if (IvarsInfo.empty())
John McCall6b5a61b2011-02-07 10:33:21 +00001711 return nullPtr;
1712
1713 // Sort on byte position; captures might not be allocated in order,
1714 // and unions can do funny things.
1715 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
1716 llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001717
1718 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00001719 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001720 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
1721 printf("\n block variable layout for block: ");
1722 const unsigned char *s = (unsigned char*)BitMap.c_str();
1723 for (unsigned i = 0; i < BitMap.size(); i++)
1724 if (!(s[i] & 0xf0))
1725 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1726 else
1727 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
1728 printf("\n");
1729 }
1730
1731 return C;
Fariborz Jahanian89ecd412010-08-04 16:57:49 +00001732}
1733
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001734llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001735 const ObjCProtocolDecl *PD) {
Daniel Dunbarc67876d2008-09-04 04:33:15 +00001736 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00001737 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc67876d2008-09-04 04:33:15 +00001738 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1739
Owen Anderson3c4972d2009-07-29 18:54:39 +00001740 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001741 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001742}
1743
Fariborz Jahanianda320092009-01-29 19:24:30 +00001744void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stumpf5408fe2009-05-16 07:57:57 +00001745 // FIXME: We shouldn't need this, the protocol decl should contain enough
1746 // information to tell us whether this was a declaration or a definition.
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001747 DefinedProtocols.insert(PD->getIdentifier());
1748
1749 // If we have generated a forward reference to this protocol, emit
1750 // it now. Otherwise do nothing, the protocol objects are lazily
1751 // emitted.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001752 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001753 GetOrEmitProtocol(PD);
1754}
1755
Fariborz Jahanianda320092009-01-29 19:24:30 +00001756llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001757 if (DefinedProtocols.count(PD->getIdentifier()))
1758 return GetOrEmitProtocol(PD);
Douglas Gregorf968d832011-05-27 01:19:52 +00001759
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001760 return GetOrEmitProtocolRef(PD);
1761}
1762
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001763/*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001764// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1765struct _objc_protocol {
1766struct _objc_protocol_extension *isa;
1767char *protocol_name;
1768struct _objc_protocol_list *protocol_list;
1769struct _objc__method_prototype_list *instance_methods;
1770struct _objc__method_prototype_list *class_methods
1771};
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001772
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001773See EmitProtocolExtension().
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001774*/
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001775llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1776 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1777
1778 // Early exit if a defining object has already been generated.
1779 if (Entry && Entry->hasInitializer())
1780 return Entry;
1781
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00001782 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00001783 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00001784 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1785
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001786 // Construct method lists.
1787 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1788 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001789 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001790 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001791 ObjCMethodDecl *MD = *i;
1792 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00001793 if (!C)
1794 return GetOrEmitProtocolRef(PD);
1795
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001796 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1797 OptInstanceMethods.push_back(C);
1798 } else {
1799 InstanceMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001800 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001801 }
1802
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001803 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001804 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001805 ObjCMethodDecl *MD = *i;
1806 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00001807 if (!C)
1808 return GetOrEmitProtocolRef(PD);
1809
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001810 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1811 OptClassMethods.push_back(C);
1812 } else {
1813 ClassMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001814 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001815 }
1816
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00001817 llvm::Constant *Values[] = {
1818 EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods),
1819 GetClassName(PD->getIdentifier()),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001820 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardbc933702008-08-21 21:57:41 +00001821 PD->protocol_begin(),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00001822 PD->protocol_end()),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001823 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001824 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00001825 InstanceMethods),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001826 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001827 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00001828 ClassMethods)
1829 };
Owen Anderson08e25242009-07-27 22:29:56 +00001830 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001831 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001832
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001833 if (Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001834 // Already created, fix the linkage and update the initializer.
1835 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001836 Entry->setInitializer(Init);
1837 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001838 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00001839 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001840 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001841 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001842 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001843 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001844 // FIXME: Is this necessary? Why only for protocol?
1845 Entry->setAlignment(4);
1846 }
Chris Lattnerad64e022009-07-17 23:57:13 +00001847 CGM.AddUsedGlobal(Entry);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001848
1849 return Entry;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001850}
1851
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001852llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001853 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1854
1855 if (!Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001856 // We use the initializer as a marker of whether this is a forward
1857 // reference or not. At module finalization we add the empty
1858 // contents for protocols which were referenced but never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001859 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00001860 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001861 llvm::GlobalValue::ExternalLinkage,
1862 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001863 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001864 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001865 // FIXME: Is this necessary? Why only for protocol?
1866 Entry->setAlignment(4);
1867 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001868
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001869 return Entry;
1870}
1871
1872/*
1873 struct _objc_protocol_extension {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001874 uint32_t size;
1875 struct objc_method_description_list *optional_instance_methods;
1876 struct objc_method_description_list *optional_class_methods;
1877 struct objc_property_list *instance_properties;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001878 };
1879*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001880llvm::Constant *
1881CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1882 const ConstantVector &OptInstanceMethods,
1883 const ConstantVector &OptClassMethods) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001884 uint64_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00001885 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00001886 llvm::Constant *Values[] = {
1887 llvm::ConstantInt::get(ObjCTypes.IntTy, Size),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001888 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001889 + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001890 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00001891 OptInstanceMethods),
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001892 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001893 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00001894 OptClassMethods),
1895 EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(), 0, PD,
1896 ObjCTypes)
1897 };
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001898
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001899 // Return null if no extension bits are used.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001900 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001901 Values[3]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001902 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001903
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001904 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00001905 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001906
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001907 // No special section, but goes in llvm.used
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001908 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001909 Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001910 0, 0, true);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001911}
1912
1913/*
1914 struct objc_protocol_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001915 struct objc_protocol_list *next;
1916 long count;
1917 Protocol *list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001918 };
1919*/
Daniel Dunbardbc933702008-08-21 21:57:41 +00001920llvm::Constant *
Chris Lattner5f9e2722011-07-23 10:55:15 +00001921CGObjCMac::EmitProtocolList(Twine Name,
Daniel Dunbardbc933702008-08-21 21:57:41 +00001922 ObjCProtocolDecl::protocol_iterator begin,
1923 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001924 std::vector<llvm::Constant*> ProtocolRefs;
1925
Daniel Dunbardbc933702008-08-21 21:57:41 +00001926 for (; begin != end; ++begin)
1927 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001928
1929 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001930 if (ProtocolRefs.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001931 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001932
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001933 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00001934 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001935
Chris Lattnerc5cbb902011-06-20 04:01:35 +00001936 llvm::Constant *Values[3];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001937 // This field is only used by the runtime.
Owen Andersonc9c88b42009-07-31 20:28:54 +00001938 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001939 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001940 ProtocolRefs.size() - 1);
1941 Values[2] =
1942 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1943 ProtocolRefs.size()),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001944 ProtocolRefs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001945
Chris Lattnerc5cbb902011-06-20 04:01:35 +00001946 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001947 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001948 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00001949 4, false);
Owen Anderson3c4972d2009-07-29 18:54:39 +00001950 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001951}
1952
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001953void CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
1954 std::vector<llvm::Constant*> &Properties,
1955 const Decl *Container,
1956 const ObjCProtocolDecl *PROTO,
1957 const ObjCCommonTypesHelper &ObjCTypes) {
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001958 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
1959 E = PROTO->protocol_end(); P != E; ++P)
1960 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
1961 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
1962 E = PROTO->prop_end(); I != E; ++I) {
1963 const ObjCPropertyDecl *PD = *I;
1964 if (!PropertySet.insert(PD->getIdentifier()))
1965 continue;
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00001966 llvm::Constant *Prop[] = {
1967 GetPropertyName(PD->getIdentifier()),
1968 GetPropertyTypeString(PD, Container)
1969 };
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001970 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
1971 }
1972}
1973
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001974/*
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001975 struct _objc_property {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001976 const char * const name;
1977 const char * const attributes;
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001978 };
1979
1980 struct _objc_property_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001981 uint32_t entsize; // sizeof (struct _objc_property)
1982 uint32_t prop_count;
1983 struct _objc_property[prop_count];
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001984 };
1985*/
Chris Lattner5f9e2722011-07-23 10:55:15 +00001986llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001987 const Decl *Container,
1988 const ObjCContainerDecl *OCD,
1989 const ObjCCommonTypesHelper &ObjCTypes) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00001990 std::vector<llvm::Constant*> Properties;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001991 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001992 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1993 E = OCD->prop_end(); I != E; ++I) {
Steve Naroff93983f82009-01-11 12:47:58 +00001994 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001995 PropertySet.insert(PD->getIdentifier());
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00001996 llvm::Constant *Prop[] = {
1997 GetPropertyName(PD->getIdentifier()),
1998 GetPropertyTypeString(PD, Container)
1999 };
Owen Anderson08e25242009-07-27 22:29:56 +00002000 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002001 Prop));
2002 }
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00002003 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek53b94412010-09-01 01:21:15 +00002004 for (ObjCInterfaceDecl::all_protocol_iterator
2005 P = OID->all_referenced_protocol_begin(),
2006 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00002007 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2008 ObjCTypes);
2009 }
2010 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
2011 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
2012 E = CD->protocol_end(); P != E; ++P)
2013 PushProtocolProperties(PropertySet, Properties, Container, (*P),
2014 ObjCTypes);
2015 }
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002016
2017 // Return null for empty list.
2018 if (Properties.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002019 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002020
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002021 unsigned PropertySize =
Duncan Sands9408c452009-05-09 07:08:47 +00002022 CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002023 llvm::Constant *Values[3];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002024 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
2025 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002026 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002027 Properties.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002028 Values[2] = llvm::ConstantArray::get(AT, Properties);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002029 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002030
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002031 llvm::GlobalVariable *GV =
2032 CreateMetadataVar(Name, Init,
2033 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002034 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002035 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002036 true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002037 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002038}
2039
2040/*
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002041 struct objc_method_description_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002042 int count;
2043 struct objc_method_description list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002044 };
2045*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002046llvm::Constant *
2047CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002048 llvm::Constant *Desc[] = {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002049 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002050 ObjCTypes.SelectorPtrTy),
2051 GetMethodVarType(MD)
2052 };
Douglas Gregorf968d832011-05-27 01:19:52 +00002053 if (!Desc[1])
2054 return 0;
2055
Owen Anderson08e25242009-07-27 22:29:56 +00002056 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002057 Desc);
2058}
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002059
Chris Lattner5f9e2722011-07-23 10:55:15 +00002060llvm::Constant *CGObjCMac::EmitMethodDescList(Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002061 const char *Section,
2062 const ConstantVector &Methods) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002063 // Return null for empty list.
2064 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002065 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002066
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002067 llvm::Constant *Values[2];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002068 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002069 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002070 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002071 Values[1] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002072 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002073
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002074 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002075 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002076 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002077}
2078
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002079/*
2080 struct _objc_category {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002081 char *category_name;
2082 char *class_name;
2083 struct _objc_method_list *instance_methods;
2084 struct _objc_method_list *class_methods;
2085 struct _objc_protocol_list *protocols;
2086 uint32_t size; // <rdar://4585769>
2087 struct _objc_property_list *instance_properties;
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002088 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002089*/
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00002090void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Duncan Sands9408c452009-05-09 07:08:47 +00002091 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002092
Mike Stumpf5408fe2009-05-16 07:57:57 +00002093 // FIXME: This is poor design, the OCD should have a pointer to the category
2094 // decl. Additionally, note that Category can be null for the @implementation
2095 // w/o an @interface case. Sema should just create one for us as it does for
2096 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002097 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002098 const ObjCCategoryDecl *Category =
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002099 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002100
2101 llvm::SmallString<256> ExtName;
2102 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2103 << OCD->getName();
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002104
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002105 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002106 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002107 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002108 // Instance methods should always be defined.
2109 InstanceMethods.push_back(GetMethodConstant(*i));
2110 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002111 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002112 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002113 // Class methods should always be defined.
2114 ClassMethods.push_back(GetMethodConstant(*i));
2115 }
2116
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002117 llvm::Constant *Values[7];
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002118 Values[0] = GetClassName(OCD->getIdentifier());
2119 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahanian679cd7f2009-04-29 20:40:05 +00002120 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002121 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002122 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002123 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002124 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002125 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002126 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002127 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002128 ClassMethods);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002129 if (Category) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002130 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002131 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002132 Category->protocol_begin(),
2133 Category->protocol_end());
2134 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002135 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002136 }
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002137 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002138
2139 // If there is no category @interface then there can be no properties.
2140 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002141 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002142 OCD, Category, ObjCTypes);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002143 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002144 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002145 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002146
Owen Anderson08e25242009-07-27 22:29:56 +00002147 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002148 Values);
2149
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002150 llvm::GlobalVariable *GV =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002151 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002152 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002153 4, true);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002154 DefinedCategories.push_back(GV);
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00002155 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00002156 // method definition entries must be clear for next implementation.
2157 MethodDefinitions.clear();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002158}
2159
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002160// FIXME: Get from somewhere?
2161enum ClassFlags {
2162 eClassFlags_Factory = 0x00001,
2163 eClassFlags_Meta = 0x00002,
2164 // <rdr://5142207>
2165 eClassFlags_HasCXXStructors = 0x02000,
2166 eClassFlags_Hidden = 0x20000,
2167 eClassFlags_ABI2_Hidden = 0x00010,
2168 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
2169};
2170
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002171/*
2172 struct _objc_class {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002173 Class isa;
2174 Class super_class;
2175 const char *name;
2176 long version;
2177 long info;
2178 long instance_size;
2179 struct _objc_ivar_list *ivars;
2180 struct _objc_method_list *methods;
2181 struct _objc_cache *cache;
2182 struct _objc_protocol_list *protocols;
2183 // Objective-C 1.0 extensions (<rdr://4585769>)
2184 const char *ivar_layout;
2185 struct _objc_class_ext *ext;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002186 };
2187
2188 See EmitClassExtension();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002189*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002190void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002191 DefinedSymbols.insert(ID->getIdentifier());
2192
Chris Lattner8ec03f52008-11-24 03:54:41 +00002193 std::string ClassName = ID->getNameAsString();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002194 // FIXME: Gross
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002195 ObjCInterfaceDecl *Interface =
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002196 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002197 llvm::Constant *Protocols =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002198 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00002199 Interface->all_referenced_protocol_begin(),
2200 Interface->all_referenced_protocol_end());
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002201 unsigned Flags = eClassFlags_Factory;
John McCallf85e1932011-06-15 23:02:42 +00002202 if (ID->hasCXXStructors())
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00002203 Flags |= eClassFlags_HasCXXStructors;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002204 unsigned Size =
Ken Dyck5f022d82011-02-09 01:59:34 +00002205 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002206
2207 // FIXME: Set CXX-structors flag.
John McCall1fb0caa2010-10-22 21:05:15 +00002208 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002209 Flags |= eClassFlags_Hidden;
2210
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002211 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002212 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002213 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002214 // Instance methods should always be defined.
2215 InstanceMethods.push_back(GetMethodConstant(*i));
2216 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002217 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002218 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002219 // Class methods should always be defined.
2220 ClassMethods.push_back(GetMethodConstant(*i));
2221 }
2222
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002223 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002224 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002225 ObjCPropertyImplDecl *PID = *i;
2226
2227 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2228 ObjCPropertyDecl *PD = PID->getPropertyDecl();
2229
2230 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2231 if (llvm::Constant *C = GetMethodConstant(MD))
2232 InstanceMethods.push_back(C);
2233 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2234 if (llvm::Constant *C = GetMethodConstant(MD))
2235 InstanceMethods.push_back(C);
2236 }
2237 }
2238
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002239 llvm::Constant *Values[12];
Daniel Dunbar5384b092009-05-03 08:56:52 +00002240 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002241 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002242 // Record a reference to the super class.
2243 LazySymbols.insert(Super->getIdentifier());
2244
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002245 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002246 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002247 ObjCTypes.ClassPtrTy);
2248 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002249 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002250 }
2251 Values[ 2] = GetClassName(ID->getIdentifier());
2252 // Version is always 0.
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002253 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2254 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2255 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002256 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002257 Values[ 7] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002258 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002259 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002260 InstanceMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002261 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002262 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002263 Values[ 9] = Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002264 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002265 Values[11] = EmitClassExtension(ID);
Owen Anderson08e25242009-07-27 22:29:56 +00002266 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002267 Values);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00002268 std::string Name("\01L_OBJC_CLASS_");
2269 Name += ClassName;
2270 const char *Section = "__OBJC,__class,regular,no_dead_strip";
2271 // Check for a forward reference.
2272 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2273 if (GV) {
2274 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2275 "Forward metaclass reference has incorrect type.");
2276 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2277 GV->setInitializer(Init);
2278 GV->setSection(Section);
2279 GV->setAlignment(4);
2280 CGM.AddUsedGlobal(GV);
2281 }
2282 else
2283 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002284 DefinedClasses.push_back(GV);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00002285 // method definition entries must be clear for next implementation.
2286 MethodDefinitions.clear();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002287}
2288
2289llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2290 llvm::Constant *Protocols,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002291 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002292 unsigned Flags = eClassFlags_Meta;
Duncan Sands9408c452009-05-09 07:08:47 +00002293 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002294
John McCall1fb0caa2010-10-22 21:05:15 +00002295 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002296 Flags |= eClassFlags_Hidden;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002297
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002298 llvm::Constant *Values[12];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002299 // The isa for the metaclass is the root of the hierarchy.
2300 const ObjCInterfaceDecl *Root = ID->getClassInterface();
2301 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2302 Root = Super;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002303 Values[ 0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002304 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002305 ObjCTypes.ClassPtrTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002306 // The super class for the metaclass is emitted as the name of the
2307 // super class. The runtime fixes this up to point to the
2308 // *metaclass* for the super class.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002309 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002310 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002311 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002312 ObjCTypes.ClassPtrTy);
2313 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002314 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002315 }
2316 Values[ 2] = GetClassName(ID->getIdentifier());
2317 // Version is always 0.
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002318 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2319 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2320 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002321 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002322 Values[ 7] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00002323 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002324 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002325 Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002326 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002327 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002328 Values[ 9] = Protocols;
2329 // ivar_layout for metaclass is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002330 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002331 // The class extension is always unused for metaclasses.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002332 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00002333 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002334 Values);
2335
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002336 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner8ec03f52008-11-24 03:54:41 +00002337 Name += ID->getNameAsCString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002338
2339 // Check for a forward reference.
2340 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2341 if (GV) {
2342 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2343 "Forward metaclass reference has incorrect type.");
2344 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2345 GV->setInitializer(Init);
2346 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00002347 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002348 llvm::GlobalValue::InternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00002349 Init, Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002350 }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002351 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbar58a29122009-03-09 22:18:41 +00002352 GV->setAlignment(4);
Chris Lattnerad64e022009-07-17 23:57:13 +00002353 CGM.AddUsedGlobal(GV);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002354
2355 return GV;
2356}
2357
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002358llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00002359 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002360
Mike Stumpf5408fe2009-05-16 07:57:57 +00002361 // FIXME: Should we look these up somewhere other than the module. Its a bit
2362 // silly since we only generate these while processing an implementation, so
2363 // exactly one pointer would work if know when we entered/exitted an
2364 // implementation block.
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002365
2366 // Check for an existing forward reference.
Fariborz Jahanianb0d27942009-01-07 20:11:22 +00002367 // Previously, metaclass with internal linkage may have been defined.
2368 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002369 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2370 true)) {
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002371 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2372 "Forward metaclass reference has incorrect type.");
2373 return GV;
2374 } else {
2375 // Generate as an external reference to keep a consistent
2376 // module. This will be patched up when we emit the metaclass.
Owen Anderson1c431b32009-07-08 19:05:04 +00002377 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002378 llvm::GlobalValue::ExternalLinkage,
2379 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00002380 Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002381 }
2382}
2383
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00002384llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2385 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2386
2387 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2388 true)) {
2389 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2390 "Forward class metadata reference has incorrect type.");
2391 return GV;
2392 } else {
2393 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2394 llvm::GlobalValue::ExternalLinkage,
2395 0,
2396 Name);
2397 }
2398}
2399
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002400/*
2401 struct objc_class_ext {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002402 uint32_t size;
2403 const char *weak_ivar_layout;
2404 struct _objc_property_list *properties;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002405 };
2406*/
2407llvm::Constant *
2408CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002409 uint64_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00002410 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002411
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002412 llvm::Constant *Values[3];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002413 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanianc71303d2009-04-22 23:00:43 +00002414 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002415 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002416 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002417
2418 // Return null if no extension bits are used.
2419 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002420 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002421
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002422 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00002423 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002424 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002425 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002426 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002427}
2428
2429/*
2430 struct objc_ivar {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002431 char *ivar_name;
2432 char *ivar_type;
2433 int ivar_offset;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002434 };
2435
2436 struct objc_ivar_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002437 int ivar_count;
2438 struct objc_ivar list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002439 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002440*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002441llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002442 bool ForClass) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002443 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002444
2445 // When emitting the root class GCC emits ivar entries for the
2446 // actual class structure. It is not clear if we need to follow this
2447 // behavior; for now lets try and get away with not doing it. If so,
2448 // the cleanest solution would be to make up an ObjCInterfaceDecl
2449 // for the class.
2450 if (ForClass)
Owen Andersonc9c88b42009-07-31 20:28:54 +00002451 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002452
Jordy Rosedb8264e2011-07-22 02:08:32 +00002453 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002454
Jordy Rosedb8264e2011-07-22 02:08:32 +00002455 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00002456 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00002457 // Ignore unnamed bit-fields.
2458 if (!IVD->getDeclName())
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002459 continue;
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002460 llvm::Constant *Ivar[] = {
2461 GetMethodVarName(IVD->getIdentifier()),
2462 GetMethodVarType(IVD),
2463 llvm::ConstantInt::get(ObjCTypes.IntTy,
2464 ComputeIvarBaseOffset(CGM, OID, IVD))
2465 };
Owen Anderson08e25242009-07-27 22:29:56 +00002466 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002467 }
2468
2469 // Return null for empty list.
2470 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002471 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002472
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002473 llvm::Constant *Values[2];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002474 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00002475 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002476 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002477 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002478 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002479
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002480 llvm::GlobalVariable *GV;
2481 if (ForClass)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002482 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002483 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002484 4, true);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002485 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002486 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002487 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002488 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002489 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002490}
2491
2492/*
2493 struct objc_method {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002494 SEL method_name;
2495 char *method_types;
2496 void *method;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002497 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002498
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002499 struct objc_method_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002500 struct objc_method_list *obsolete;
2501 int count;
2502 struct objc_method methods_list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002503 };
2504*/
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002505
2506/// GetMethodConstant - Return a struct objc_method constant for the
2507/// given method if it has been defined. The result is null if the
2508/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002509llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00002510 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002511 if (!Fn)
2512 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002513
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002514 llvm::Constant *Method[] = {
Owen Anderson3c4972d2009-07-29 18:54:39 +00002515 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00002516 ObjCTypes.SelectorPtrTy),
2517 GetMethodVarType(MD),
2518 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
2519 };
Owen Anderson08e25242009-07-27 22:29:56 +00002520 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002521}
2522
Chris Lattner5f9e2722011-07-23 10:55:15 +00002523llvm::Constant *CGObjCMac::EmitMethodList(Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002524 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002525 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002526 // Return null for empty list.
2527 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002528 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002529
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002530 llvm::Constant *Values[3];
Owen Andersonc9c88b42009-07-31 20:28:54 +00002531 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002532 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00002533 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002534 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002535 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002536 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002537
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002538 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00002539 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListPtrTy);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002540}
2541
Fariborz Jahanian493dab72009-01-26 21:38:32 +00002542llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002543 const ObjCContainerDecl *CD) {
Daniel Dunbarc575ce72009-10-19 01:21:19 +00002544 llvm::SmallString<256> Name;
Fariborz Jahanian679a5022009-01-10 21:06:09 +00002545 GetNameForMethod(OMD, CD, Name);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002546
Daniel Dunbar541b63b2009-02-02 23:23:47 +00002547 CodeGenTypes &Types = CGM.getTypes();
Chris Lattner2acc6e32011-07-18 04:24:23 +00002548 llvm::FunctionType *MethodTy =
Daniel Dunbar541b63b2009-02-02 23:23:47 +00002549 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002550 llvm::Function *Method =
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00002551 llvm::Function::Create(MethodTy,
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002552 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00002553 Name.str(),
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002554 &CGM.getModule());
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002555 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002556
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002557 return Method;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002558}
2559
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002560llvm::GlobalVariable *
Chris Lattner5f9e2722011-07-23 10:55:15 +00002561CGObjCCommonMac::CreateMetadataVar(Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002562 llvm::Constant *Init,
2563 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +00002564 unsigned Align,
2565 bool AddToUsed) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00002566 llvm::Type *Ty = Init->getType();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002567 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00002568 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerad64e022009-07-17 23:57:13 +00002569 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002570 if (Section)
2571 GV->setSection(Section);
Daniel Dunbar35bd7632009-03-09 20:50:13 +00002572 if (Align)
2573 GV->setAlignment(Align);
2574 if (AddToUsed)
Chris Lattnerad64e022009-07-17 23:57:13 +00002575 CGM.AddUsedGlobal(GV);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002576 return GV;
2577}
2578
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002579llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002580 // Abuse this interface function as a place to finalize.
2581 FinishModule();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002582 return NULL;
2583}
2584
Chris Lattner74391b42009-03-22 21:03:39 +00002585llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002586 return ObjCTypes.getGetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00002587}
2588
Chris Lattner74391b42009-03-22 21:03:39 +00002589llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002590 return ObjCTypes.getSetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00002591}
2592
David Chisnall8fac25d2010-12-26 22:13:16 +00002593llvm::Constant *CGObjCMac::GetGetStructFunction() {
2594 return ObjCTypes.getCopyStructFn();
2595}
2596llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00002597 return ObjCTypes.getCopyStructFn();
2598}
2599
Chris Lattner74391b42009-03-22 21:03:39 +00002600llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002601 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson2abd89c2008-08-31 04:05:03 +00002602}
2603
John McCallf1549f62010-07-06 01:34:17 +00002604void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
2605 return EmitTryOrSynchronizedStmt(CGF, S);
2606}
2607
2608void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
2609 const ObjCAtSynchronizedStmt &S) {
2610 return EmitTryOrSynchronizedStmt(CGF, S);
2611}
2612
John McCallcc505292010-07-21 06:59:36 +00002613namespace {
John McCall1f0fca52010-07-21 07:22:38 +00002614 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCallcc505292010-07-21 06:59:36 +00002615 const Stmt &S;
John McCall0b251722010-08-04 05:59:32 +00002616 llvm::Value *SyncArgSlot;
John McCallcc505292010-07-21 06:59:36 +00002617 llvm::Value *CallTryExitVar;
2618 llvm::Value *ExceptionData;
2619 ObjCTypesHelper &ObjCTypes;
2620 PerformFragileFinally(const Stmt *S,
John McCall0b251722010-08-04 05:59:32 +00002621 llvm::Value *SyncArgSlot,
John McCallcc505292010-07-21 06:59:36 +00002622 llvm::Value *CallTryExitVar,
2623 llvm::Value *ExceptionData,
2624 ObjCTypesHelper *ObjCTypes)
John McCall0b251722010-08-04 05:59:32 +00002625 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCallcc505292010-07-21 06:59:36 +00002626 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
2627
John McCallad346f42011-07-12 20:27:29 +00002628 void Emit(CodeGenFunction &CGF, Flags flags) {
John McCallcc505292010-07-21 06:59:36 +00002629 // Check whether we need to call objc_exception_try_exit.
2630 // In optimized code, this branch will always be folded.
2631 llvm::BasicBlock *FinallyCallExit =
2632 CGF.createBasicBlock("finally.call_exit");
2633 llvm::BasicBlock *FinallyNoCallExit =
2634 CGF.createBasicBlock("finally.no_call_exit");
2635 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
2636 FinallyCallExit, FinallyNoCallExit);
2637
2638 CGF.EmitBlock(FinallyCallExit);
2639 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
2640 ->setDoesNotThrow();
2641
2642 CGF.EmitBlock(FinallyNoCallExit);
2643
2644 if (isa<ObjCAtTryStmt>(S)) {
2645 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCalld96a8e72010-08-11 00:16:14 +00002646 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
2647 // Save the current cleanup destination in case there's
2648 // control flow inside the finally statement.
2649 llvm::Value *CurCleanupDest =
2650 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
2651
John McCallcc505292010-07-21 06:59:36 +00002652 CGF.EmitStmt(FinallyStmt->getFinallyBody());
2653
John McCalld96a8e72010-08-11 00:16:14 +00002654 if (CGF.HaveInsertPoint()) {
2655 CGF.Builder.CreateStore(CurCleanupDest,
2656 CGF.getNormalCleanupDestSlot());
2657 } else {
2658 // Currently, the end of the cleanup must always exist.
2659 CGF.EnsureInsertPoint();
2660 }
2661 }
John McCallcc505292010-07-21 06:59:36 +00002662 } else {
2663 // Emit objc_sync_exit(expr); as finally's sole statement for
2664 // @synchronized.
John McCall0b251722010-08-04 05:59:32 +00002665 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCallcc505292010-07-21 06:59:36 +00002666 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2667 ->setDoesNotThrow();
2668 }
2669 }
2670 };
John McCall87bb5822010-07-31 23:20:56 +00002671
2672 class FragileHazards {
2673 CodeGenFunction &CGF;
Chris Lattner5f9e2722011-07-23 10:55:15 +00002674 SmallVector<llvm::Value*, 20> Locals;
John McCall87bb5822010-07-31 23:20:56 +00002675 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
2676
2677 llvm::InlineAsm *ReadHazard;
2678 llvm::InlineAsm *WriteHazard;
2679
2680 llvm::FunctionType *GetAsmFnType();
2681
2682 void collectLocals();
2683 void emitReadHazard(CGBuilderTy &Builder);
2684
2685 public:
2686 FragileHazards(CodeGenFunction &CGF);
John McCall0b251722010-08-04 05:59:32 +00002687
John McCall87bb5822010-07-31 23:20:56 +00002688 void emitWriteHazard();
John McCall0b251722010-08-04 05:59:32 +00002689 void emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00002690 };
2691}
2692
2693/// Create the fragile-ABI read and write hazards based on the current
2694/// state of the function, which is presumed to be immediately prior
2695/// to a @try block. These hazards are used to maintain correct
2696/// semantics in the face of optimization and the fragile ABI's
2697/// cavalier use of setjmp/longjmp.
2698FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
2699 collectLocals();
2700
2701 if (Locals.empty()) return;
2702
2703 // Collect all the blocks in the function.
2704 for (llvm::Function::iterator
2705 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
2706 BlocksBeforeTry.insert(&*I);
2707
2708 llvm::FunctionType *AsmFnTy = GetAsmFnType();
2709
2710 // Create a read hazard for the allocas. This inhibits dead-store
2711 // optimizations and forces the values to memory. This hazard is
2712 // inserted before any 'throwing' calls in the protected scope to
2713 // reflect the possibility that the variables might be read from the
2714 // catch block if the call throws.
2715 {
2716 std::string Constraint;
2717 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2718 if (I) Constraint += ',';
2719 Constraint += "*m";
2720 }
2721
2722 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2723 }
2724
2725 // Create a write hazard for the allocas. This inhibits folding
2726 // loads across the hazard. This hazard is inserted at the
2727 // beginning of the catch path to reflect the possibility that the
2728 // variables might have been written within the protected scope.
2729 {
2730 std::string Constraint;
2731 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2732 if (I) Constraint += ',';
2733 Constraint += "=*m";
2734 }
2735
2736 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2737 }
2738}
2739
2740/// Emit a write hazard at the current location.
2741void FragileHazards::emitWriteHazard() {
2742 if (Locals.empty()) return;
2743
Jay Foad4c7d9f12011-07-15 08:37:34 +00002744 CGF.Builder.CreateCall(WriteHazard, Locals)->setDoesNotThrow();
John McCall87bb5822010-07-31 23:20:56 +00002745}
2746
John McCall87bb5822010-07-31 23:20:56 +00002747void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
2748 assert(!Locals.empty());
Jay Foad4c7d9f12011-07-15 08:37:34 +00002749 Builder.CreateCall(ReadHazard, Locals)->setDoesNotThrow();
John McCall87bb5822010-07-31 23:20:56 +00002750}
2751
2752/// Emit read hazards in all the protected blocks, i.e. all the blocks
2753/// which have been inserted since the beginning of the try.
John McCall0b251722010-08-04 05:59:32 +00002754void FragileHazards::emitHazardsInNewBlocks() {
John McCall87bb5822010-07-31 23:20:56 +00002755 if (Locals.empty()) return;
2756
2757 CGBuilderTy Builder(CGF.getLLVMContext());
2758
2759 // Iterate through all blocks, skipping those prior to the try.
2760 for (llvm::Function::iterator
2761 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
2762 llvm::BasicBlock &BB = *FI;
2763 if (BlocksBeforeTry.count(&BB)) continue;
2764
2765 // Walk through all the calls in the block.
2766 for (llvm::BasicBlock::iterator
2767 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
2768 llvm::Instruction &I = *BI;
2769
2770 // Ignore instructions that aren't non-intrinsic calls.
2771 // These are the only calls that can possibly call longjmp.
2772 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
2773 if (isa<llvm::IntrinsicInst>(I))
2774 continue;
2775
2776 // Ignore call sites marked nounwind. This may be questionable,
2777 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
2778 llvm::CallSite CS(&I);
2779 if (CS.doesNotThrow()) continue;
2780
John McCall0b251722010-08-04 05:59:32 +00002781 // Insert a read hazard before the call. This will ensure that
2782 // any writes to the locals are performed before making the
2783 // call. If the call throws, then this is sufficient to
2784 // guarantee correctness as long as it doesn't also write to any
2785 // locals.
John McCall87bb5822010-07-31 23:20:56 +00002786 Builder.SetInsertPoint(&BB, BI);
2787 emitReadHazard(Builder);
2788 }
2789 }
2790}
2791
2792static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
2793 if (V) S.insert(V);
2794}
2795
2796void FragileHazards::collectLocals() {
2797 // Compute a set of allocas to ignore.
2798 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
2799 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
2800 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
John McCall87bb5822010-07-31 23:20:56 +00002801
2802 // Collect all the allocas currently in the function. This is
2803 // probably way too aggressive.
2804 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
2805 for (llvm::BasicBlock::iterator
2806 I = Entry.begin(), E = Entry.end(); I != E; ++I)
2807 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
2808 Locals.push_back(&*I);
2809}
2810
2811llvm::FunctionType *FragileHazards::GetAsmFnType() {
Chris Lattner5f9e2722011-07-23 10:55:15 +00002812 SmallVector<llvm::Type *, 16> tys(Locals.size());
John McCall0774cb82011-05-15 01:53:33 +00002813 for (unsigned i = 0, e = Locals.size(); i != e; ++i)
2814 tys[i] = Locals[i]->getType();
2815 return llvm::FunctionType::get(CGF.VoidTy, tys, false);
John McCallcc505292010-07-21 06:59:36 +00002816}
2817
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002818/*
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002819
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002820 Objective-C setjmp-longjmp (sjlj) Exception Handling
2821 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002822
John McCallf1549f62010-07-06 01:34:17 +00002823 A catch buffer is a setjmp buffer plus:
2824 - a pointer to the exception that was caught
2825 - a pointer to the previous exception data buffer
2826 - two pointers of reserved storage
2827 Therefore catch buffers form a stack, with a pointer to the top
2828 of the stack kept in thread-local storage.
2829
2830 objc_exception_try_enter pushes a catch buffer onto the EH stack.
2831 objc_exception_try_exit pops the given catch buffer, which is
2832 required to be the top of the EH stack.
2833 objc_exception_throw pops the top of the EH stack, writes the
2834 thrown exception into the appropriate field, and longjmps
2835 to the setjmp buffer. It crashes the process (with a printf
2836 and an abort()) if there are no catch buffers on the stack.
2837 objc_exception_extract just reads the exception pointer out of the
2838 catch buffer.
2839
2840 There's no reason an implementation couldn't use a light-weight
2841 setjmp here --- something like __builtin_setjmp, but API-compatible
2842 with the heavyweight setjmp. This will be more important if we ever
2843 want to implement correct ObjC/C++ exception interactions for the
2844 fragile ABI.
2845
2846 Note that for this use of setjmp/longjmp to be correct, we may need
2847 to mark some local variables volatile: if a non-volatile local
2848 variable is modified between the setjmp and the longjmp, it has
2849 indeterminate value. For the purposes of LLVM IR, it may be
2850 sufficient to make loads and stores within the @try (to variables
2851 declared outside the @try) volatile. This is necessary for
2852 optimized correctness, but is not currently being done; this is
2853 being tracked as rdar://problem/8160285
2854
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002855 The basic framework for a @try-catch-finally is as follows:
2856 {
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002857 objc_exception_data d;
2858 id _rethrow = null;
Anders Carlsson190d00e2009-02-07 21:26:04 +00002859 bool _call_try_exit = true;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002860
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002861 objc_exception_try_enter(&d);
2862 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002863 ... try body ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002864 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002865 // exception path
2866 id _caught = objc_exception_extract(&d);
2867
2868 // enter new try scope for handlers
2869 if (!setjmp(d.jmp_buf)) {
2870 ... match exception and execute catch blocks ...
2871
2872 // fell off end, rethrow.
2873 _rethrow = _caught;
2874 ... jump-through-finally to finally_rethrow ...
2875 } else {
2876 // exception in catch block
2877 _rethrow = objc_exception_extract(&d);
2878 _call_try_exit = false;
2879 ... jump-through-finally to finally_rethrow ...
2880 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002881 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00002882 ... jump-through-finally to finally_end ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002883
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002884 finally:
Anders Carlsson190d00e2009-02-07 21:26:04 +00002885 if (_call_try_exit)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002886 objc_exception_try_exit(&d);
Anders Carlsson190d00e2009-02-07 21:26:04 +00002887
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002888 ... finally block ....
Daniel Dunbar898d5082008-09-30 01:06:03 +00002889 ... dispatch to finally destination ...
2890
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002891 finally_rethrow:
Daniel Dunbar898d5082008-09-30 01:06:03 +00002892 objc_exception_throw(_rethrow);
2893
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002894 finally_end:
2895 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002896
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002897 This framework differs slightly from the one gcc uses, in that gcc
2898 uses _rethrow to determine if objc_exception_try_exit should be called
2899 and if the object should be rethrown. This breaks in the face of
2900 throwing nil and introduces unnecessary branches.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002901
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002902 We specialize this framework for a few particular circumstances:
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002903
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002904 - If there are no catch blocks, then we avoid emitting the second
2905 exception handling context.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002906
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002907 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2908 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002909
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002910 - FIXME: If there is no @finally block we can do a few more
2911 simplifications.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002912
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002913 Rethrows and Jumps-Through-Finally
2914 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002915
John McCallf1549f62010-07-06 01:34:17 +00002916 '@throw;' is supported by pushing the currently-caught exception
2917 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002918
John McCallf1549f62010-07-06 01:34:17 +00002919 Branches through the @finally block are handled with an ordinary
2920 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
2921 exceptions are not compatible with C++ exceptions, and this is
2922 hardly the only place where this will go wrong.
Daniel Dunbar898d5082008-09-30 01:06:03 +00002923
John McCallf1549f62010-07-06 01:34:17 +00002924 @synchronized(expr) { stmt; } is emitted as if it were:
2925 id synch_value = expr;
2926 objc_sync_enter(synch_value);
2927 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002928*/
2929
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00002930void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2931 const Stmt &S) {
2932 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallf1549f62010-07-06 01:34:17 +00002933
2934 // A destination for the fall-through edges of the catch handlers to
2935 // jump to.
2936 CodeGenFunction::JumpDest FinallyEnd =
2937 CGF.getJumpDestInCurrentScope("finally.end");
2938
2939 // A destination for the rethrow edge of the catch handlers to jump
2940 // to.
2941 CodeGenFunction::JumpDest FinallyRethrow =
2942 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002943
Daniel Dunbar1c566672009-02-24 01:43:46 +00002944 // For @synchronized, call objc_sync_enter(sync.expr). The
2945 // evaluation of the expression must occur before we enter the
John McCall0b251722010-08-04 05:59:32 +00002946 // @synchronized. We can't avoid a temp here because we need the
2947 // value to be preserved. If the backend ever does liveness
2948 // correctly after setjmp, this will be unnecessary.
2949 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar1c566672009-02-24 01:43:46 +00002950 if (!isTry) {
John McCall0b251722010-08-04 05:59:32 +00002951 llvm::Value *SyncArg =
Daniel Dunbar1c566672009-02-24 01:43:46 +00002952 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2953 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallf1549f62010-07-06 01:34:17 +00002954 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
2955 ->setDoesNotThrow();
John McCall0b251722010-08-04 05:59:32 +00002956
2957 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
2958 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar1c566672009-02-24 01:43:46 +00002959 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00002960
John McCall0b251722010-08-04 05:59:32 +00002961 // Allocate memory for the setjmp buffer. This needs to be kept
2962 // live throughout the try and catch blocks.
2963 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2964 "exceptiondata.ptr");
2965
John McCall87bb5822010-07-31 23:20:56 +00002966 // Create the fragile hazards. Note that this will not capture any
2967 // of the allocas required for exception processing, but will
2968 // capture the current basic block (which extends all the way to the
2969 // setjmp call) as "before the @try".
2970 FragileHazards Hazards(CGF);
2971
John McCallf1549f62010-07-06 01:34:17 +00002972 // Create a flag indicating whether the cleanup needs to call
2973 // objc_exception_try_exit. This is true except when
2974 // - no catches match and we're branching through the cleanup
2975 // just to rethrow the exception, or
2976 // - a catch matched and we're falling out of the catch handler.
John McCall0b251722010-08-04 05:59:32 +00002977 // The setjmp-safety rule here is that we should always store to this
2978 // variable in a place that dominates the branch through the cleanup
2979 // without passing through any setjmps.
John McCallf1549f62010-07-06 01:34:17 +00002980 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlsson190d00e2009-02-07 21:26:04 +00002981 "_call_try_exit");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002982
John McCall9e2213d2010-10-04 23:42:51 +00002983 // A slot containing the exception to rethrow. Only needed when we
2984 // have both a @catch and a @finally.
2985 llvm::Value *PropagatingExnVar = 0;
2986
John McCallf1549f62010-07-06 01:34:17 +00002987 // Push a normal cleanup to leave the try scope.
John McCall1f0fca52010-07-21 07:22:38 +00002988 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall0b251722010-08-04 05:59:32 +00002989 SyncArgSlot,
John McCall1f0fca52010-07-21 07:22:38 +00002990 CallTryExitVar,
2991 ExceptionData,
2992 &ObjCTypes);
John McCallf1549f62010-07-06 01:34:17 +00002993
2994 // Enter a try block:
2995 // - Call objc_exception_try_enter to push ExceptionData on top of
2996 // the EH stack.
2997 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
2998 ->setDoesNotThrow();
2999
3000 // - Call setjmp on the exception data buffer.
3001 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
3002 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
3003 llvm::Value *SetJmpBuffer =
Jay Foad0f6ac7c2011-07-22 08:16:57 +00003004 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, "setjmp_buffer");
John McCallf1549f62010-07-06 01:34:17 +00003005 llvm::CallInst *SetJmpResult =
3006 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
3007 SetJmpResult->setDoesNotThrow();
3008
3009 // If setjmp returned 0, enter the protected block; otherwise,
3010 // branch to the handler.
Daniel Dunbar55e87422008-11-11 02:29:29 +00003011 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
3012 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallf1549f62010-07-06 01:34:17 +00003013 llvm::Value *DidCatch =
John McCalld96a8e72010-08-11 00:16:14 +00003014 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3015 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson80f25672008-09-09 17:59:25 +00003016
John McCallf1549f62010-07-06 01:34:17 +00003017 // Emit the protected block.
Anders Carlsson80f25672008-09-09 17:59:25 +00003018 CGF.EmitBlock(TryBlock);
John McCall0b251722010-08-04 05:59:32 +00003019 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003020 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallf1549f62010-07-06 01:34:17 +00003021 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall0b251722010-08-04 05:59:32 +00003022
3023 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003024
John McCallf1549f62010-07-06 01:34:17 +00003025 // Emit the exception handler block.
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003026 CGF.EmitBlock(TryHandler);
Daniel Dunbar55e40722008-09-27 07:03:52 +00003027
John McCall87bb5822010-07-31 23:20:56 +00003028 // Don't optimize loads of the in-scope locals across this point.
3029 Hazards.emitWriteHazard();
3030
John McCallf1549f62010-07-06 01:34:17 +00003031 // For a @synchronized (or a @try with no catches), just branch
3032 // through the cleanup to the rethrow block.
3033 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
3034 // Tell the cleanup not to re-pop the exit.
John McCall0b251722010-08-04 05:59:32 +00003035 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003036 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallf1549f62010-07-06 01:34:17 +00003037
3038 // Otherwise, we have to match against the caught exceptions.
3039 } else {
John McCall0b251722010-08-04 05:59:32 +00003040 // Retrieve the exception object. We may emit multiple blocks but
3041 // nothing can cross this so the value is already in SSA form.
3042 llvm::CallInst *Caught =
3043 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3044 ExceptionData, "caught");
3045 Caught->setDoesNotThrow();
3046
John McCallf1549f62010-07-06 01:34:17 +00003047 // Push the exception to rethrow onto the EH value stack for the
3048 // benefit of any @throws in the handlers.
3049 CGF.ObjCEHValueStack.push_back(Caught);
3050
Douglas Gregor8f5e3dd2010-04-23 22:50:49 +00003051 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003052
John McCall0b251722010-08-04 05:59:32 +00003053 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallf1549f62010-07-06 01:34:17 +00003054
John McCall0b251722010-08-04 05:59:32 +00003055 llvm::BasicBlock *CatchBlock = 0;
3056 llvm::BasicBlock *CatchHandler = 0;
3057 if (HasFinally) {
John McCall9e2213d2010-10-04 23:42:51 +00003058 // Save the currently-propagating exception before
3059 // objc_exception_try_enter clears the exception slot.
3060 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3061 "propagating_exception");
3062 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3063
John McCall0b251722010-08-04 05:59:32 +00003064 // Enter a new exception try block (in case a @catch block
3065 // throws an exception).
3066 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3067 ->setDoesNotThrow();
Anders Carlsson80f25672008-09-09 17:59:25 +00003068
John McCall0b251722010-08-04 05:59:32 +00003069 llvm::CallInst *SetJmpResult =
3070 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3071 "setjmp.result");
3072 SetJmpResult->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003073
John McCall0b251722010-08-04 05:59:32 +00003074 llvm::Value *Threw =
3075 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3076
3077 CatchBlock = CGF.createBasicBlock("catch");
3078 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3079 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3080
3081 CGF.EmitBlock(CatchBlock);
3082 }
3083
3084 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003085
Daniel Dunbar55e40722008-09-27 07:03:52 +00003086 // Handle catch list. As a special case we check if everything is
3087 // matched and avoid generating code for falling off the end if
3088 // so.
3089 bool AllMatched = false;
Douglas Gregor8f5e3dd2010-04-23 22:50:49 +00003090 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3091 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson80f25672008-09-09 17:59:25 +00003092
Douglas Gregorc00d8e12010-04-26 16:46:50 +00003093 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff14108da2009-07-10 23:34:53 +00003094 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar129271a2008-09-27 07:36:24 +00003095
Anders Carlsson80f25672008-09-09 17:59:25 +00003096 // catch(...) always matches.
Daniel Dunbar55e40722008-09-27 07:03:52 +00003097 if (!CatchParam) {
3098 AllMatched = true;
3099 } else {
John McCall183700f2009-09-21 23:43:11 +00003100 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003101
John McCallf1549f62010-07-06 01:34:17 +00003102 // catch(id e) always matches under this ABI, since only
3103 // ObjC exceptions end up here in the first place.
Daniel Dunbar97f61d12008-09-27 22:21:14 +00003104 // FIXME: For the time being we also match id<X>; this should
3105 // be rejected by Sema instead.
Eli Friedman818e96f2009-07-11 00:57:02 +00003106 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbar55e40722008-09-27 07:03:52 +00003107 AllMatched = true;
Anders Carlsson80f25672008-09-09 17:59:25 +00003108 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003109
John McCallf1549f62010-07-06 01:34:17 +00003110 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003111 if (AllMatched) {
John McCallf1549f62010-07-06 01:34:17 +00003112 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3113
Anders Carlssondde0a942008-09-11 09:15:33 +00003114 if (CatchParam) {
John McCallb6bbcc92010-10-15 04:57:14 +00003115 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003116 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallf1549f62010-07-06 01:34:17 +00003117
3118 // These types work out because ConvertType(id) == i8*.
Steve Naroff7ba138a2009-03-03 19:52:17 +00003119 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlssondde0a942008-09-11 09:15:33 +00003120 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003121
Anders Carlssondde0a942008-09-11 09:15:33 +00003122 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003123
3124 // The scope of the catch variable ends right here.
3125 CatchVarCleanups.ForceCleanup();
3126
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003127 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson80f25672008-09-09 17:59:25 +00003128 break;
3129 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003130
Steve Naroff14108da2009-07-10 23:34:53 +00003131 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall506b57e2010-05-17 21:00:27 +00003132 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallf1549f62010-07-06 01:34:17 +00003133
3134 // FIXME: @catch (Class c) ?
John McCall506b57e2010-05-17 21:00:27 +00003135 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3136 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson80f25672008-09-09 17:59:25 +00003137
3138 // Check if the @catch block matches the exception object.
John McCall506b57e2010-05-17 21:00:27 +00003139 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003140
John McCallf1549f62010-07-06 01:34:17 +00003141 llvm::CallInst *Match =
Chris Lattner34b02a12009-04-22 02:26:14 +00003142 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3143 Class, Caught, "match");
John McCallf1549f62010-07-06 01:34:17 +00003144 Match->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003145
John McCallf1549f62010-07-06 01:34:17 +00003146 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3147 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003148
3149 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003150 MatchedBlock, NextCatchBlock);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003151
Anders Carlsson80f25672008-09-09 17:59:25 +00003152 // Emit the @catch block.
3153 CGF.EmitBlock(MatchedBlock);
John McCallf1549f62010-07-06 01:34:17 +00003154
3155 // Collect any cleanups for the catch variable. The scope lasts until
3156 // the end of the catch body.
John McCall0b251722010-08-04 05:59:32 +00003157 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallf1549f62010-07-06 01:34:17 +00003158
John McCallb6bbcc92010-10-15 04:57:14 +00003159 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003160 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003161
John McCallf1549f62010-07-06 01:34:17 +00003162 // Initialize the catch variable.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003163 llvm::Value *Tmp =
3164 CGF.Builder.CreateBitCast(Caught,
Benjamin Kramer578faa82011-09-27 21:06:10 +00003165 CGF.ConvertType(CatchParam->getType()));
Steve Naroff7ba138a2009-03-03 19:52:17 +00003166 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003167
Anders Carlssondde0a942008-09-11 09:15:33 +00003168 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003169
3170 // We're done with the catch variable.
3171 CatchVarCleanups.ForceCleanup();
3172
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003173 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003174
Anders Carlsson80f25672008-09-09 17:59:25 +00003175 CGF.EmitBlock(NextCatchBlock);
3176 }
3177
John McCallf1549f62010-07-06 01:34:17 +00003178 CGF.ObjCEHValueStack.pop_back();
3179
John McCall0b251722010-08-04 05:59:32 +00003180 // If nothing wanted anything to do with the caught exception,
3181 // kill the extract call.
3182 if (Caught->use_empty())
3183 Caught->eraseFromParent();
3184
3185 if (!AllMatched)
3186 CGF.EmitBranchThroughCleanup(FinallyRethrow);
3187
3188 if (HasFinally) {
3189 // Emit the exception handler for the @catch blocks.
3190 CGF.EmitBlock(CatchHandler);
3191
3192 // In theory we might now need a write hazard, but actually it's
3193 // unnecessary because there's no local-accessing code between
3194 // the try's write hazard and here.
3195 //Hazards.emitWriteHazard();
3196
John McCall9e2213d2010-10-04 23:42:51 +00003197 // Extract the new exception and save it to the
3198 // propagating-exception slot.
3199 assert(PropagatingExnVar);
3200 llvm::CallInst *NewCaught =
3201 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3202 ExceptionData, "caught");
3203 NewCaught->setDoesNotThrow();
3204 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
3205
John McCall0b251722010-08-04 05:59:32 +00003206 // Don't pop the catch handler; the throw already did.
3207 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003208 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar55e40722008-09-27 07:03:52 +00003209 }
Anders Carlsson80f25672008-09-09 17:59:25 +00003210 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003211
John McCall87bb5822010-07-31 23:20:56 +00003212 // Insert read hazards as required in the new blocks.
John McCall0b251722010-08-04 05:59:32 +00003213 Hazards.emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00003214
John McCallf1549f62010-07-06 01:34:17 +00003215 // Pop the cleanup.
John McCall0b251722010-08-04 05:59:32 +00003216 CGF.Builder.restoreIP(TryFallthroughIP);
3217 if (CGF.HaveInsertPoint())
3218 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallf1549f62010-07-06 01:34:17 +00003219 CGF.PopCleanupBlock();
John McCall0b251722010-08-04 05:59:32 +00003220 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003221
John McCallf1549f62010-07-06 01:34:17 +00003222 // Emit the rethrow block.
John McCall87bb5822010-07-31 23:20:56 +00003223 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallff8e1152010-07-23 21:56:41 +00003224 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallf1549f62010-07-06 01:34:17 +00003225 if (CGF.HaveInsertPoint()) {
John McCall9e2213d2010-10-04 23:42:51 +00003226 // If we have a propagating-exception variable, check it.
3227 llvm::Value *PropagatingExn;
3228 if (PropagatingExnVar) {
3229 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall0b251722010-08-04 05:59:32 +00003230
John McCall9e2213d2010-10-04 23:42:51 +00003231 // Otherwise, just look in the buffer for the exception to throw.
3232 } else {
3233 llvm::CallInst *Caught =
3234 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3235 ExceptionData);
3236 Caught->setDoesNotThrow();
3237 PropagatingExn = Caught;
3238 }
3239
3240 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallf1549f62010-07-06 01:34:17 +00003241 ->setDoesNotThrow();
3242 CGF.Builder.CreateUnreachable();
Fariborz Jahanianf2878e52008-11-21 19:21:53 +00003243 }
Anders Carlsson80f25672008-09-09 17:59:25 +00003244
John McCall87bb5822010-07-31 23:20:56 +00003245 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00003246}
3247
3248void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar898d5082008-09-30 01:06:03 +00003249 const ObjCAtThrowStmt &S) {
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003250 llvm::Value *ExceptionAsObject;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003251
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003252 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall2b014d62011-10-01 10:32:24 +00003253 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003254 ExceptionAsObject =
Benjamin Kramer578faa82011-09-27 21:06:10 +00003255 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003256 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003257 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003258 "Unexpected rethrow outside @catch block.");
Anders Carlsson273558f2009-02-07 21:37:21 +00003259 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003260 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003261
John McCallf1549f62010-07-06 01:34:17 +00003262 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3263 ->setDoesNotReturn();
Anders Carlsson80f25672008-09-09 17:59:25 +00003264 CGF.Builder.CreateUnreachable();
Daniel Dunbara448fb22008-11-11 23:11:34 +00003265
3266 // Clear the insertion point to indicate we are in unreachable code.
3267 CGF.Builder.ClearInsertionPoint();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00003268}
3269
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003270/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00003271/// object: objc_read_weak (id *src)
3272///
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003273llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003274 llvm::Value *AddrWeakObj) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00003275 llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003276 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3277 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3278 ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00003279 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003280 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00003281 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00003282 return read_weak;
3283}
3284
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003285/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
3286/// objc_assign_weak (id src, id *dst)
3287///
3288void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003289 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00003290 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003291 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003292 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003293 assert(Size <= 8 && "does not support size > 8");
3294 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003295 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003296 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3297 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003298 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3299 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00003300 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003301 src, dst, "weakassign");
3302 return;
3303}
3304
Fariborz Jahanian58626502008-11-19 00:59:10 +00003305/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
3306/// objc_assign_global (id src, id *dst)
3307///
3308void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00003309 llvm::Value *src, llvm::Value *dst,
3310 bool threadlocal) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00003311 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003312 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003313 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003314 assert(Size <= 8 && "does not support size > 8");
3315 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003316 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003317 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3318 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003319 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3320 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00003321 if (!threadlocal)
3322 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
3323 src, dst, "globalassign");
3324 else
3325 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
3326 src, dst, "threadlocalassign");
Fariborz Jahanian58626502008-11-19 00:59:10 +00003327 return;
3328}
3329
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003330/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003331/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003332///
3333void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003334 llvm::Value *src, llvm::Value *dst,
3335 llvm::Value *ivarOffset) {
3336 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Chris Lattner2acc6e32011-07-18 04:24:23 +00003337 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003338 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003339 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003340 assert(Size <= 8 && "does not support size > 8");
3341 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003342 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003343 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3344 }
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003345 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3346 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003347 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3348 src, dst, ivarOffset);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003349 return;
3350}
3351
Fariborz Jahanian58626502008-11-19 00:59:10 +00003352/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
3353/// objc_assign_strongCast (id src, id *dst)
3354///
3355void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003356 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00003357 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003358 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003359 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003360 assert(Size <= 8 && "does not support size > 8");
3361 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003362 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003363 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3364 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003365 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3366 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00003367 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian58626502008-11-19 00:59:10 +00003368 src, dst, "weakassign");
3369 return;
3370}
3371
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003372void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003373 llvm::Value *DestPtr,
3374 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00003375 llvm::Value *size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003376 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3377 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003378 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00003379 DestPtr, SrcPtr, size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003380 return;
3381}
3382
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00003383/// EmitObjCValueForIvar - Code Gen for ivar reference.
3384///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00003385LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3386 QualType ObjectTy,
3387 llvm::Value *BaseValue,
3388 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00003389 unsigned CVRQualifiers) {
John McCallc12c5bb2010-05-15 11:32:37 +00003390 const ObjCInterfaceDecl *ID =
3391 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00003392 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3393 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00003394}
3395
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003396llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00003397 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003398 const ObjCIvarDecl *Ivar) {
Daniel Dunbar97776872009-04-22 07:32:20 +00003399 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003400 return llvm::ConstantInt::get(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003401 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3402 Offset);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003403}
3404
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003405/* *** Private Interface *** */
3406
3407/// EmitImageInfo - Emit the image info marker used to encode some module
3408/// level information.
3409///
3410/// See: <rdr://4810609&4810587&4810587>
3411/// struct IMAGE_INFO {
3412/// unsigned version;
3413/// unsigned flags;
3414/// };
3415enum ImageInfoFlags {
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003416 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003417 eImageInfo_GarbageCollected = (1 << 1),
3418 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003419 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3420
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003421 // A flag indicating that the module has no instances of a @synthesize of a
3422 // superclass variable. <rdar://problem/6803242>
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003423 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003424};
3425
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003426void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003427 unsigned version = 0; // Version is unused?
3428 unsigned flags = 0;
3429
3430 // FIXME: Fix and continue?
Douglas Gregore289d812011-09-13 17:21:33 +00003431 if (CGM.getLangOptions().getGC() != LangOptions::NonGC)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003432 flags |= eImageInfo_GarbageCollected;
Douglas Gregore289d812011-09-13 17:21:33 +00003433 if (CGM.getLangOptions().getGC() == LangOptions::GCOnly)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003434 flags |= eImageInfo_GCOnly;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003435
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003436 // We never allow @synthesize of a superclass property.
3437 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003438
Chris Lattner2acc6e32011-07-18 04:24:23 +00003439 llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
Chris Lattner77b89b82010-06-27 07:15:29 +00003440
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003441 // Emitted as int[2];
3442 llvm::Constant *values[2] = {
Chris Lattner77b89b82010-06-27 07:15:29 +00003443 llvm::ConstantInt::get(Int32Ty, version),
3444 llvm::ConstantInt::get(Int32Ty, flags)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003445 };
Chris Lattner77b89b82010-06-27 07:15:29 +00003446 llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003447
3448 const char *Section;
3449 if (ObjCABI == 1)
3450 Section = "__OBJC, __image_info,regular";
3451 else
3452 Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003453 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003454 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
Jay Foad97357602011-06-22 09:24:39 +00003455 llvm::ConstantArray::get(AT, values),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003456 Section,
3457 0,
3458 true);
3459 GV->setConstant(true);
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003460}
3461
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003462
3463// struct objc_module {
3464// unsigned long version;
3465// unsigned long size;
3466// const char *name;
3467// Symtab symtab;
3468// };
3469
3470// FIXME: Get from somewhere
3471static const int ModuleVersion = 7;
3472
3473void CGObjCMac::EmitModuleInfo() {
Duncan Sands9408c452009-05-09 07:08:47 +00003474 uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003475
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00003476 llvm::Constant *Values[] = {
3477 llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion),
3478 llvm::ConstantInt::get(ObjCTypes.LongTy, Size),
3479 // This used to be the filename, now it is unused. <rdr://4327263>
3480 GetClassName(&CGM.getContext().Idents.get("")),
3481 EmitModuleSymbols()
3482 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003483 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson08e25242009-07-27 22:29:56 +00003484 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003485 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00003486 4, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003487}
3488
3489llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003490 unsigned NumClasses = DefinedClasses.size();
3491 unsigned NumCategories = DefinedCategories.size();
3492
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003493 // Return null if no symbols were defined.
3494 if (!NumClasses && !NumCategories)
Owen Andersonc9c88b42009-07-31 20:28:54 +00003495 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003496
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003497 llvm::Constant *Values[5];
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003498 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Andersonc9c88b42009-07-31 20:28:54 +00003499 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003500 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3501 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003502
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003503 // The runtime expects exactly the list of defined classes followed
3504 // by the list of defined categories, in a single array.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003505 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003506 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00003507 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003508 ObjCTypes.Int8PtrTy);
3509 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003510 Symbols[NumClasses + i] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003511 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003512 ObjCTypes.Int8PtrTy);
3513
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003514 Values[4] =
Owen Anderson96e0fc72009-07-29 22:16:19 +00003515 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003516 NumClasses + NumCategories),
3517 Symbols);
3518
Chris Lattnerc5cbb902011-06-20 04:01:35 +00003519 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003520
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003521 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003522 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3523 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003524 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00003525 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003526}
3527
John McCallf85e1932011-06-15 23:02:42 +00003528llvm::Value *CGObjCMac::EmitClassRefFromId(CGBuilderTy &Builder,
3529 IdentifierInfo *II) {
3530 LazySymbols.insert(II);
3531
3532 llvm::GlobalVariable *&Entry = ClassReferences[II];
3533
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003534 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003535 llvm::Constant *Casted =
John McCallf85e1932011-06-15 23:02:42 +00003536 llvm::ConstantExpr::getBitCast(GetClassName(II),
3537 ObjCTypes.ClassPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003538 Entry =
John McCallf85e1932011-06-15 23:02:42 +00003539 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3540 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
3541 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003542 }
John McCallf85e1932011-06-15 23:02:42 +00003543
Benjamin Kramer578faa82011-09-27 21:06:10 +00003544 return Builder.CreateLoad(Entry);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003545}
3546
John McCallf85e1932011-06-15 23:02:42 +00003547llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
3548 const ObjCInterfaceDecl *ID) {
3549 return EmitClassRefFromId(Builder, ID->getIdentifier());
3550}
3551
3552llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder) {
3553 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
3554 return EmitClassRefFromId(Builder, II);
3555}
3556
Fariborz Jahanian03b29602010-06-17 19:56:20 +00003557llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3558 bool lvalue) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003559 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003560
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003561 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003562 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003563 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003564 ObjCTypes.SelectorPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003565 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003566 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3567 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003568 4, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003569 }
3570
Fariborz Jahanian03b29602010-06-17 19:56:20 +00003571 if (lvalue)
3572 return Entry;
Benjamin Kramer578faa82011-09-27 21:06:10 +00003573 return Builder.CreateLoad(Entry);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003574}
3575
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00003576llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003577 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003578
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003579 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003580 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003581 llvm::ConstantArray::get(VMContext,
3582 Ident->getNameStart()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003583 ((ObjCABI == 2) ?
3584 "__TEXT,__objc_classname,cstring_literals" :
3585 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003586 1, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003587
Owen Andersona1cf15f2009-07-14 23:10:40 +00003588 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003589}
3590
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00003591llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
3592 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
3593 I = MethodDefinitions.find(MD);
3594 if (I != MethodDefinitions.end())
3595 return I->second;
3596
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00003597 return NULL;
3598}
3599
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00003600/// GetIvarLayoutName - Returns a unique constant for the given
3601/// ivar layout bitmap.
3602llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003603 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Andersonc9c88b42009-07-31 20:28:54 +00003604 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00003605}
3606
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003607void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003608 unsigned int BytePos,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003609 bool ForStrongLayout,
3610 bool &HasUnion) {
3611 const RecordDecl *RD = RT->getDecl();
3612 // FIXME - Use iterator.
Jordy Rosedb8264e2011-07-22 02:08:32 +00003613 SmallVector<const FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
Chris Lattner2acc6e32011-07-18 04:24:23 +00003614 llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003615 const llvm::StructLayout *RecLayout =
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003616 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003617
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003618 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3619 ForStrongLayout, HasUnion);
3620}
3621
Daniel Dunbar5a5a8032009-05-03 21:05:10 +00003622void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003623 const llvm::StructLayout *Layout,
3624 const RecordDecl *RD,
Jordy Rosedb8264e2011-07-22 02:08:32 +00003625 const SmallVectorImpl<const FieldDecl*> &RecFields,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003626 unsigned int BytePos, bool ForStrongLayout,
3627 bool &HasUnion) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003628 bool IsUnion = (RD && RD->isUnion());
3629 uint64_t MaxUnionIvarSize = 0;
3630 uint64_t MaxSkippedUnionIvarSize = 0;
Jordy Rosedb8264e2011-07-22 02:08:32 +00003631 const FieldDecl *MaxField = 0;
3632 const FieldDecl *MaxSkippedField = 0;
3633 const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003634 uint64_t MaxFieldOffset = 0;
3635 uint64_t MaxSkippedFieldOffset = 0;
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003636 uint64_t LastBitfieldOrUnnamedOffset = 0;
John McCallf85e1932011-06-15 23:02:42 +00003637 uint64_t FirstFieldDelta = 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003638
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003639 if (RecFields.empty())
3640 return;
Douglas Gregorbcfd1f52011-09-02 00:18:52 +00003641 unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
3642 unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
John McCallf85e1932011-06-15 23:02:42 +00003643 if (!RD && CGM.getLangOptions().ObjCAutoRefCount) {
Jordy Rosedb8264e2011-07-22 02:08:32 +00003644 const FieldDecl *FirstField = RecFields[0];
John McCallf85e1932011-06-15 23:02:42 +00003645 FirstFieldDelta =
3646 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
3647 }
3648
Chris Lattnerf1690852009-03-31 08:48:01 +00003649 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Jordy Rosedb8264e2011-07-22 02:08:32 +00003650 const FieldDecl *Field = RecFields[i];
Daniel Dunbare05cc982009-05-03 23:35:23 +00003651 uint64_t FieldOffset;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00003652 if (RD) {
Daniel Dunbarf8f8eba2010-04-14 17:02:21 +00003653 // Note that 'i' here is actually the field index inside RD of Field,
3654 // although this dependency is hidden.
3655 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
John McCallf85e1932011-06-15 23:02:42 +00003656 FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00003657 } else
John McCallf85e1932011-06-15 23:02:42 +00003658 FieldOffset =
3659 ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003660
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003661 // Skip over unnamed or bitfields
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003662 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003663 LastFieldBitfieldOrUnnamed = Field;
3664 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003665 continue;
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003666 }
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003667
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003668 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003669 QualType FQT = Field->getType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003670 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003671 if (FQT->isUnionType())
3672 HasUnion = true;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003673
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003674 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003675 BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003676 ForStrongLayout, HasUnion);
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003677 continue;
3678 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003679
Chris Lattnerf1690852009-03-31 08:48:01 +00003680 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003681 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003682 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003683 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003684 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003685 FQT = CArray->getElementType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003686 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3687 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003688 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003689 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003690 FQT = CArray->getElementType();
3691 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003692
3693 assert(!FQT->isUnionType() &&
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003694 "layout for array of unions not supported");
Fariborz Jahanianf96bdf42011-01-03 19:23:18 +00003695 if (FQT->isRecordType() && ElCount) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003696 int OldIndex = IvarsInfo.size() - 1;
3697 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003698
Ted Kremenek6217b802009-07-29 21:53:49 +00003699 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003700 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003701 ForStrongLayout, HasUnion);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003702
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003703 // Replicate layout information for each array element. Note that
3704 // one element is already done.
3705 uint64_t ElIx = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003706 for (int FirstIndex = IvarsInfo.size() - 1,
3707 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003708 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003709 for (int i = OldIndex+1; i <= FirstIndex; ++i)
3710 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3711 IvarsInfo[i].ivar_size));
3712 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3713 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3714 SkipIvars[i].ivar_size));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003715 }
3716 continue;
3717 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003718 }
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003719 // At this point, we are done with Record/Union and array there of.
3720 // For other arrays we are down to its element type.
John McCall0953e762009-09-24 19:53:00 +00003721 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003722
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003723 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall0953e762009-09-24 19:53:00 +00003724 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3725 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00003726 if (IsUnion) {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003727 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar487993b2009-05-03 13:32:01 +00003728 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003729 MaxUnionIvarSize = UnionIvarSize;
3730 MaxField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003731 MaxFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003732 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00003733 } else {
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003734 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003735 FieldSize / WordSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003736 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003737 } else if ((ForStrongLayout &&
John McCall0953e762009-09-24 19:53:00 +00003738 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3739 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00003740 if (IsUnion) {
Mike Stumpf5408fe2009-05-16 07:57:57 +00003741 // FIXME: Why the asymmetry? We divide by word size in bits on other
3742 // side.
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003743 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar487993b2009-05-03 13:32:01 +00003744 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003745 MaxSkippedUnionIvarSize = UnionIvarSize;
3746 MaxSkippedField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003747 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003748 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00003749 } else {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003750 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003751 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003752 FieldSize / ByteSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003753 }
3754 }
3755 }
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003756
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003757 if (LastFieldBitfieldOrUnnamed) {
3758 if (LastFieldBitfieldOrUnnamed->isBitField()) {
3759 // Last field was a bitfield. Must update skip info.
Richard Smitha6b8b2c2011-10-10 18:28:20 +00003760 uint64_t BitFieldSize
3761 = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003762 GC_IVAR skivar;
3763 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
3764 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3765 + ((BitFieldSize % ByteSizeInBits) != 0);
3766 SkipIvars.push_back(skivar);
3767 } else {
3768 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
3769 // Last field was unnamed. Must update skip info.
3770 unsigned FieldSize
3771 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
3772 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
3773 FieldSize / ByteSizeInBits));
3774 }
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003775 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003776
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003777 if (MaxField)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003778 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003779 MaxUnionIvarSize));
3780 if (MaxSkippedField)
Daniel Dunbar900c1982009-05-03 23:31:46 +00003781 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003782 MaxSkippedUnionIvarSize));
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00003783}
3784
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003785/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
3786/// the computations and returning the layout bitmap (for ivar or blocks) in
3787/// the given argument BitMap string container. Routine reads
3788/// two containers, IvarsInfo and SkipIvars which are assumed to be
3789/// filled already by the caller.
3790llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003791 unsigned int WordsToScan, WordsToSkip;
Chris Lattner2acc6e32011-07-18 04:24:23 +00003792 llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003793
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003794 // Build the string of skip/scan nibbles
Chris Lattner5f9e2722011-07-23 10:55:15 +00003795 SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003796 unsigned int WordSize =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003797 CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003798 if (IvarsInfo[0].ivar_bytepos == 0) {
3799 WordsToSkip = 0;
3800 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003801 } else {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003802 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3803 WordsToScan = IvarsInfo[0].ivar_size;
3804 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003805 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003806 unsigned int TailPrevGCObjC =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003807 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003808 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003809 // consecutive 'scanned' object pointers.
3810 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003811 } else {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003812 // Skip over 'gc'able object pointer which lay over each other.
3813 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3814 continue;
3815 // Must skip over 1 or more words. We save current skip/scan values
3816 // and start a new pair.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003817 SKIP_SCAN SkScan;
3818 SkScan.skip = WordsToSkip;
3819 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003820 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003821
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003822 // Skip the hole.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003823 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3824 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003825 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003826 WordsToSkip = 0;
3827 WordsToScan = IvarsInfo[i].ivar_size;
3828 }
3829 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003830 if (WordsToScan > 0) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003831 SKIP_SCAN SkScan;
3832 SkScan.skip = WordsToSkip;
3833 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003834 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003835 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003836
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003837 if (!SkipIvars.empty()) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003838 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003839 int LastByteSkipped =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003840 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003841 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003842 int LastByteScanned =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003843 IvarsInfo[LastIndex].ivar_bytepos +
3844 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003845 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramer54d76db2009-12-25 15:43:36 +00003846 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003847 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003848 SKIP_SCAN SkScan;
3849 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3850 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003851 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003852 }
3853 }
3854 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3855 // as 0xMN.
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003856 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003857 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003858 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3859 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3860 // 0xM0 followed by 0x0N detected.
3861 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3862 for (int j = i+1; j < SkipScan; j++)
3863 SkipScanIvars[j] = SkipScanIvars[j+1];
3864 --SkipScan;
3865 }
3866 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003867
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003868 // Generate the string.
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003869 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003870 unsigned char byte;
3871 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3872 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3873 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
3874 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003875
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003876 // first skip big.
3877 for (unsigned int ix = 0; ix < skip_big; ix++)
3878 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003879
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003880 // next (skip small, scan)
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003881 if (skip_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003882 byte = skip_small << 4;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003883 if (scan_big > 0) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003884 byte |= 0xf;
3885 --scan_big;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003886 } else if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003887 byte |= scan_small;
3888 scan_small = 0;
3889 }
3890 BitMap += byte;
3891 }
3892 // next scan big
3893 for (unsigned int ix = 0; ix < scan_big; ix++)
3894 BitMap += (unsigned char)(0x0f);
3895 // last scan small
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003896 if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003897 byte = scan_small;
3898 BitMap += byte;
3899 }
3900 }
3901 // null terminate string.
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003902 unsigned char zero = 0;
3903 BitMap += zero;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003904
3905 llvm::GlobalVariable * Entry =
3906 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3907 llvm::ConstantArray::get(VMContext, BitMap.c_str()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003908 ((ObjCABI == 2) ?
3909 "__TEXT,__objc_classname,cstring_literals" :
3910 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003911 1, true);
3912 return getConstantGEP(VMContext, Entry, 0, 0);
3913}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003914
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003915/// BuildIvarLayout - Builds ivar layout bitmap for the class
3916/// implementation for the __strong or __weak case.
3917/// The layout map displays which words in ivar list must be skipped
3918/// and which must be scanned by GC (see below). String is built of bytes.
3919/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
3920/// of words to skip and right nibble is count of words to scan. So, each
3921/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
3922/// represented by a 0x00 byte which also ends the string.
3923/// 1. when ForStrongLayout is true, following ivars are scanned:
3924/// - id, Class
3925/// - object *
3926/// - __strong anything
3927///
3928/// 2. When ForStrongLayout is false, following ivars are scanned:
3929/// - __weak anything
3930///
3931llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
3932 const ObjCImplementationDecl *OMD,
3933 bool ForStrongLayout) {
3934 bool hasUnion = false;
3935
Chris Lattner2acc6e32011-07-18 04:24:23 +00003936 llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Douglas Gregore289d812011-09-13 17:21:33 +00003937 if (CGM.getLangOptions().getGC() == LangOptions::NonGC &&
John McCallf85e1932011-06-15 23:02:42 +00003938 !CGM.getLangOptions().ObjCAutoRefCount)
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003939 return llvm::Constant::getNullValue(PtrTy);
3940
Jordy Rosedb8264e2011-07-22 02:08:32 +00003941 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
3942 SmallVector<const FieldDecl*, 32> RecFields;
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00003943 if (CGM.getLangOptions().ObjCAutoRefCount) {
Jordy Rosedb8264e2011-07-22 02:08:32 +00003944 for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00003945 IVD; IVD = IVD->getNextIvar())
3946 RecFields.push_back(cast<FieldDecl>(IVD));
3947 }
3948 else {
Jordy Rosedb8264e2011-07-22 02:08:32 +00003949 SmallVector<const ObjCIvarDecl*, 32> Ivars;
John McCallf85e1932011-06-15 23:02:42 +00003950 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003951
Jordy Rosedb8264e2011-07-22 02:08:32 +00003952 // FIXME: This is not ideal; we shouldn't have to do this copy.
3953 RecFields.append(Ivars.begin(), Ivars.end());
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00003954 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003955
3956 if (RecFields.empty())
3957 return llvm::Constant::getNullValue(PtrTy);
3958
3959 SkipIvars.clear();
3960 IvarsInfo.clear();
3961
3962 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
3963 if (IvarsInfo.empty())
3964 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003965 // Sort on byte position in case we encounterred a union nested in
3966 // the ivar list.
3967 if (hasUnion && !IvarsInfo.empty())
3968 std::sort(IvarsInfo.begin(), IvarsInfo.end());
3969 if (hasUnion && !SkipIvars.empty())
3970 std::sort(SkipIvars.begin(), SkipIvars.end());
3971
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003972 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003973 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003974
3975 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003976 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian3d2ad662009-04-20 22:03:45 +00003977 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar4087f272010-08-17 22:39:59 +00003978 OMD->getClassInterface()->getName().data());
Fariborz Jahanian3d2ad662009-04-20 22:03:45 +00003979 const unsigned char *s = (unsigned char*)BitMap.c_str();
3980 for (unsigned i = 0; i < BitMap.size(); i++)
3981 if (!(s[i] & 0xf0))
3982 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3983 else
3984 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
3985 printf("\n");
3986 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003987 return C;
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00003988}
3989
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003990llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003991 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3992
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003993 // FIXME: Avoid std::string copying.
3994 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003995 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Owen Anderson0032b272009-08-13 21:57:51 +00003996 llvm::ConstantArray::get(VMContext, Sel.getAsString()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003997 ((ObjCABI == 2) ?
3998 "__TEXT,__objc_methname,cstring_literals" :
3999 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004000 1, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004001
Owen Andersona1cf15f2009-07-14 23:10:40 +00004002 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004003}
4004
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004005// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004006llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004007 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
4008}
4009
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00004010llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel7794bb82009-03-04 18:21:39 +00004011 std::string TypeStr;
4012 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
4013
4014 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004015
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004016 if (!Entry)
4017 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson0032b272009-08-13 21:57:51 +00004018 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004019 ((ObjCABI == 2) ?
4020 "__TEXT,__objc_methtype,cstring_literals" :
4021 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004022 1, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004023
Owen Andersona1cf15f2009-07-14 23:10:40 +00004024 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00004025}
4026
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004027llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004028 std::string TypeStr;
Douglas Gregorf968d832011-05-27 01:19:52 +00004029 if (CGM.getContext().getObjCEncodingForMethodDecl(
4030 const_cast<ObjCMethodDecl*>(D),
4031 TypeStr))
4032 return 0;
Devang Patel7794bb82009-03-04 18:21:39 +00004033
4034 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
4035
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004036 if (!Entry)
4037 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson0032b272009-08-13 21:57:51 +00004038 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00004039 ((ObjCABI == 2) ?
4040 "__TEXT,__objc_methtype,cstring_literals" :
4041 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004042 1, true);
Devang Patel7794bb82009-03-04 18:21:39 +00004043
Owen Andersona1cf15f2009-07-14 23:10:40 +00004044 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004045}
4046
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004047// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004048llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004049 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004050
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004051 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004052 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004053 llvm::ConstantArray::get(VMContext,
4054 Ident->getNameStart()),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004055 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00004056 1, true);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004057
Owen Andersona1cf15f2009-07-14 23:10:40 +00004058 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004059}
4060
4061// FIXME: Merge into a single cstring creation function.
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00004062// FIXME: This Decl should be more precise.
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004063llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004064CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4065 const Decl *Container) {
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00004066 std::string TypeStr;
4067 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004068 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4069}
4070
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004071void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004072 const ObjCContainerDecl *CD,
Chris Lattner5f9e2722011-07-23 10:55:15 +00004073 SmallVectorImpl<char> &Name) {
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004074 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian679a5022009-01-10 21:06:09 +00004075 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004076 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4077 << '[' << CD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004078 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004079 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer900fc632010-04-17 09:33:03 +00004080 OS << '(' << CID << ')';
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004081 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00004082}
4083
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004084void CGObjCMac::FinishModule() {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004085 EmitModuleInfo();
4086
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004087 // Emit the dummy bodies for any protocols which were referenced but
4088 // never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004089 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerad64e022009-07-17 23:57:13 +00004090 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4091 if (I->second->hasInitializer())
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004092 continue;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004093
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00004094 llvm::Constant *Values[5];
Owen Andersonc9c88b42009-07-31 20:28:54 +00004095 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004096 Values[1] = GetClassName(I->first);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004097 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004098 Values[3] = Values[4] =
Owen Andersonc9c88b42009-07-31 20:28:54 +00004099 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004100 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson08e25242009-07-27 22:29:56 +00004101 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004102 Values));
Chris Lattnerad64e022009-07-17 23:57:13 +00004103 CGM.AddUsedGlobal(I->second);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004104 }
4105
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004106 // Add assembler directives to add lazy undefined symbol references
4107 // for classes which are referenced but not defined. This is
4108 // important for correct linker interaction.
Daniel Dunbar33063492009-09-07 00:20:42 +00004109 //
4110 // FIXME: It would be nice if we had an LLVM construct for this.
4111 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
4112 llvm::SmallString<256> Asm;
4113 Asm += CGM.getModule().getModuleInlineAsm();
4114 if (!Asm.empty() && Asm.back() != '\n')
4115 Asm += '\n';
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004116
Daniel Dunbar33063492009-09-07 00:20:42 +00004117 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbar33063492009-09-07 00:20:42 +00004118 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4119 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00004120 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4121 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004122 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004123 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004124 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004125 }
4126
4127 for (size_t i = 0; i < DefinedCategoryNames.size(); ++i) {
4128 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4129 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4130 }
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004131
Daniel Dunbar33063492009-09-07 00:20:42 +00004132 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004133 }
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004134}
4135
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004136CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004137 : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00004138 ObjCTypes(cgm) {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004139 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004140 ObjCABI = 2;
4141}
4142
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004143/* *** */
4144
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004145ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004146 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004147 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4148 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004149
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004150 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004151 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004152 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004153 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00004154 Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004155
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004156 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004157 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004158 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004159
Mike Stumpf5408fe2009-05-16 07:57:57 +00004160 // FIXME: It would be nice to unify this with the opaque type, so that the IR
4161 // comes out a bit cleaner.
Chris Lattner2acc6e32011-07-18 04:24:23 +00004162 llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004163 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004164
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004165 // I'm not sure I like this. The implicit coordination is a bit
4166 // gross. We should solve this in a reasonable fashion because this
4167 // is a pretty common task (match some runtime data structure with
4168 // an LLVM data structure).
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004169
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004170 // FIXME: This is leaked.
4171 // FIXME: Merge with rewriter code?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004172
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004173 // struct _objc_super {
4174 // id self;
4175 // Class cls;
4176 // }
Abramo Bagnara465d41b2010-05-11 21:36:43 +00004177 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00004178 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00004179 SourceLocation(), SourceLocation(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004180 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004181 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith7a614d82011-06-11 17:19:42 +00004182 Ctx.getObjCIdType(), 0, 0, false, false));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004183 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith7a614d82011-06-11 17:19:42 +00004184 Ctx.getObjCClassType(), 0, 0, false, false));
Douglas Gregor838db382010-02-11 01:19:42 +00004185 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004186
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004187 SuperCTy = Ctx.getTagDeclType(RD);
4188 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004189
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004190 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004191 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4192
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004193 // struct _prop_t {
4194 // char *name;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004195 // char *attributes;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004196 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00004197 PropertyTy = llvm::StructType::create("struct._prop_t",
4198 Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004199
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004200 // struct _prop_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004201 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004202 // uint32_t count_of_properties;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004203 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004204 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004205 PropertyListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004206 llvm::StructType::create("struct._prop_list_t", IntTy, IntTy,
4207 llvm::ArrayType::get(PropertyTy, 0), NULL);
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004208 // struct _prop_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004209 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004210
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004211 // struct _objc_method {
4212 // SEL _cmd;
4213 // char *method_type;
4214 // char *_imp;
4215 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00004216 MethodTy = llvm::StructType::create("struct._objc_method",
4217 SelectorPtrTy, Int8PtrTy, Int8PtrTy,
4218 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004219
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004220 // struct _objc_cache *
Chris Lattnerc1c20112011-08-12 17:43:31 +00004221 CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
Owen Anderson96e0fc72009-07-29 22:16:19 +00004222 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00004223
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004224}
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004225
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004226ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004227 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004228 // struct _objc_method_description {
4229 // SEL name;
4230 // char *types;
4231 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004232 MethodDescriptionTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004233 llvm::StructType::create("struct._objc_method_description",
4234 SelectorPtrTy, Int8PtrTy, NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004235
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004236 // struct _objc_method_description_list {
4237 // int count;
4238 // struct _objc_method_description[1];
4239 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004240 MethodDescriptionListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004241 llvm::StructType::create("struct._objc_method_description_list",
4242 IntTy,
4243 llvm::ArrayType::get(MethodDescriptionTy, 0),NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004244
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004245 // struct _objc_method_description_list *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004246 MethodDescriptionListPtrTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004247 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004248
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004249 // Protocol description structures
4250
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004251 // struct _objc_protocol_extension {
4252 // uint32_t size; // sizeof(struct _objc_protocol_extension)
4253 // struct _objc_method_description_list *optional_instance_methods;
4254 // struct _objc_method_description_list *optional_class_methods;
4255 // struct _objc_property_list *instance_properties;
4256 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004257 ProtocolExtensionTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004258 llvm::StructType::create("struct._objc_protocol_extension",
4259 IntTy, MethodDescriptionListPtrTy,
4260 MethodDescriptionListPtrTy, PropertyListPtrTy,
4261 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004262
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004263 // struct _objc_protocol_extension *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004264 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004265
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004266 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004267
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004268 ProtocolTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004269 llvm::StructType::create(VMContext, "struct._objc_protocol");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004270
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004271 ProtocolListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004272 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004273 ProtocolListTy->setBody(llvm::PointerType::getUnqual(ProtocolListTy),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004274 LongTy,
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004275 llvm::ArrayType::get(ProtocolTy, 0),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004276 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004277
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004278 // struct _objc_protocol {
4279 // struct _objc_protocol_extension *isa;
4280 // char *protocol_name;
4281 // struct _objc_protocol **_objc_protocol_list;
4282 // struct _objc_method_description_list *instance_methods;
4283 // struct _objc_method_description_list *class_methods;
4284 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004285 ProtocolTy->setBody(ProtocolExtensionPtrTy, Int8PtrTy,
4286 llvm::PointerType::getUnqual(ProtocolListTy),
4287 MethodDescriptionListPtrTy,
4288 MethodDescriptionListPtrTy,
4289 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004290
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004291 // struct _objc_protocol_list *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004292 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004293
Owen Anderson96e0fc72009-07-29 22:16:19 +00004294 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004295
4296 // Class description structures
4297
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004298 // struct _objc_ivar {
4299 // char *ivar_name;
4300 // char *ivar_type;
4301 // int ivar_offset;
4302 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00004303 IvarTy = llvm::StructType::create("struct._objc_ivar",
4304 Int8PtrTy, Int8PtrTy, IntTy, NULL);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004305
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004306 // struct _objc_ivar_list *
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004307 IvarListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004308 llvm::StructType::create(VMContext, "struct._objc_ivar_list");
Owen Anderson96e0fc72009-07-29 22:16:19 +00004309 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004310
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004311 // struct _objc_method_list *
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004312 MethodListTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004313 llvm::StructType::create(VMContext, "struct._objc_method_list");
Owen Anderson96e0fc72009-07-29 22:16:19 +00004314 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004315
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004316 // struct _objc_class_extension *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004317 ClassExtensionTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004318 llvm::StructType::create("struct._objc_class_extension",
4319 IntTy, Int8PtrTy, PropertyListPtrTy, NULL);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004320 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004321
Chris Lattnerc1c20112011-08-12 17:43:31 +00004322 ClassTy = llvm::StructType::create(VMContext, "struct._objc_class");
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004323
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004324 // struct _objc_class {
4325 // Class isa;
4326 // Class super_class;
4327 // char *name;
4328 // long version;
4329 // long info;
4330 // long instance_size;
4331 // struct _objc_ivar_list *ivars;
4332 // struct _objc_method_list *methods;
4333 // struct _objc_cache *cache;
4334 // struct _objc_protocol_list *protocols;
4335 // char *ivar_layout;
4336 // struct _objc_class_ext *ext;
4337 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004338 ClassTy->setBody(llvm::PointerType::getUnqual(ClassTy),
4339 llvm::PointerType::getUnqual(ClassTy),
4340 Int8PtrTy,
4341 LongTy,
4342 LongTy,
4343 LongTy,
4344 IvarListPtrTy,
4345 MethodListPtrTy,
4346 CachePtrTy,
4347 ProtocolListPtrTy,
4348 Int8PtrTy,
4349 ClassExtensionPtrTy,
4350 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004351
Owen Anderson96e0fc72009-07-29 22:16:19 +00004352 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004353
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004354 // struct _objc_category {
4355 // char *category_name;
4356 // char *class_name;
4357 // struct _objc_method_list *instance_method;
4358 // struct _objc_method_list *class_method;
4359 // uint32_t size; // sizeof(struct _objc_category)
4360 // struct _objc_property_list *instance_properties;// category's @property
4361 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004362 CategoryTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004363 llvm::StructType::create("struct._objc_category",
4364 Int8PtrTy, Int8PtrTy, MethodListPtrTy,
4365 MethodListPtrTy, ProtocolListPtrTy,
4366 IntTy, PropertyListPtrTy, NULL);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00004367
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004368 // Global metadata structures
4369
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004370 // struct _objc_symtab {
4371 // long sel_ref_cnt;
4372 // SEL *refs;
4373 // short cls_def_cnt;
4374 // short cat_def_cnt;
4375 // char *defs[cls_def_cnt + cat_def_cnt];
4376 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004377 SymtabTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004378 llvm::StructType::create("struct._objc_symtab",
4379 LongTy, SelectorPtrTy, ShortTy, ShortTy,
4380 llvm::ArrayType::get(Int8PtrTy, 0), NULL);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004381 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004382
Fariborz Jahaniandb286862009-01-22 00:37:21 +00004383 // struct _objc_module {
4384 // long version;
4385 // long size; // sizeof(struct _objc_module)
4386 // char *name;
4387 // struct _objc_symtab* symtab;
4388 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004389 ModuleTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004390 llvm::StructType::create("struct._objc_module",
4391 LongTy, LongTy, Int8PtrTy, SymtabPtrTy, NULL);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00004392
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004393
Mike Stumpf5408fe2009-05-16 07:57:57 +00004394 // FIXME: This is the size of the setjmp buffer and should be target
4395 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson124526b2008-09-09 10:10:21 +00004396 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004397
Anders Carlsson124526b2008-09-09 10:10:21 +00004398 // Exceptions
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004399 llvm::Type *StackPtrTy = llvm::ArrayType::get(
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00004400 llvm::Type::getInt8PtrTy(VMContext), 4);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004401
4402 ExceptionDataTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004403 llvm::StructType::create("struct._objc_exception_data",
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004404 llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
4405 SetJmpBufferSize),
4406 StackPtrTy, NULL);
Anders Carlsson124526b2008-09-09 10:10:21 +00004407
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00004408}
4409
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004410ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004411 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004412 // struct _method_list_t {
4413 // uint32_t entsize; // sizeof(struct _objc_method)
4414 // uint32_t method_count;
4415 // struct _objc_method method_list[method_count];
4416 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004417 MethodListnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004418 llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
4419 llvm::ArrayType::get(MethodTy, 0), NULL);
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004420 // struct method_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004421 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004422
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004423 // struct _protocol_t {
4424 // id isa; // NULL
4425 // const char * const protocol_name;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004426 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004427 // const struct method_list_t * const instance_methods;
4428 // const struct method_list_t * const class_methods;
4429 // const struct method_list_t *optionalInstanceMethods;
4430 // const struct method_list_t *optionalClassMethods;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004431 // const struct _prop_list_t * properties;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004432 // const uint32_t size; // sizeof(struct _protocol_t)
4433 // const uint32_t flags; // = 0
4434 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004435
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004436 // Holder for struct _protocol_list_t *
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004437 ProtocolListnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004438 llvm::StructType::create(VMContext, "struct._objc_protocol_list");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004439
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004440 ProtocolnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004441 llvm::StructType::create("struct._protocol_t", ObjectPtrTy, Int8PtrTy,
4442 llvm::PointerType::getUnqual(ProtocolListnfABITy),
4443 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
4444 MethodListnfABIPtrTy, MethodListnfABIPtrTy,
4445 PropertyListPtrTy, IntTy, IntTy, NULL);
Daniel Dunbar948e2582009-02-15 07:36:20 +00004446
4447 // struct _protocol_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004448 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004449
Fariborz Jahanianda320092009-01-29 19:24:30 +00004450 // struct _protocol_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004451 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar948e2582009-02-15 07:36:20 +00004452 // struct _protocol_t *[protocol_count];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004453 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004454 ProtocolListnfABITy->setBody(LongTy,
4455 llvm::ArrayType::get(ProtocolnfABIPtrTy, 0),
4456 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004457
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004458 // struct _objc_protocol_list*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004459 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004460
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004461 // struct _ivar_t {
4462 // unsigned long int *offset; // pointer to ivar offset location
4463 // char *name;
4464 // char *type;
4465 // uint32_t alignment;
4466 // uint32_t size;
4467 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004468 IvarnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004469 llvm::StructType::create("struct._ivar_t",
4470 llvm::PointerType::getUnqual(LongTy),
4471 Int8PtrTy, Int8PtrTy, IntTy, IntTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004472
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004473 // struct _ivar_list_t {
4474 // uint32 entsize; // sizeof(struct _ivar_t)
4475 // uint32 count;
4476 // struct _iver_t list[count];
4477 // }
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004478 IvarListnfABITy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004479 llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
4480 llvm::ArrayType::get(IvarnfABITy, 0), NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004481
Owen Anderson96e0fc72009-07-29 22:16:19 +00004482 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004483
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004484 // struct _class_ro_t {
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004485 // uint32_t const flags;
4486 // uint32_t const instanceStart;
4487 // uint32_t const instanceSize;
4488 // uint32_t const reserved; // only when building for 64bit targets
4489 // const uint8_t * const ivarLayout;
4490 // const char *const name;
4491 // const struct _method_list_t * const baseMethods;
4492 // const struct _objc_protocol_list *const baseProtocols;
4493 // const struct _ivar_list_t *const ivars;
4494 // const uint8_t * const weakIvarLayout;
4495 // const struct _prop_list_t * const properties;
4496 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004497
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004498 // FIXME. Add 'reserved' field in 64bit abi mode!
Chris Lattnerc1c20112011-08-12 17:43:31 +00004499 ClassRonfABITy = llvm::StructType::create("struct._class_ro_t",
4500 IntTy, IntTy, IntTy, Int8PtrTy,
4501 Int8PtrTy, MethodListnfABIPtrTy,
4502 ProtocolListnfABIPtrTy,
4503 IvarListnfABIPtrTy,
4504 Int8PtrTy, PropertyListPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004505
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004506 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004507 llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
John McCall0774cb82011-05-15 01:53:33 +00004508 ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
4509 ->getPointerTo();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004510
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004511 // struct _class_t {
4512 // struct _class_t *isa;
4513 // struct _class_t * const superclass;
4514 // void *cache;
4515 // IMP *vtable;
4516 // struct class_ro_t *ro;
4517 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004518
Chris Lattnerc1c20112011-08-12 17:43:31 +00004519 ClassnfABITy = llvm::StructType::create(VMContext, "struct._class_t");
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004520 ClassnfABITy->setBody(llvm::PointerType::getUnqual(ClassnfABITy),
4521 llvm::PointerType::getUnqual(ClassnfABITy),
4522 CachePtrTy,
4523 llvm::PointerType::getUnqual(ImpnfABITy),
4524 llvm::PointerType::getUnqual(ClassRonfABITy),
4525 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004526
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004527 // LLVM for struct _class_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004528 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004529
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004530 // struct _category_t {
4531 // const char * const name;
4532 // struct _class_t *const cls;
4533 // const struct _method_list_t * const instance_methods;
4534 // const struct _method_list_t * const class_methods;
4535 // const struct _protocol_list_t * const protocols;
4536 // const struct _prop_list_t * const properties;
Fariborz Jahanian45c2ba02009-01-23 17:41:22 +00004537 // }
Chris Lattnerc1c20112011-08-12 17:43:31 +00004538 CategorynfABITy = llvm::StructType::create("struct._category_t",
4539 Int8PtrTy, ClassnfABIPtrTy,
4540 MethodListnfABIPtrTy,
4541 MethodListnfABIPtrTy,
4542 ProtocolListnfABIPtrTy,
4543 PropertyListPtrTy,
4544 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004545
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004546 // New types for nonfragile abi messaging.
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004547 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4548 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004549
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004550 // MessageRefTy - LLVM for:
4551 // struct _message_ref_t {
4552 // IMP messenger;
4553 // SEL name;
4554 // };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004555
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004556 // First the clang type for struct _message_ref_t
Abramo Bagnara465d41b2010-05-11 21:36:43 +00004557 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00004558 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00004559 SourceLocation(), SourceLocation(),
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004560 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004561 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith7a614d82011-06-11 17:19:42 +00004562 Ctx.VoidPtrTy, 0, 0, false, false));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004563 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Richard Smith7a614d82011-06-11 17:19:42 +00004564 Ctx.getObjCSelType(), 0, 0, false, false));
Douglas Gregor838db382010-02-11 01:19:42 +00004565 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004566
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004567 MessageRefCTy = Ctx.getTagDeclType(RD);
4568 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4569 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004570
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004571 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004572 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004573
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004574 // SuperMessageRefTy - LLVM for:
4575 // struct _super_message_ref_t {
4576 // SUPER_IMP messenger;
4577 // SEL name;
4578 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004579 SuperMessageRefTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004580 llvm::StructType::create("struct._super_message_ref_t",
4581 ImpnfABITy, SelectorPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004582
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004583 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004584 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
Fariborz Jahanian9d96bce2011-06-22 20:21:51 +00004585
Daniel Dunbare588b992009-03-01 04:46:24 +00004586
4587 // struct objc_typeinfo {
4588 // const void** vtable; // objc_ehtype_vtable + 2
4589 // const char* name; // c++ typeinfo string
4590 // Class cls;
4591 // };
Chris Lattner9cbe4f02011-07-09 17:41:47 +00004592 EHTypeTy =
Chris Lattnerc1c20112011-08-12 17:43:31 +00004593 llvm::StructType::create("struct._objc_typeinfo",
4594 llvm::PointerType::getUnqual(Int8PtrTy),
4595 Int8PtrTy, ClassnfABIPtrTy, NULL);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004596 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00004597}
4598
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004599llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004600 FinishNonFragileABIModule();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004601
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004602 return NULL;
4603}
4604
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004605void CGObjCNonFragileABIMac::AddModuleClassList(const
4606 std::vector<llvm::GlobalValue*>
4607 &Container,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004608 const char *SymbolName,
4609 const char *SectionName) {
4610 unsigned NumClasses = Container.size();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004611
Daniel Dunbar463b8762009-05-15 21:48:48 +00004612 if (!NumClasses)
4613 return;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004614
Daniel Dunbar463b8762009-05-15 21:48:48 +00004615 std::vector<llvm::Constant*> Symbols(NumClasses);
4616 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00004617 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar463b8762009-05-15 21:48:48 +00004618 ObjCTypes.Int8PtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004619 llvm::Constant* Init =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004620 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004621 NumClasses),
4622 Symbols);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004623
Daniel Dunbar463b8762009-05-15 21:48:48 +00004624 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00004625 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004626 llvm::GlobalValue::InternalLinkage,
4627 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00004628 SymbolName);
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004629 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Daniel Dunbar463b8762009-05-15 21:48:48 +00004630 GV->setSection(SectionName);
Chris Lattnerad64e022009-07-17 23:57:13 +00004631 CGM.AddUsedGlobal(GV);
Daniel Dunbar463b8762009-05-15 21:48:48 +00004632}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004633
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004634void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4635 // nonfragile abi has no module definition.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004636
Daniel Dunbar463b8762009-05-15 21:48:48 +00004637 // Build list of all implemented class addresses in array
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004638 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004639 AddModuleClassList(DefinedClasses,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004640 "\01L_OBJC_LABEL_CLASS_$",
4641 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004642
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004643 for (unsigned i = 0; i < DefinedClasses.size(); i++) {
4644 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
4645 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4646 continue;
4647 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004648 }
4649
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004650 for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
4651 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
4652 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4653 continue;
4654 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4655 }
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004656
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004657 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004658 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4659 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004660
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004661 // Build list of all implemented category addresses in array
4662 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004663 AddModuleClassList(DefinedCategories,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004664 "\01L_OBJC_LABEL_CATEGORY_$",
4665 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004666 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004667 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4668 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004669
Daniel Dunbarfce176b2010-04-25 20:39:01 +00004670 EmitImageInfo();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004671}
4672
John McCall944c8432011-05-14 03:10:52 +00004673/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
4674/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004675/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004676/// message dispatch call for all the rest.
John McCall944c8432011-05-14 03:10:52 +00004677bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
4678 // At various points we've experimented with using vtable-based
4679 // dispatch for all methods.
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004680 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
4681 default:
John McCall944c8432011-05-14 03:10:52 +00004682 llvm_unreachable("Invalid dispatch method!");
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004683 case CodeGenOptions::Legacy:
Fariborz Jahanian776dbf92010-04-19 17:53:30 +00004684 return false;
John McCall944c8432011-05-14 03:10:52 +00004685 case CodeGenOptions::NonLegacy:
4686 return true;
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004687 case CodeGenOptions::Mixed:
4688 break;
4689 }
4690
4691 // If so, see whether this selector is in the white-list of things which must
4692 // use the new dispatch convention. We lazily build a dense set for this.
John McCall944c8432011-05-14 03:10:52 +00004693 if (VTableDispatchMethods.empty()) {
4694 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
4695 VTableDispatchMethods.insert(GetNullarySelector("class"));
4696 VTableDispatchMethods.insert(GetNullarySelector("self"));
4697 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
4698 VTableDispatchMethods.insert(GetNullarySelector("length"));
4699 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004700
John McCall944c8432011-05-14 03:10:52 +00004701 // These are vtable-based if GC is disabled.
4702 // Optimistically use vtable dispatch for hybrid compiles.
Douglas Gregore289d812011-09-13 17:21:33 +00004703 if (CGM.getLangOptions().getGC() != LangOptions::GCOnly) {
John McCall944c8432011-05-14 03:10:52 +00004704 VTableDispatchMethods.insert(GetNullarySelector("retain"));
4705 VTableDispatchMethods.insert(GetNullarySelector("release"));
4706 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
4707 }
4708
4709 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
4710 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
4711 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
4712 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
4713 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
4714 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
4715 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
4716
4717 // These are vtable-based if GC is enabled.
4718 // Optimistically use vtable dispatch for hybrid compiles.
Douglas Gregore289d812011-09-13 17:21:33 +00004719 if (CGM.getLangOptions().getGC() != LangOptions::NonGC) {
John McCall944c8432011-05-14 03:10:52 +00004720 VTableDispatchMethods.insert(GetNullarySelector("hash"));
4721 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
4722
4723 // "countByEnumeratingWithState:objects:count"
4724 IdentifierInfo *KeyIdents[] = {
4725 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4726 &CGM.getContext().Idents.get("objects"),
4727 &CGM.getContext().Idents.get("count")
4728 };
4729 VTableDispatchMethods.insert(
4730 CGM.getContext().Selectors.getSelector(3, KeyIdents));
4731 }
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004732 }
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004733
John McCall944c8432011-05-14 03:10:52 +00004734 return VTableDispatchMethods.count(Sel);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004735}
4736
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004737// Metadata flags
4738enum MetaDataDlags {
4739 CLS = 0x0,
4740 CLS_META = 0x1,
4741 CLS_ROOT = 0x2,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004742 OBJC2_CLS_HIDDEN = 0x10,
John McCallf85e1932011-06-15 23:02:42 +00004743 CLS_EXCEPTION = 0x20,
4744
4745 /// (Obsolete) ARC-specific: this class has a .release_ivars method
4746 CLS_HAS_IVAR_RELEASER = 0x40,
4747 /// class was compiled with -fobjc-arr
4748 CLS_COMPILED_BY_ARC = 0x80 // (1<<7)
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004749};
4750/// BuildClassRoTInitializer - generate meta-data for:
4751/// struct _class_ro_t {
4752/// uint32_t const flags;
4753/// uint32_t const instanceStart;
4754/// uint32_t const instanceSize;
4755/// uint32_t const reserved; // only when building for 64bit targets
4756/// const uint8_t * const ivarLayout;
4757/// const char *const name;
4758/// const struct _method_list_t * const baseMethods;
Fariborz Jahanianda320092009-01-29 19:24:30 +00004759/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004760/// const struct _ivar_list_t *const ivars;
4761/// const uint8_t * const weakIvarLayout;
4762/// const struct _prop_list_t * const properties;
4763/// }
4764///
4765llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004766 unsigned flags,
4767 unsigned InstanceStart,
4768 unsigned InstanceSize,
4769 const ObjCImplementationDecl *ID) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004770 std::string ClassName = ID->getNameAsString();
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00004771 llvm::Constant *Values[10]; // 11 for 64bit targets!
John McCallf85e1932011-06-15 23:02:42 +00004772
4773 if (CGM.getLangOptions().ObjCAutoRefCount)
4774 flags |= CLS_COMPILED_BY_ARC;
4775
Owen Anderson4a28d5d2009-07-24 23:12:58 +00004776 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4777 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4778 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004779 // FIXME. For 64bit targets add 0 here.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004780 Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4781 : BuildIvarLayout(ID, true);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004782 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004783 // const struct _method_list_t * const baseMethods;
4784 std::vector<llvm::Constant*> Methods;
4785 std::string MethodListName("\01l_OBJC_$_");
4786 if (flags & CLS_META) {
4787 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004788 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004789 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004790 // Class methods should always be defined.
4791 Methods.push_back(GetMethodConstant(*i));
4792 }
4793 } else {
4794 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004795 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004796 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004797 // Instance methods should always be defined.
4798 Methods.push_back(GetMethodConstant(*i));
4799 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004800 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004801 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004802 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004803
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004804 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4805 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004806
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004807 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4808 if (llvm::Constant *C = GetMethodConstant(MD))
4809 Methods.push_back(C);
4810 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4811 if (llvm::Constant *C = GetMethodConstant(MD))
4812 Methods.push_back(C);
4813 }
4814 }
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004815 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004816 Values[ 5] = EmitMethodList(MethodListName,
4817 "__DATA, __objc_const", Methods);
4818
Fariborz Jahanianda320092009-01-29 19:24:30 +00004819 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4820 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004821 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004822 + OID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00004823 OID->all_referenced_protocol_begin(),
4824 OID->all_referenced_protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004825
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00004826 if (flags & CLS_META)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004827 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00004828 else
4829 Values[ 7] = EmitIvarList(ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004830 Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4831 : BuildIvarLayout(ID, false);
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00004832 if (flags & CLS_META)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004833 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00004834 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004835 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4836 ID, ID->getClassInterface(), ObjCTypes);
Owen Anderson08e25242009-07-27 22:29:56 +00004837 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004838 Values);
4839 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004840 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
4841 llvm::GlobalValue::InternalLinkage,
4842 Init,
4843 (flags & CLS_META) ?
4844 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4845 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00004846 CLASS_RO_GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004847 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00004848 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004849 return CLASS_RO_GV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00004850
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004851}
4852
4853/// BuildClassMetaData - This routine defines that to-level meta-data
4854/// for the given ClassName for:
4855/// struct _class_t {
4856/// struct _class_t *isa;
4857/// struct _class_t * const superclass;
4858/// void *cache;
4859/// IMP *vtable;
4860/// struct class_ro_t *ro;
4861/// }
4862///
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004863llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004864 std::string &ClassName,
4865 llvm::Constant *IsAGV,
4866 llvm::Constant *SuperClassGV,
4867 llvm::Constant *ClassRoGV,
4868 bool HiddenVisibility) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00004869 llvm::Constant *Values[] = {
4870 IsAGV,
4871 SuperClassGV,
4872 ObjCEmptyCacheVar, // &ObjCEmptyCacheVar
4873 ObjCEmptyVtableVar, // &ObjCEmptyVtableVar
4874 ClassRoGV // &CLASS_RO_GV
4875 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004876 if (!Values[1])
4877 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004878 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004879 Values);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004880 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4881 GV->setInitializer(Init);
Fariborz Jahaniandd0db2a2009-01-31 01:07:39 +00004882 GV->setSection("__DATA, __objc_data");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00004883 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004884 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004885 if (HiddenVisibility)
4886 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004887 return GV;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004888}
4889
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004890bool
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00004891CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004892 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004893}
4894
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00004895void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00004896 uint32_t &InstanceStart,
4897 uint32_t &InstanceSize) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004898 const ASTRecordLayout &RL =
Daniel Dunbarb4c79e02009-05-04 21:26:30 +00004899 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004900
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00004901 // InstanceSize is really instance end.
Ken Dyckec299032011-02-11 02:20:09 +00004902 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00004903
4904 // If there are no fields, the start is the same as the end.
4905 if (!RL.getFieldCount())
4906 InstanceStart = InstanceSize;
4907 else
Ken Dyckfb67ccd2011-04-14 00:43:09 +00004908 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbarb02532a2009-04-19 23:41:48 +00004909}
4910
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004911void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
4912 std::string ClassName = ID->getNameAsString();
4913 if (!ObjCEmptyCacheVar) {
4914 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004915 CGM.getModule(),
4916 ObjCTypes.CacheTy,
4917 false,
4918 llvm::GlobalValue::ExternalLinkage,
4919 0,
4920 "_objc_empty_cache");
4921
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004922 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004923 CGM.getModule(),
4924 ObjCTypes.ImpnfABITy,
4925 false,
4926 llvm::GlobalValue::ExternalLinkage,
4927 0,
4928 "_objc_empty_vtable");
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004929 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004930 assert(ID->getClassInterface() &&
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004931 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbar6c1aac82009-04-20 20:18:54 +00004932 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004933 uint32_t InstanceStart =
Duncan Sands9408c452009-05-09 07:08:47 +00004934 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004935 uint32_t InstanceSize = InstanceStart;
4936 uint32_t flags = CLS_META;
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00004937 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4938 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004939
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004940 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004941
4942 bool classIsHidden =
John McCall1fb0caa2010-10-22 21:05:15 +00004943 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004944 if (classIsHidden)
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004945 flags |= OBJC2_CLS_HIDDEN;
John McCallf85e1932011-06-15 23:02:42 +00004946 if (ID->hasCXXStructors())
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00004947 flags |= eClassFlags_ABI2_HasCXXStructors;
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004948 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004949 // class is root
4950 flags |= CLS_ROOT;
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004951 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004952 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004953 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004954 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004955 const ObjCInterfaceDecl *Root = ID->getClassInterface();
4956 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4957 Root = Super;
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004958 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004959 if (Root->isWeakImported())
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004960 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004961 // work on super class metadata symbol.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004962 std::string SuperClassName =
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004963 ObjCMetaClassName +
4964 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004965 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004966 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004967 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004968 }
4969 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4970 InstanceStart,
4971 InstanceSize,ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004972 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004973 llvm::GlobalVariable *MetaTClass =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004974 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4975 classIsHidden);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004976 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00004977
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004978 // Metadata for the class
4979 flags = CLS;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004980 if (classIsHidden)
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004981 flags |= OBJC2_CLS_HIDDEN;
John McCallf85e1932011-06-15 23:02:42 +00004982 if (ID->hasCXXStructors())
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00004983 flags |= eClassFlags_ABI2_HasCXXStructors;
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004984
Douglas Gregor68584ed2009-06-18 16:11:24 +00004985 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004986 flags |= CLS_EXCEPTION;
4987
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004988 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004989 flags |= CLS_ROOT;
4990 SuperClassGV = 0;
Chris Lattnerb7b58b12009-04-19 06:02:28 +00004991 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004992 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004993 std::string RootClassName =
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004994 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004995 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004996 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004997 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004998 }
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00004999 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005000 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00005001 InstanceStart,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005002 InstanceSize,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00005003 ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005004
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005005 TClassName = ObjCClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005006 llvm::GlobalVariable *ClassMD =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005007 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5008 classIsHidden);
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00005009 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005010
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005011 // Determine if this class is also "non-lazy".
5012 if (ImplementationIsNonLazy(ID))
5013 DefinedNonLazyClasses.push_back(ClassMD);
5014
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005015 // Force the definition of the EHType if necessary.
5016 if (flags & CLS_EXCEPTION)
5017 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00005018 // Make sure method definition entries are all clear for next implementation.
5019 MethodDefinitions.clear();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005020}
5021
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005022/// GenerateProtocolRef - This routine is called to generate code for
5023/// a protocol reference expression; as in:
5024/// @code
5025/// @protocol(Proto1);
5026/// @endcode
5027/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5028/// which will hold address of the protocol meta-data.
5029///
5030llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005031 const ObjCProtocolDecl *PD) {
5032
Fariborz Jahanian960cd062009-04-10 18:47:34 +00005033 // This routine is called for @protocol only. So, we must build definition
5034 // of protocol's meta-data (not a reference to it!)
5035 //
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005036 llvm::Constant *Init =
5037 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5038 ObjCTypes.ExternalProtocolPtrTy);
5039
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005040 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar4087f272010-08-17 22:39:59 +00005041 ProtocolName += PD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005042
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005043 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5044 if (PTGV)
Benjamin Kramer578faa82011-09-27 21:06:10 +00005045 return Builder.CreateLoad(PTGV);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005046 PTGV = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005047 CGM.getModule(),
5048 Init->getType(), false,
5049 llvm::GlobalValue::WeakAnyLinkage,
5050 Init,
5051 ProtocolName);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005052 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5053 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005054 CGM.AddUsedGlobal(PTGV);
Benjamin Kramer578faa82011-09-27 21:06:10 +00005055 return Builder.CreateLoad(PTGV);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005056}
5057
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005058/// GenerateCategory - Build metadata for a category implementation.
5059/// struct _category_t {
5060/// const char * const name;
5061/// struct _class_t *const cls;
5062/// const struct _method_list_t * const instance_methods;
5063/// const struct _method_list_t * const class_methods;
5064/// const struct _protocol_list_t * const protocols;
5065/// const struct _prop_list_t * const properties;
5066/// }
5067///
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005068void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005069 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005070 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005071 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5072 "_$_" + OCD->getNameAsString());
5073 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005074 Interface->getNameAsString());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005075
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005076 llvm::Constant *Values[6];
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005077 Values[0] = GetClassName(OCD->getIdentifier());
5078 // meta-class entry symbol
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005079 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005080 if (Interface->isWeakImported())
Fariborz Jahanian2cdcc4c2009-11-17 22:02:21 +00005081 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5082
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005083 Values[1] = ClassGV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005084 std::vector<llvm::Constant*> Methods;
5085 std::string MethodListName(Prefix);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005086 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005087 "_$_" + OCD->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005088
5089 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005090 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005091 // Instance methods should always be defined.
5092 Methods.push_back(GetMethodConstant(*i));
5093 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005094
5095 Values[2] = EmitMethodList(MethodListName,
5096 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005097 Methods);
5098
5099 MethodListName = Prefix;
5100 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5101 OCD->getNameAsString();
5102 Methods.clear();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005103 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005104 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005105 // Class methods should always be defined.
5106 Methods.push_back(GetMethodConstant(*i));
5107 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005108
5109 Values[3] = EmitMethodList(MethodListName,
5110 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005111 Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005112 const ObjCCategoryDecl *Category =
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00005113 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005114 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005115 llvm::SmallString<256> ExtName;
5116 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5117 << OCD->getName();
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005118 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005119 + Interface->getName() + "_$_"
5120 + Category->getName(),
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005121 Category->protocol_begin(),
5122 Category->protocol_end());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005123 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5124 OCD, Category, ObjCTypes);
Mike Stumpb3589f42009-07-30 22:28:39 +00005125 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00005126 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5127 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005128 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005129
5130 llvm::Constant *Init =
5131 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005132 Values);
5133 llvm::GlobalVariable *GCATV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005134 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005135 false,
5136 llvm::GlobalValue::InternalLinkage,
5137 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005138 ExtCatName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005139 GCATV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005140 CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005141 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerad64e022009-07-17 23:57:13 +00005142 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005143 DefinedCategories.push_back(GCATV);
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005144
5145 // Determine if this category is also "non-lazy".
5146 if (ImplementationIsNonLazy(OCD))
5147 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00005148 // method definition entries must be clear for next implementation.
5149 MethodDefinitions.clear();
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005150}
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005151
5152/// GetMethodConstant - Return a struct objc_method constant for the
5153/// given method if it has been defined. The result is null if the
5154/// method has not been defined. The return value has type MethodPtrTy.
5155llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005156 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00005157 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005158 if (!Fn)
5159 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005160
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005161 llvm::Constant *Method[] = {
Owen Anderson3c4972d2009-07-29 18:54:39 +00005162 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005163 ObjCTypes.SelectorPtrTy),
5164 GetMethodVarType(MD),
5165 llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy)
5166 };
Owen Anderson08e25242009-07-27 22:29:56 +00005167 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005168}
5169
5170/// EmitMethodList - Build meta-data for method declarations
5171/// struct _method_list_t {
5172/// uint32_t entsize; // sizeof(struct _objc_method)
5173/// uint32_t method_count;
5174/// struct _objc_method method_list[method_count];
5175/// }
5176///
Chris Lattner5f9e2722011-07-23 10:55:15 +00005177llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(Twine Name,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005178 const char *Section,
5179 const ConstantVector &Methods) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005180 // Return null for empty list.
5181 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00005182 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005183
Chris Lattnerc5cbb902011-06-20 04:01:35 +00005184 llvm::Constant *Values[3];
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005185 // sizeof(struct _objc_method)
Duncan Sands9408c452009-05-09 07:08:47 +00005186 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005187 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005188 // method_count
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005189 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00005190 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005191 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00005192 Values[2] = llvm::ConstantArray::get(AT, Methods);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00005193 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005194
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005195 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005196 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Chris Lattnerc5cbb902011-06-20 04:01:35 +00005197 llvm::GlobalValue::InternalLinkage, Init, Name);
5198 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005199 GV->setSection(Section);
Chris Lattnerad64e022009-07-17 23:57:13 +00005200 CGM.AddUsedGlobal(GV);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00005201 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005202}
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005203
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005204/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5205/// the given ivar.
Daniel Dunbare83be122010-04-02 21:14:02 +00005206llvm::GlobalVariable *
5207CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5208 const ObjCIvarDecl *Ivar) {
5209 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbara81419d2009-05-05 00:36:57 +00005210 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregor6ab35242009-04-09 21:40:53 +00005211 '.' + Ivar->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005212 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005213 CGM.getModule().getGlobalVariable(Name);
5214 if (!IvarOffsetGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005215 IvarOffsetGV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005216 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005217 false,
5218 llvm::GlobalValue::ExternalLinkage,
5219 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00005220 Name);
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005221 return IvarOffsetGV;
5222}
5223
Daniel Dunbare83be122010-04-02 21:14:02 +00005224llvm::Constant *
5225CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5226 const ObjCIvarDecl *Ivar,
5227 unsigned long int Offset) {
Daniel Dunbar737c5022009-04-19 00:44:02 +00005228 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005229 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar737c5022009-04-19 00:44:02 +00005230 Offset));
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005231 IvarOffsetGV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005232 CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbar737c5022009-04-19 00:44:02 +00005233
Mike Stumpf5408fe2009-05-16 07:57:57 +00005234 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
5235 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbar737c5022009-04-19 00:44:02 +00005236 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5237 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall1fb0caa2010-10-22 21:05:15 +00005238 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00005239 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar04d40782009-04-14 06:00:08 +00005240 else
Fariborz Jahanian77c9fd22009-04-06 18:30:00 +00005241 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendling1f382512011-05-04 21:37:25 +00005242 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005243 return IvarOffsetGV;
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005244}
5245
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005246/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar11394522009-04-18 08:51:00 +00005247/// implementation. The return value has type
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005248/// IvarListnfABIPtrTy.
5249/// struct _ivar_t {
5250/// unsigned long int *offset; // pointer to ivar offset location
5251/// char *name;
5252/// char *type;
5253/// uint32_t alignment;
5254/// uint32_t size;
5255/// }
5256/// struct _ivar_list_t {
5257/// uint32 entsize; // sizeof(struct _ivar_t)
5258/// uint32 count;
5259/// struct _iver_t list[count];
5260/// }
5261///
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00005262
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005263llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005264 const ObjCImplementationDecl *ID) {
5265
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005266 std::vector<llvm::Constant*> Ivars;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005267
Jordy Rosedb8264e2011-07-22 02:08:32 +00005268 const ObjCInterfaceDecl *OID = ID->getClassInterface();
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005269 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005270
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005271 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005272
Jordy Rosedb8264e2011-07-22 02:08:32 +00005273 for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin();
Fariborz Jahanianbf9eb882011-06-28 18:05:25 +00005274 IVD; IVD = IVD->getNextIvar()) {
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00005275 // Ignore unnamed bit-fields.
5276 if (!IVD->getDeclName())
5277 continue;
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005278 llvm::Constant *Ivar[5];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005279 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005280 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00005281 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5282 Ivar[2] = GetMethodVarType(IVD);
Chris Lattner2acc6e32011-07-18 04:24:23 +00005283 llvm::Type *FieldTy =
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00005284 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Duncan Sands9408c452009-05-09 07:08:47 +00005285 unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005286 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005287 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005288 Align = llvm::Log2_32(Align);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005289 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbar91636d62009-04-20 00:33:43 +00005290 // NOTE. Size of a bitfield does not match gcc's, because of the
5291 // way bitfields are treated special in each. But I am told that
5292 // 'size' for bitfield ivars is ignored by the runtime so it does
5293 // not matter. If it matters, there is enough info to get the
5294 // bitfield right!
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005295 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson08e25242009-07-27 22:29:56 +00005296 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005297 }
5298 // Return null for empty list.
5299 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00005300 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00005301
5302 llvm::Constant *Values[3];
Duncan Sands9408c452009-05-09 07:08:47 +00005303 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005304 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5305 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00005306 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005307 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00005308 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Chris Lattnerc5cbb902011-06-20 04:01:35 +00005309 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005310 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5311 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005312 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005313 llvm::GlobalValue::InternalLinkage,
5314 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005315 Prefix + OID->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005316 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005317 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005318 GV->setSection("__DATA, __objc_const");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005319
Chris Lattnerad64e022009-07-17 23:57:13 +00005320 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005321 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005322}
5323
5324llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005325 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005326 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005327
Fariborz Jahanianda320092009-01-29 19:24:30 +00005328 if (!Entry) {
5329 // We use the initializer as a marker of whether this is a forward
5330 // reference or not. At module finalization we add the empty
5331 // contents for protocols which were referenced but never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005332 Entry =
5333 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5334 llvm::GlobalValue::ExternalLinkage,
5335 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005336 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianda320092009-01-29 19:24:30 +00005337 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00005338 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005339
Fariborz Jahanianda320092009-01-29 19:24:30 +00005340 return Entry;
5341}
5342
5343/// GetOrEmitProtocol - Generate the protocol meta-data:
5344/// @code
5345/// struct _protocol_t {
5346/// id isa; // NULL
5347/// const char * const protocol_name;
5348/// const struct _protocol_list_t * protocol_list; // super protocols
5349/// const struct method_list_t * const instance_methods;
5350/// const struct method_list_t * const class_methods;
5351/// const struct method_list_t *optionalInstanceMethods;
5352/// const struct method_list_t *optionalClassMethods;
5353/// const struct _prop_list_t * properties;
5354/// const uint32_t size; // sizeof(struct _protocol_t)
5355/// const uint32_t flags; // = 0
5356/// }
5357/// @endcode
5358///
5359
5360llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005361 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005362 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005363
Fariborz Jahanianda320092009-01-29 19:24:30 +00005364 // Early exit if a defining object has already been generated.
5365 if (Entry && Entry->hasInitializer())
5366 return Entry;
5367
Fariborz Jahanianda320092009-01-29 19:24:30 +00005368 // Construct method lists.
5369 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5370 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005371 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005372 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005373 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005374 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00005375 if (!C)
5376 return GetOrEmitProtocolRef(PD);
5377
Fariborz Jahanianda320092009-01-29 19:24:30 +00005378 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5379 OptInstanceMethods.push_back(C);
5380 } else {
5381 InstanceMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005382 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00005383 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005384
5385 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005386 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005387 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005388 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00005389 if (!C)
5390 return GetOrEmitProtocolRef(PD);
5391
Fariborz Jahanianda320092009-01-29 19:24:30 +00005392 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5393 OptClassMethods.push_back(C);
5394 } else {
5395 ClassMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005396 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00005397 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005398
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005399 llvm::Constant *Values[10];
Fariborz Jahanianda320092009-01-29 19:24:30 +00005400 // isa is NULL
Owen Andersonc9c88b42009-07-31 20:28:54 +00005401 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005402 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005403 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5404 PD->protocol_begin(),
5405 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005406
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005407 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005408 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005409 "__DATA, __objc_const",
5410 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005411 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005412 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005413 "__DATA, __objc_const",
5414 ClassMethods);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005415 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005416 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005417 "__DATA, __objc_const",
5418 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005419 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005420 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005421 "__DATA, __objc_const",
5422 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005423 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005424 0, PD, ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005425 uint32_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00005426 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005427 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Andersonc9c88b42009-07-31 20:28:54 +00005428 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005429 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanianda320092009-01-29 19:24:30 +00005430 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005431
Fariborz Jahanianda320092009-01-29 19:24:30 +00005432 if (Entry) {
5433 // Already created, fix the linkage and update the initializer.
Mike Stump286acbd2009-03-07 16:33:28 +00005434 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005435 Entry->setInitializer(Init);
5436 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005437 Entry =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005438 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
5439 false, llvm::GlobalValue::WeakAnyLinkage, Init,
5440 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005441 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005442 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanianda320092009-01-29 19:24:30 +00005443 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00005444 }
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005445 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005446 CGM.AddUsedGlobal(Entry);
5447
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005448 // Use this protocol meta-data to build protocol list table in section
5449 // __DATA, __objc_protolist
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005450 llvm::GlobalVariable *PTGV =
5451 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
5452 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
5453 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005454 PTGV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005455 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbar0bf21992009-04-15 02:56:18 +00005456 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005457 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005458 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005459 return Entry;
5460}
5461
5462/// EmitProtocolList - Generate protocol list meta-data:
5463/// @code
5464/// struct _protocol_list_t {
5465/// long protocol_count; // Note, this is 32/64 bit
5466/// struct _protocol_t[protocol_count];
5467/// }
5468/// @endcode
5469///
5470llvm::Constant *
Chris Lattner5f9e2722011-07-23 10:55:15 +00005471CGObjCNonFragileABIMac::EmitProtocolList(Twine Name,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005472 ObjCProtocolDecl::protocol_iterator begin,
5473 ObjCProtocolDecl::protocol_iterator end) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005474 std::vector<llvm::Constant*> ProtocolRefs;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005475
Fariborz Jahanianda320092009-01-29 19:24:30 +00005476 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005477 if (begin == end)
Owen Andersonc9c88b42009-07-31 20:28:54 +00005478 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005479
Daniel Dunbar948e2582009-02-15 07:36:20 +00005480 // FIXME: We shouldn't need to do this lookup here, should we?
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005481 llvm::SmallString<256> TmpName;
5482 Name.toVector(TmpName);
5483 llvm::GlobalVariable *GV =
5484 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005485 if (GV)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005486 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005487
Daniel Dunbar948e2582009-02-15 07:36:20 +00005488 for (; begin != end; ++begin)
5489 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5490
Fariborz Jahanianda320092009-01-29 19:24:30 +00005491 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00005492 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005493 ObjCTypes.ProtocolnfABIPtrTy));
5494
Chris Lattnerc5cbb902011-06-20 04:01:35 +00005495 llvm::Constant *Values[2];
Owen Andersona1cf15f2009-07-14 23:10:40 +00005496 Values[0] =
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005497 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005498 Values[1] =
Owen Anderson7db6d832009-07-28 18:33:04 +00005499 llvm::ConstantArray::get(
Owen Anderson96e0fc72009-07-29 22:16:19 +00005500 llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005501 ProtocolRefs.size()),
5502 ProtocolRefs);
5503
Chris Lattnerc5cbb902011-06-20 04:01:35 +00005504 llvm::Constant *Init = llvm::ConstantStruct::getAnon(Values);
Owen Anderson1c431b32009-07-08 19:05:04 +00005505 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanianda320092009-01-29 19:24:30 +00005506 llvm::GlobalValue::InternalLinkage,
Chris Lattnerc5cbb902011-06-20 04:01:35 +00005507 Init, Name);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005508 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005509 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005510 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Chris Lattnerad64e022009-07-17 23:57:13 +00005511 CGM.AddUsedGlobal(GV);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005512 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar948e2582009-02-15 07:36:20 +00005513 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005514}
5515
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005516/// GetMethodDescriptionConstant - This routine build following meta-data:
5517/// struct _objc_method {
5518/// SEL _cmd;
5519/// char *method_type;
5520/// char *_imp;
5521/// }
5522
5523llvm::Constant *
5524CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00005525 llvm::Constant *Desc[3];
Owen Andersona1cf15f2009-07-14 23:10:40 +00005526 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005527 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5528 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005529 Desc[1] = GetMethodVarType(MD);
Douglas Gregorf968d832011-05-27 01:19:52 +00005530 if (!Desc[1])
5531 return 0;
5532
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005533 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00005534 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005535 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005536}
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005537
5538/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
5539/// This code gen. amounts to generating code for:
5540/// @code
5541/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
5542/// @encode
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005543///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00005544LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall506b57e2010-05-17 21:00:27 +00005545 CodeGen::CodeGenFunction &CGF,
5546 QualType ObjectTy,
5547 llvm::Value *BaseValue,
5548 const ObjCIvarDecl *Ivar,
5549 unsigned CVRQualifiers) {
5550 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00005551 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5552 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005553}
5554
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00005555llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005556 CodeGen::CodeGenFunction &CGF,
5557 const ObjCInterfaceDecl *Interface,
5558 const ObjCIvarDecl *Ivar) {
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005559 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00005560}
5561
John McCallb1e81442011-05-13 23:16:18 +00005562static void appendSelectorForMessageRefTable(std::string &buffer,
5563 Selector selector) {
5564 if (selector.isUnarySelector()) {
5565 buffer += selector.getNameForSlot(0);
5566 return;
5567 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005568
John McCallb1e81442011-05-13 23:16:18 +00005569 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
5570 buffer += selector.getNameForSlot(i);
5571 buffer += '_';
5572 }
5573}
5574
John McCall944c8432011-05-14 03:10:52 +00005575/// Emit a "v-table" message send. We emit a weak hidden-visibility
5576/// struct, initially containing the selector pointer and a pointer to
5577/// a "fixup" variant of the appropriate objc_msgSend. To call, we
5578/// load and call the function pointer, passing the address of the
5579/// struct as the second parameter. The runtime determines whether
5580/// the selector is currently emitted using vtable dispatch; if so, it
5581/// substitutes a stub function which simply tail-calls through the
5582/// appropriate vtable slot, and if not, it substitues a stub function
5583/// which tail-calls objc_msgSend. Both stubs adjust the selector
5584/// argument to correctly point to the selector.
5585RValue
5586CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
5587 ReturnValueSlot returnSlot,
5588 QualType resultType,
5589 Selector selector,
5590 llvm::Value *arg0,
5591 QualType arg0Type,
5592 bool isSuper,
5593 const CallArgList &formalArgs,
5594 const ObjCMethodDecl *method) {
John McCallb1e81442011-05-13 23:16:18 +00005595 // Compute the actual arguments.
5596 CallArgList args;
5597
John McCall944c8432011-05-14 03:10:52 +00005598 // First argument: the receiver / super-call structure.
John McCallb1e81442011-05-13 23:16:18 +00005599 if (!isSuper)
John McCall944c8432011-05-14 03:10:52 +00005600 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
5601 args.add(RValue::get(arg0), arg0Type);
John McCallb1e81442011-05-13 23:16:18 +00005602
John McCall944c8432011-05-14 03:10:52 +00005603 // Second argument: a pointer to the message ref structure. Leave
5604 // the actual argument value blank for now.
John McCallb1e81442011-05-13 23:16:18 +00005605 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
5606
5607 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
5608
5609 const CGFunctionInfo &fnInfo =
5610 CGM.getTypes().getFunctionInfo(resultType, args,
5611 FunctionType::ExtInfo());
5612
John McCallcba681a2011-05-14 21:12:11 +00005613 NullReturnState nullReturn;
5614
John McCall944c8432011-05-14 03:10:52 +00005615 // Find the function to call and the mangled name for the message
5616 // ref structure. Using a different mangled name wouldn't actually
5617 // be a problem; it would just be a waste.
5618 //
5619 // The runtime currently never uses vtable dispatch for anything
5620 // except normal, non-super message-sends.
5621 // FIXME: don't use this for that.
John McCallb1e81442011-05-13 23:16:18 +00005622 llvm::Constant *fn = 0;
5623 std::string messageRefName("\01l_");
5624 if (CGM.ReturnTypeUsesSRet(fnInfo)) {
John McCallb1e81442011-05-13 23:16:18 +00005625 if (isSuper) {
5626 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5627 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005628 } else {
John McCallcba681a2011-05-14 21:12:11 +00005629 nullReturn.init(CGF, arg0);
John McCallb1e81442011-05-13 23:16:18 +00005630 fn = ObjCTypes.getMessageSendStretFixupFn();
5631 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005632 }
John McCallb1e81442011-05-13 23:16:18 +00005633 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
5634 fn = ObjCTypes.getMessageSendFpretFixupFn();
5635 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stumpb3589f42009-07-30 22:28:39 +00005636 } else {
John McCallb1e81442011-05-13 23:16:18 +00005637 if (isSuper) {
5638 fn = ObjCTypes.getMessageSendSuper2FixupFn();
5639 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005640 } else {
John McCallb1e81442011-05-13 23:16:18 +00005641 fn = ObjCTypes.getMessageSendFixupFn();
5642 messageRefName += "objc_msgSend_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005643 }
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005644 }
John McCallb1e81442011-05-13 23:16:18 +00005645 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5646 messageRefName += '_';
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005647
John McCallb1e81442011-05-13 23:16:18 +00005648 // Append the selector name, except use underscores anywhere we
5649 // would have used colons.
5650 appendSelectorForMessageRefTable(messageRefName, selector);
5651
5652 llvm::GlobalVariable *messageRef
5653 = CGM.getModule().getGlobalVariable(messageRefName);
5654 if (!messageRef) {
John McCall944c8432011-05-14 03:10:52 +00005655 // Build the message ref structure.
John McCallb1e81442011-05-13 23:16:18 +00005656 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
Chris Lattnerc5cbb902011-06-20 04:01:35 +00005657 llvm::Constant *init = llvm::ConstantStruct::getAnon(values);
John McCallb1e81442011-05-13 23:16:18 +00005658 messageRef = new llvm::GlobalVariable(CGM.getModule(),
5659 init->getType(),
5660 /*constant*/ false,
5661 llvm::GlobalValue::WeakAnyLinkage,
5662 init,
5663 messageRefName);
5664 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
5665 messageRef->setAlignment(16);
5666 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
5667 }
5668 llvm::Value *mref =
5669 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
5670
John McCall944c8432011-05-14 03:10:52 +00005671 // Update the message ref argument.
John McCallb1e81442011-05-13 23:16:18 +00005672 args[1].RV = RValue::get(mref);
5673
5674 // Load the function to call from the message ref table.
5675 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
5676 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
5677
5678 bool variadic = method ? method->isVariadic() : false;
Chris Lattner2acc6e32011-07-18 04:24:23 +00005679 llvm::FunctionType *fnType =
John McCallb1e81442011-05-13 23:16:18 +00005680 CGF.getTypes().GetFunctionType(fnInfo, variadic);
5681 callee = CGF.Builder.CreateBitCast(callee,
5682 llvm::PointerType::getUnqual(fnType));
5683
John McCallcba681a2011-05-14 21:12:11 +00005684 RValue result = CGF.EmitCall(fnInfo, callee, returnSlot, args);
5685 return nullReturn.complete(CGF, result, resultType);
Fariborz Jahanian46551122009-02-04 00:22:57 +00005686}
5687
5688/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005689CodeGen::RValue
5690CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00005691 ReturnValueSlot Return,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005692 QualType ResultType,
5693 Selector Sel,
5694 llvm::Value *Receiver,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005695 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00005696 const ObjCInterfaceDecl *Class,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005697 const ObjCMethodDecl *Method) {
John McCall944c8432011-05-14 03:10:52 +00005698 return isVTableDispatchedSelector(Sel)
5699 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005700 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00005701 false, CallArgs, Method)
5702 : EmitMessageSend(CGF, Return, ResultType,
5703 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005704 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00005705 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian46551122009-02-04 00:22:57 +00005706}
5707
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005708llvm::GlobalVariable *
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005709CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005710 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5711
Daniel Dunbardfff2302009-03-02 05:18:14 +00005712 if (!GV) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005713 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005714 false, llvm::GlobalValue::ExternalLinkage,
5715 0, Name);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005716 }
5717
5718 return GV;
5719}
5720
John McCallf85e1932011-06-15 23:02:42 +00005721llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CGBuilderTy &Builder,
5722 IdentifierInfo *II) {
5723 llvm::GlobalVariable *&Entry = ClassReferences[II];
5724
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005725 if (!Entry) {
John McCallf85e1932011-06-15 23:02:42 +00005726 std::string ClassName(getClassSymbolPrefix() + II->getName().str());
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005727 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005728 Entry =
John McCallf85e1932011-06-15 23:02:42 +00005729 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
5730 false, llvm::GlobalValue::InternalLinkage,
5731 ClassGV,
5732 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005733 Entry->setAlignment(
John McCallf85e1932011-06-15 23:02:42 +00005734 CGM.getTargetData().getABITypeAlignment(
5735 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00005736 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005737 CGM.AddUsedGlobal(Entry);
Daniel Dunbar11394522009-04-18 08:51:00 +00005738 }
John McCallf85e1932011-06-15 23:02:42 +00005739
Benjamin Kramer578faa82011-09-27 21:06:10 +00005740 return Builder.CreateLoad(Entry);
Daniel Dunbar11394522009-04-18 08:51:00 +00005741}
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005742
John McCallf85e1932011-06-15 23:02:42 +00005743llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5744 const ObjCInterfaceDecl *ID) {
5745 return EmitClassRefFromId(Builder, ID->getIdentifier());
5746}
5747
5748llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
5749 CGBuilderTy &Builder) {
5750 IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
5751 return EmitClassRefFromId(Builder, II);
5752}
5753
Daniel Dunbar11394522009-04-18 08:51:00 +00005754llvm::Value *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005755CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00005756 const ObjCInterfaceDecl *ID) {
5757 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005758
Daniel Dunbar11394522009-04-18 08:51:00 +00005759 if (!Entry) {
5760 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5761 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005762 Entry =
5763 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005764 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005765 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005766 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar11394522009-04-18 08:51:00 +00005767 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005768 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005769 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00005770 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005771 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005772 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005773
Benjamin Kramer578faa82011-09-27 21:06:10 +00005774 return Builder.CreateLoad(Entry);
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005775}
5776
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005777/// EmitMetaClassRef - Return a Value * of the address of _class_t
5778/// meta-data
5779///
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005780llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5781 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005782 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5783 if (Entry)
Benjamin Kramer578faa82011-09-27 21:06:10 +00005784 return Builder.CreateLoad(Entry);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005785
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005786 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005787 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005788 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00005789 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005790 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005791 MetaClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005792 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005793 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005794 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005795 ObjCTypes.ClassnfABIPtrTy));
5796
Daniel Dunbar33af70f2009-04-15 19:03:14 +00005797 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005798 CGM.AddUsedGlobal(Entry);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005799
Benjamin Kramer578faa82011-09-27 21:06:10 +00005800 return Builder.CreateLoad(Entry);
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005801}
5802
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005803/// GetClass - Return a reference to the class for the given interface
5804/// decl.
5805llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5806 const ObjCInterfaceDecl *ID) {
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005807 if (ID->isWeakImported()) {
Fariborz Jahanian269f8bc2009-11-17 22:42:00 +00005808 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5809 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5810 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5811 }
5812
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005813 return EmitClassRef(Builder, ID);
5814}
5815
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005816/// Generates a message send where the super is the receiver. This is
5817/// a message send to self with special delivery semantics indicating
5818/// which class's method should be called.
5819CodeGen::RValue
5820CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00005821 ReturnValueSlot Return,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005822 QualType ResultType,
5823 Selector Sel,
5824 const ObjCInterfaceDecl *Class,
5825 bool isCategoryImpl,
5826 llvm::Value *Receiver,
5827 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005828 const CodeGen::CallArgList &CallArgs,
5829 const ObjCMethodDecl *Method) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005830 // ...
5831 // Create and init a super structure; this is a (receiver, class)
5832 // pair we will pass to objc_msgSendSuper.
5833 llvm::Value *ObjCSuper =
John McCall604da292011-03-04 08:00:29 +00005834 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005835
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005836 llvm::Value *ReceiverAsObject =
5837 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5838 CGF.Builder.CreateStore(ReceiverAsObject,
5839 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005840
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005841 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005842 llvm::Value *Target;
5843 if (IsClassMessage) {
5844 if (isCategoryImpl) {
5845 // Message sent to "super' in a class method defined in
5846 // a category implementation.
Daniel Dunbar11394522009-04-18 08:51:00 +00005847 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005848 Target = CGF.Builder.CreateStructGEP(Target, 0);
5849 Target = CGF.Builder.CreateLoad(Target);
Mike Stumpb3589f42009-07-30 22:28:39 +00005850 } else
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005851 Target = EmitMetaClassRef(CGF.Builder, Class);
Mike Stumpb3589f42009-07-30 22:28:39 +00005852 } else
Daniel Dunbar11394522009-04-18 08:51:00 +00005853 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005854
Mike Stumpf5408fe2009-05-16 07:57:57 +00005855 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5856 // ObjCTypes types.
Chris Lattner2acc6e32011-07-18 04:24:23 +00005857 llvm::Type *ClassTy =
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005858 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
5859 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
5860 CGF.Builder.CreateStore(Target,
5861 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005862
John McCall944c8432011-05-14 03:10:52 +00005863 return (isVTableDispatchedSelector(Sel))
5864 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005865 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00005866 true, CallArgs, Method)
5867 : EmitMessageSend(CGF, Return, ResultType,
5868 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005869 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00005870 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005871}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005872
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005873llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian03b29602010-06-17 19:56:20 +00005874 Selector Sel, bool lval) {
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005875 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005876
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005877 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005878 llvm::Constant *Casted =
5879 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5880 ObjCTypes.SelectorPtrTy);
5881 Entry =
5882 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
5883 llvm::GlobalValue::InternalLinkage,
5884 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00005885 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005886 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005887 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005888
Fariborz Jahanian03b29602010-06-17 19:56:20 +00005889 if (lval)
5890 return Entry;
Pete Cooperb6d71142011-11-10 21:45:06 +00005891 llvm::LoadInst* LI = Builder.CreateLoad(Entry);
5892
5893 LI->setMetadata(CGM.getModule().getMDKindID("invariant.load"),
5894 llvm::MDNode::get(VMContext,
5895 ArrayRef<llvm::Value*>()));
5896 return LI;
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005897}
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005898/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005899/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005900///
5901void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005902 llvm::Value *src,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005903 llvm::Value *dst,
5904 llvm::Value *ivarOffset) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00005905 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005906 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005907 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005908 assert(Size <= 8 && "does not support size > 8");
5909 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5910 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005911 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5912 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005913 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5914 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005915 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5916 src, dst, ivarOffset);
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005917 return;
5918}
5919
5920/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5921/// objc_assign_strongCast (id src, id *dst)
5922///
5923void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005924 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005925 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00005926 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005927 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005928 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005929 assert(Size <= 8 && "does not support size > 8");
5930 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005931 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005932 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5933 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005934 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5935 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00005936 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005937 src, dst, "weakassign");
5938 return;
5939}
5940
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005941void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005942 CodeGen::CodeGenFunction &CGF,
5943 llvm::Value *DestPtr,
5944 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00005945 llvm::Value *Size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005946 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5947 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005948 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00005949 DestPtr, SrcPtr, Size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005950 return;
5951}
5952
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005953/// EmitObjCWeakRead - Code gen for loading value of a __weak
5954/// object: objc_read_weak (id *src)
5955///
5956llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005957 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005958 llvm::Value *AddrWeakObj) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00005959 llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005960 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5961 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00005962 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005963 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00005964 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005965 return read_weak;
5966}
5967
5968/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
5969/// objc_assign_weak (id src, id *dst)
5970///
5971void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005972 llvm::Value *src, llvm::Value *dst) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00005973 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005974 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005975 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005976 assert(Size <= 8 && "does not support size > 8");
5977 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5978 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005979 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5980 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005981 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5982 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00005983 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005984 src, dst, "weakassign");
5985 return;
5986}
5987
5988/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
5989/// objc_assign_global (id src, id *dst)
5990///
5991void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00005992 llvm::Value *src, llvm::Value *dst,
5993 bool threadlocal) {
Chris Lattner2acc6e32011-07-18 04:24:23 +00005994 llvm::Type * SrcTy = src->getType();
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005995 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005996 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005997 assert(Size <= 8 && "does not support size > 8");
5998 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5999 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00006000 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
6001 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006002 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
6003 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00006004 if (!threadlocal)
6005 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
6006 src, dst, "globalassign");
6007 else
6008 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
6009 src, dst, "threadlocalassign");
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006010 return;
6011}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006012
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006013void
John McCallf1549f62010-07-06 01:34:17 +00006014CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6015 const ObjCAtSynchronizedStmt &S) {
David Chisnall05dc91b2011-03-25 17:46:35 +00006016 EmitAtSynchronizedStmt(CGF, S,
6017 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6018 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallf1549f62010-07-06 01:34:17 +00006019}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006020
John McCall5a180392010-07-24 00:37:23 +00006021llvm::Constant *
Fariborz Jahaniancf5abc72011-06-23 19:00:08 +00006022CGObjCNonFragileABIMac::GetEHType(QualType T) {
John McCall5a180392010-07-24 00:37:23 +00006023 // There's a particular fixed type info for 'id'.
6024 if (T->isObjCIdType() ||
6025 T->isObjCQualifiedIdType()) {
6026 llvm::Constant *IDEHType =
6027 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6028 if (!IDEHType)
6029 IDEHType =
6030 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6031 false,
6032 llvm::GlobalValue::ExternalLinkage,
6033 0, "OBJC_EHTYPE_id");
6034 return IDEHType;
6035 }
6036
6037 // All other types should be Objective-C interface pointer types.
6038 const ObjCObjectPointerType *PT =
6039 T->getAs<ObjCObjectPointerType>();
6040 assert(PT && "Invalid @catch type.");
6041 const ObjCInterfaceType *IT = PT->getInterfaceType();
6042 assert(IT && "Invalid @catch type.");
6043 return GetInterfaceEHType(IT->getDecl(), false);
6044}
6045
John McCallf1549f62010-07-06 01:34:17 +00006046void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6047 const ObjCAtTryStmt &S) {
David Chisnall05dc91b2011-03-25 17:46:35 +00006048 EmitTryCatchStmt(CGF, S,
6049 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6050 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6051 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006052}
6053
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006054/// EmitThrowStmt - Generate code for a throw statement.
6055void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6056 const ObjCAtThrowStmt &S) {
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006057 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall2b014d62011-10-01 10:32:24 +00006058 llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Benjamin Kramer578faa82011-09-27 21:06:10 +00006059 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
Jay Foad4c7d9f12011-07-15 08:37:34 +00006060 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
John McCall7ec404c2010-10-16 08:21:07 +00006061 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006062 } else {
Jay Foad4c7d9f12011-07-15 08:37:34 +00006063 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn())
John McCall7ec404c2010-10-16 08:21:07 +00006064 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006065 }
6066
John McCall7ec404c2010-10-16 08:21:07 +00006067 CGF.Builder.CreateUnreachable();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006068 CGF.Builder.ClearInsertionPoint();
6069}
Daniel Dunbare588b992009-03-01 04:46:24 +00006070
John McCall5a180392010-07-24 00:37:23 +00006071llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006072CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006073 bool ForDefinition) {
Daniel Dunbare588b992009-03-01 04:46:24 +00006074 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbare588b992009-03-01 04:46:24 +00006075
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006076 // If we don't need a definition, return the entry if found or check
6077 // if we use an external reference.
6078 if (!ForDefinition) {
6079 if (Entry)
6080 return Entry;
Daniel Dunbar7e075cb2009-04-07 06:43:45 +00006081
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006082 // If this type (or a super class) has the __objc_exception__
6083 // attribute, emit an external reference.
Douglas Gregor68584ed2009-06-18 16:11:24 +00006084 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006085 return Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00006086 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006087 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006088 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006089 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006090 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006091 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006092
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006093 // Otherwise we need to either make a new entry or fill in the
6094 // initializer.
6095 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006096 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbare588b992009-03-01 04:46:24 +00006097 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006098 llvm::GlobalVariable *VTableGV =
Daniel Dunbare588b992009-03-01 04:46:24 +00006099 CGM.getModule().getGlobalVariable(VTableName);
6100 if (!VTableGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006101 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6102 false,
Daniel Dunbare588b992009-03-01 04:46:24 +00006103 llvm::GlobalValue::ExternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00006104 0, VTableName);
Daniel Dunbare588b992009-03-01 04:46:24 +00006105
Chris Lattner77b89b82010-06-27 07:15:29 +00006106 llvm::Value *VTableIdx =
6107 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
Daniel Dunbare588b992009-03-01 04:46:24 +00006108
Benjamin Kramer1d236ab2011-10-15 12:20:02 +00006109 llvm::Constant *Values[] = {
6110 llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx),
6111 GetClassName(ID->getIdentifier()),
6112 GetClassGlobal(ClassName)
6113 };
Owen Andersona1cf15f2009-07-14 23:10:40 +00006114 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00006115 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbare588b992009-03-01 04:46:24 +00006116
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006117 if (Entry) {
6118 Entry->setInitializer(Init);
6119 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00006120 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006121 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006122 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006123 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006124 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006125 }
6126
John McCall1fb0caa2010-10-22 21:05:15 +00006127 if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006128 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00006129 Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6130 ObjCTypes.EHTypeTy));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006131
6132 if (ForDefinition) {
6133 Entry->setSection("__DATA,__objc_const");
6134 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6135 } else {
6136 Entry->setSection("__DATA,__datacoal_nt,coalesced");
6137 }
Daniel Dunbare588b992009-03-01 04:46:24 +00006138
6139 return Entry;
6140}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006141
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00006142/* *** */
6143
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00006144CodeGen::CGObjCRuntime *
6145CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
David Chisnall60be6072011-03-22 21:21:24 +00006146 if (CGM.getLangOptions().ObjCNonFragileABI)
6147 return new CGObjCNonFragileABIMac(CGM);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00006148 return new CGObjCMac(CGM);
6149}