blob: 137f724c991675c398102d0d8fab695a6cc0fcef [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
John McCall448d2cd2011-02-26 09:48:59 +000046static void EmitNullReturnInitialization(CodeGenFunction &CGF,
47 ReturnValueSlot &returnSlot,
48 QualType resultType) {
49 // Force the return slot to exist.
50 if (!returnSlot.getValue())
51 returnSlot = ReturnValueSlot(CGF.CreateMemTemp(resultType), false);
52 CGF.EmitNullInitialization(returnSlot.getValue(), resultType);
53}
54
Daniel Dunbar97776872009-04-22 07:32:20 +000055
56///
57
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000058namespace {
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000059
Daniel Dunbar6bff2512009-08-03 17:06:42 +000060typedef std::vector<llvm::Constant*> ConstantVector;
Daniel Dunbarae226fa2008-08-27 02:31:56 +000061
Daniel Dunbar6bff2512009-08-03 17:06:42 +000062// FIXME: We should find a nicer way to make the labels for metadata, string
63// concatenation is lame.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000064
Fariborz Jahanianee0af742009-01-21 22:04:16 +000065class ObjCCommonTypesHelper {
Owen Andersona1cf15f2009-07-14 23:10:40 +000066protected:
67 llvm::LLVMContext &VMContext;
Daniel Dunbar6bff2512009-08-03 17:06:42 +000068
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000069private:
70 llvm::Constant *getMessageSendFn() const {
71 // id objc_msgSend (id, SEL, ...)
72 std::vector<const llvm::Type*> Params;
73 Params.push_back(ObjectPtrTy);
74 Params.push_back(SelectorPtrTy);
75 return
Daniel Dunbar6bff2512009-08-03 17:06:42 +000076 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +000077 Params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +000078 "objc_msgSend");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000079 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000080
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000081 llvm::Constant *getMessageSendStretFn() const {
82 // id objc_msgSend_stret (id, SEL, ...)
83 std::vector<const llvm::Type*> Params;
84 Params.push_back(ObjectPtrTy);
85 Params.push_back(SelectorPtrTy);
86 return
Owen Anderson0032b272009-08-13 21:57:51 +000087 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +000088 Params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +000089 "objc_msgSend_stret");
90
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000091 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000092
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000093 llvm::Constant *getMessageSendFpretFn() const {
94 // FIXME: This should be long double on x86_64?
95 // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
96 std::vector<const llvm::Type*> Params;
97 Params.push_back(ObjectPtrTy);
98 Params.push_back(SelectorPtrTy);
99 return
Owen Anderson0032b272009-08-13 21:57:51 +0000100 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
101 llvm::Type::getDoubleTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000102 Params,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000103 true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000104 "objc_msgSend_fpret");
105
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000106 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000107
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000108 llvm::Constant *getMessageSendSuperFn() const {
109 // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
110 const char *SuperName = "objc_msgSendSuper";
111 std::vector<const llvm::Type*> Params;
112 Params.push_back(SuperPtrTy);
113 Params.push_back(SelectorPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000114 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000115 Params, true),
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000116 SuperName);
117 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000118
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000119 llvm::Constant *getMessageSendSuperFn2() const {
120 // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
121 const char *SuperName = "objc_msgSendSuper2";
122 std::vector<const llvm::Type*> Params;
123 Params.push_back(SuperPtrTy);
124 Params.push_back(SelectorPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000125 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000126 Params, true),
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000127 SuperName);
128 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000129
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000130 llvm::Constant *getMessageSendSuperStretFn() const {
131 // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
132 // SEL op, ...)
133 std::vector<const llvm::Type*> Params;
134 Params.push_back(Int8PtrTy);
135 Params.push_back(SuperPtrTy);
136 Params.push_back(SelectorPtrTy);
Owen Andersona1cf15f2009-07-14 23:10:40 +0000137 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000138 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000139 Params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000140 "objc_msgSendSuper_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000141 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000142
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000143 llvm::Constant *getMessageSendSuperStretFn2() const {
144 // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
145 // SEL op, ...)
146 std::vector<const llvm::Type*> Params;
147 Params.push_back(Int8PtrTy);
148 Params.push_back(SuperPtrTy);
149 Params.push_back(SelectorPtrTy);
Owen Andersona1cf15f2009-07-14 23:10:40 +0000150 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000151 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000152 Params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000153 "objc_msgSendSuper2_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000154 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000155
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000156 llvm::Constant *getMessageSendSuperFpretFn() const {
157 // There is no objc_msgSendSuper_fpret? How can that work?
158 return getMessageSendSuperFn();
159 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000160
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000161 llvm::Constant *getMessageSendSuperFpretFn2() const {
162 // There is no objc_msgSendSuper_fpret? How can that work?
163 return getMessageSendSuperFn2();
164 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000165
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000166protected:
167 CodeGen::CodeGenModule &CGM;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000168
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000169public:
Fariborz Jahanian0a855d02009-03-23 19:10:40 +0000170 const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000171 const llvm::Type *Int8PtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000172
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000173 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
174 const llvm::Type *ObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000175
Fariborz Jahanian6d657c42008-11-18 20:18:11 +0000176 /// PtrObjectPtrTy - LLVM type for id *
177 const llvm::Type *PtrObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000178
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000179 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000180 const llvm::Type *SelectorPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000181 /// ProtocolPtrTy - LLVM type for external protocol handles
182 /// (typeof(Protocol))
183 const llvm::Type *ExternalProtocolPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000184
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000185 // SuperCTy - clang type for struct objc_super.
186 QualType SuperCTy;
187 // SuperPtrCTy - clang type for struct objc_super *.
188 QualType SuperPtrCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000189
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000190 /// SuperTy - LLVM type for struct objc_super.
191 const llvm::StructType *SuperTy;
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000192 /// SuperPtrTy - LLVM type for struct objc_super *.
193 const llvm::Type *SuperPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000194
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000195 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
196 /// in GCC parlance).
197 const llvm::StructType *PropertyTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000198
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000199 /// PropertyListTy - LLVM type for struct objc_property_list
200 /// (_prop_list_t in GCC parlance).
201 const llvm::StructType *PropertyListTy;
202 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
203 const llvm::Type *PropertyListPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000204
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000205 // MethodTy - LLVM type for struct objc_method.
206 const llvm::StructType *MethodTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000207
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000208 /// CacheTy - LLVM type for struct objc_cache.
209 const llvm::Type *CacheTy;
210 /// CachePtrTy - LLVM type for struct objc_cache *.
211 const llvm::Type *CachePtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000212
Chris Lattner72db6c32009-04-22 02:44:54 +0000213 llvm::Constant *getGetPropertyFn() {
214 CodeGen::CodeGenTypes &Types = CGM.getTypes();
215 ASTContext &Ctx = CGM.getContext();
216 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
John McCallead608a2010-02-26 00:48:12 +0000217 llvm::SmallVector<CanQualType,4> Params;
218 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
219 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattner72db6c32009-04-22 02:44:54 +0000220 Params.push_back(IdType);
221 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000222 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000223 Params.push_back(Ctx.BoolTy);
224 const llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000225 Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000226 FunctionType::ExtInfo()),
227 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000228 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
229 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000230
Chris Lattner72db6c32009-04-22 02:44:54 +0000231 llvm::Constant *getSetPropertyFn() {
232 CodeGen::CodeGenTypes &Types = CGM.getTypes();
233 ASTContext &Ctx = CGM.getContext();
234 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
John McCallead608a2010-02-26 00:48:12 +0000235 llvm::SmallVector<CanQualType,6> Params;
236 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
237 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattner72db6c32009-04-22 02:44:54 +0000238 Params.push_back(IdType);
239 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000240 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000241 Params.push_back(IdType);
242 Params.push_back(Ctx.BoolTy);
243 Params.push_back(Ctx.BoolTy);
244 const llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000245 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000246 FunctionType::ExtInfo()),
247 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000248 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
249 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000250
Fariborz Jahanian6cc59062010-04-12 18:18:10 +0000251
252 llvm::Constant *getCopyStructFn() {
253 CodeGen::CodeGenTypes &Types = CGM.getTypes();
254 ASTContext &Ctx = CGM.getContext();
255 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
256 llvm::SmallVector<CanQualType,5> Params;
257 Params.push_back(Ctx.VoidPtrTy);
258 Params.push_back(Ctx.VoidPtrTy);
259 Params.push_back(Ctx.LongTy);
260 Params.push_back(Ctx.BoolTy);
261 Params.push_back(Ctx.BoolTy);
262 const llvm::FunctionType *FTy =
263 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
264 FunctionType::ExtInfo()),
265 false);
266 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
267 }
268
Chris Lattner72db6c32009-04-22 02:44:54 +0000269 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000270 CodeGen::CodeGenTypes &Types = CGM.getTypes();
271 ASTContext &Ctx = CGM.getContext();
Chris Lattner72db6c32009-04-22 02:44:54 +0000272 // void objc_enumerationMutation (id)
John McCallead608a2010-02-26 00:48:12 +0000273 llvm::SmallVector<CanQualType,1> Params;
274 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000275 const llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000276 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000277 FunctionType::ExtInfo()),
278 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000279 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
280 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000281
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000282 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattner72db6c32009-04-22 02:44:54 +0000283 llvm::Constant *getGcReadWeakFn() {
284 // id objc_read_weak (id *)
285 std::vector<const llvm::Type*> Args;
286 Args.push_back(ObjectPtrTy->getPointerTo());
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000287 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000288 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000289 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000290 }
291
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000292 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner96508e12009-04-17 22:12:36 +0000293 llvm::Constant *getGcAssignWeakFn() {
294 // id objc_assign_weak (id, id *)
295 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
296 Args.push_back(ObjectPtrTy->getPointerTo());
297 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000298 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner96508e12009-04-17 22:12:36 +0000299 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
300 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000301
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000302 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000303 llvm::Constant *getGcAssignGlobalFn() {
304 // id objc_assign_global(id, id *)
305 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
306 Args.push_back(ObjectPtrTy->getPointerTo());
Owen Andersona1cf15f2009-07-14 23:10:40 +0000307 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000308 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000309 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
310 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000311
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000312 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
313 llvm::Constant *getGcAssignThreadLocalFn() {
314 // id objc_assign_threadlocal(id src, id * dest)
315 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
316 Args.push_back(ObjectPtrTy->getPointerTo());
317 llvm::FunctionType *FTy =
318 llvm::FunctionType::get(ObjectPtrTy, Args, false);
319 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
320 }
321
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000322 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000323 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +0000324 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnerbbccd612009-04-22 02:38:11 +0000325 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
326 Args.push_back(ObjectPtrTy->getPointerTo());
Fariborz Jahaniane0c76652011-05-05 22:00:38 +0000327 const llvm::Type *PtrDiffTy =
328 CGM.getTypes().ConvertType(
329 CGM.getContext().getPointerDiffType()->getCanonicalTypeUnqualified());
330
331 Args.push_back(PtrDiffTy);
Owen Andersona1cf15f2009-07-14 23:10:40 +0000332 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000333 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000334 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
335 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000336
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000337 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
338 llvm::Constant *GcMemmoveCollectableFn() {
339 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
340 std::vector<const llvm::Type*> Args(1, Int8PtrTy);
341 Args.push_back(Int8PtrTy);
342 Args.push_back(LongTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000343 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000344 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
345 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000346
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000347 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000348 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000349 // id objc_assign_strongCast(id, id *)
Chris Lattnerbbccd612009-04-22 02:38:11 +0000350 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
351 Args.push_back(ObjectPtrTy->getPointerTo());
Owen Andersona1cf15f2009-07-14 23:10:40 +0000352 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000353 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000354 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
355 }
Anders Carlssonf57c5b22009-02-16 22:59:18 +0000356
357 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000358 llvm::Constant *getExceptionThrowFn() {
359 // void objc_exception_throw(id)
360 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
361 llvm::FunctionType *FTy =
Owen Anderson0032b272009-08-13 21:57:51 +0000362 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000363 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
364 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000365
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000366 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
367 llvm::Constant *getExceptionRethrowFn() {
368 // void objc_exception_rethrow(void)
369 std::vector<const llvm::Type*> Args;
370 llvm::FunctionType *FTy =
John McCall7ec404c2010-10-16 08:21:07 +0000371 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000372 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
373 }
374
Daniel Dunbar1c566672009-02-24 01:43:46 +0000375 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000376 llvm::Constant *getSyncEnterFn() {
377 // void objc_sync_enter (id)
378 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
379 llvm::FunctionType *FTy =
Owen Anderson0032b272009-08-13 21:57:51 +0000380 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000381 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
382 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000383
Daniel Dunbar1c566672009-02-24 01:43:46 +0000384 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000385 llvm::Constant *getSyncExitFn() {
386 // void objc_sync_exit (id)
387 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
388 llvm::FunctionType *FTy =
Owen Anderson0032b272009-08-13 21:57:51 +0000389 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000390 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
391 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000392
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000393 llvm::Constant *getSendFn(bool IsSuper) const {
394 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
395 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000396
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000397 llvm::Constant *getSendFn2(bool IsSuper) const {
398 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
399 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000400
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000401 llvm::Constant *getSendStretFn(bool IsSuper) const {
402 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
403 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000404
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000405 llvm::Constant *getSendStretFn2(bool IsSuper) const {
406 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
407 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000408
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000409 llvm::Constant *getSendFpretFn(bool IsSuper) const {
410 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
411 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000412
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000413 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
414 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
415 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000416
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000417 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
418 ~ObjCCommonTypesHelper(){}
419};
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000420
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000421/// ObjCTypesHelper - Helper class that encapsulates lazy
422/// construction of varies types used during ObjC generation.
423class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000424public:
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000425 /// SymtabTy - LLVM type for struct objc_symtab.
426 const llvm::StructType *SymtabTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000427 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
428 const llvm::Type *SymtabPtrTy;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000429 /// ModuleTy - LLVM type for struct objc_module.
430 const llvm::StructType *ModuleTy;
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000431
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000432 /// ProtocolTy - LLVM type for struct objc_protocol.
433 const llvm::StructType *ProtocolTy;
434 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
435 const llvm::Type *ProtocolPtrTy;
436 /// ProtocolExtensionTy - LLVM type for struct
437 /// objc_protocol_extension.
438 const llvm::StructType *ProtocolExtensionTy;
439 /// ProtocolExtensionTy - LLVM type for struct
440 /// objc_protocol_extension *.
441 const llvm::Type *ProtocolExtensionPtrTy;
442 /// MethodDescriptionTy - LLVM type for struct
443 /// objc_method_description.
444 const llvm::StructType *MethodDescriptionTy;
445 /// MethodDescriptionListTy - LLVM type for struct
446 /// objc_method_description_list.
447 const llvm::StructType *MethodDescriptionListTy;
448 /// MethodDescriptionListPtrTy - LLVM type for struct
449 /// objc_method_description_list *.
450 const llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000451 /// ProtocolListTy - LLVM type for struct objc_property_list.
452 const llvm::Type *ProtocolListTy;
453 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
454 const llvm::Type *ProtocolListPtrTy;
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000455 /// CategoryTy - LLVM type for struct objc_category.
456 const llvm::StructType *CategoryTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000457 /// ClassTy - LLVM type for struct objc_class.
458 const llvm::StructType *ClassTy;
459 /// ClassPtrTy - LLVM type for struct objc_class *.
460 const llvm::Type *ClassPtrTy;
461 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
462 const llvm::StructType *ClassExtensionTy;
463 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
464 const llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000465 // IvarTy - LLVM type for struct objc_ivar.
466 const llvm::StructType *IvarTy;
467 /// IvarListTy - LLVM type for struct objc_ivar_list.
468 const llvm::Type *IvarListTy;
469 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
470 const llvm::Type *IvarListPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000471 /// MethodListTy - LLVM type for struct objc_method_list.
472 const llvm::Type *MethodListTy;
473 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
474 const llvm::Type *MethodListPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000475
Anders Carlsson124526b2008-09-09 10:10:21 +0000476 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
477 const llvm::Type *ExceptionDataTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000478
Anders Carlsson124526b2008-09-09 10:10:21 +0000479 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000480 llvm::Constant *getExceptionTryEnterFn() {
481 std::vector<const llvm::Type*> Params;
Owen Anderson96e0fc72009-07-29 22:16:19 +0000482 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
Owen Andersona1cf15f2009-07-14 23:10:40 +0000483 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000484 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000485 Params, false),
486 "objc_exception_try_enter");
Chris Lattner34b02a12009-04-22 02:26:14 +0000487 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000488
489 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000490 llvm::Constant *getExceptionTryExitFn() {
491 std::vector<const llvm::Type*> Params;
Owen Anderson96e0fc72009-07-29 22:16:19 +0000492 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
Owen Andersona1cf15f2009-07-14 23:10:40 +0000493 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000494 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000495 Params, false),
496 "objc_exception_try_exit");
Chris Lattner34b02a12009-04-22 02:26:14 +0000497 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000498
499 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000500 llvm::Constant *getExceptionExtractFn() {
501 std::vector<const llvm::Type*> Params;
Owen Anderson96e0fc72009-07-29 22:16:19 +0000502 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
503 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner34b02a12009-04-22 02:26:14 +0000504 Params, false),
505 "objc_exception_extract");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000506
Chris Lattner34b02a12009-04-22 02:26:14 +0000507 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000508
Anders Carlsson124526b2008-09-09 10:10:21 +0000509 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000510 llvm::Constant *getExceptionMatchFn() {
511 std::vector<const llvm::Type*> Params;
512 Params.push_back(ClassPtrTy);
513 Params.push_back(ObjectPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000514 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000515 llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000516 Params, false),
517 "objc_exception_match");
518
Chris Lattner34b02a12009-04-22 02:26:14 +0000519 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000520
Anders Carlsson124526b2008-09-09 10:10:21 +0000521 /// SetJmpFn - LLVM _setjmp function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000522 llvm::Constant *getSetJmpFn() {
523 std::vector<const llvm::Type*> Params;
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +0000524 Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
Chris Lattner34b02a12009-04-22 02:26:14 +0000525 return
Owen Anderson0032b272009-08-13 21:57:51 +0000526 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Chris Lattner34b02a12009-04-22 02:26:14 +0000527 Params, false),
528 "_setjmp");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000529
Chris Lattner34b02a12009-04-22 02:26:14 +0000530 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000531
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000532public:
533 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000534 ~ObjCTypesHelper() {}
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000535};
536
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000537/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000538/// modern abi
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000539class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000540public:
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000541
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000542 // MethodListnfABITy - LLVM for struct _method_list_t
543 const llvm::StructType *MethodListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000544
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000545 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
546 const llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000547
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000548 // ProtocolnfABITy = LLVM for struct _protocol_t
549 const llvm::StructType *ProtocolnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000550
Daniel Dunbar948e2582009-02-15 07:36:20 +0000551 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
552 const llvm::Type *ProtocolnfABIPtrTy;
553
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000554 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
555 const llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000556
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000557 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
558 const llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000559
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000560 // ClassnfABITy - LLVM for struct _class_t
561 const llvm::StructType *ClassnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000562
Fariborz Jahanianaa23b572009-01-23 23:53:38 +0000563 // ClassnfABIPtrTy - LLVM for struct _class_t*
564 const llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000565
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000566 // IvarnfABITy - LLVM for struct _ivar_t
567 const llvm::StructType *IvarnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000568
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000569 // IvarListnfABITy - LLVM for struct _ivar_list_t
570 const llvm::StructType *IvarListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000571
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000572 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
573 const llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000574
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000575 // ClassRonfABITy - LLVM for struct _class_ro_t
576 const llvm::StructType *ClassRonfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000577
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000578 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
579 const llvm::Type *ImpnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000580
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000581 // CategorynfABITy - LLVM for struct _category_t
582 const llvm::StructType *CategorynfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000583
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000584 // New types for nonfragile abi messaging.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000585
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000586 // MessageRefTy - LLVM for:
587 // struct _message_ref_t {
588 // IMP messenger;
589 // SEL name;
590 // };
591 const llvm::StructType *MessageRefTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000592 // MessageRefCTy - clang type for struct _message_ref_t
593 QualType MessageRefCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000594
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000595 // MessageRefPtrTy - LLVM for struct _message_ref_t*
596 const llvm::Type *MessageRefPtrTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000597 // MessageRefCPtrTy - clang type for struct _message_ref_t*
598 QualType MessageRefCPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000599
Fariborz Jahanianef163782009-02-05 01:13:09 +0000600 // MessengerTy - Type of the messenger (shown as IMP above)
601 const llvm::FunctionType *MessengerTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000602
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000603 // SuperMessageRefTy - LLVM for:
604 // struct _super_message_ref_t {
605 // SUPER_IMP messenger;
606 // SEL name;
607 // };
608 const llvm::StructType *SuperMessageRefTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000609
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000610 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
611 const llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000612
Chris Lattner1c02f862009-04-22 02:53:24 +0000613 llvm::Constant *getMessageSendFixupFn() {
614 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
615 std::vector<const llvm::Type*> Params;
616 Params.push_back(ObjectPtrTy);
617 Params.push_back(MessageRefPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000618 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000619 Params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000620 "objc_msgSend_fixup");
621 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000622
Chris Lattner1c02f862009-04-22 02:53:24 +0000623 llvm::Constant *getMessageSendFpretFixupFn() {
624 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
625 std::vector<const llvm::Type*> Params;
626 Params.push_back(ObjectPtrTy);
627 Params.push_back(MessageRefPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000628 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000629 Params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000630 "objc_msgSend_fpret_fixup");
631 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000632
Chris Lattner1c02f862009-04-22 02:53:24 +0000633 llvm::Constant *getMessageSendStretFixupFn() {
634 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
635 std::vector<const llvm::Type*> Params;
636 Params.push_back(ObjectPtrTy);
637 Params.push_back(MessageRefPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000638 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000639 Params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000640 "objc_msgSend_stret_fixup");
641 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000642
Chris Lattner1c02f862009-04-22 02:53:24 +0000643 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000644 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000645 // struct _super_message_ref_t*, ...)
646 std::vector<const llvm::Type*> Params;
647 Params.push_back(SuperPtrTy);
648 Params.push_back(SuperMessageRefPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000649 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000650 Params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000651 "objc_msgSendSuper2_fixup");
652 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000653
Chris Lattner1c02f862009-04-22 02:53:24 +0000654 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000655 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000656 // struct _super_message_ref_t*, ...)
657 std::vector<const llvm::Type*> Params;
658 Params.push_back(SuperPtrTy);
659 Params.push_back(SuperMessageRefPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000660 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000661 Params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000662 "objc_msgSendSuper2_stret_fixup");
663 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000664
Chris Lattner8a569112009-04-22 02:15:23 +0000665 llvm::Constant *getObjCEndCatchFn() {
Owen Anderson0032b272009-08-13 21:57:51 +0000666 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Chris Lattnerb59761b2009-07-01 04:13:52 +0000667 false),
Chris Lattner8a569112009-04-22 02:15:23 +0000668 "objc_end_catch");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000669
Chris Lattner8a569112009-04-22 02:15:23 +0000670 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000671
Chris Lattner8a569112009-04-22 02:15:23 +0000672 llvm::Constant *getObjCBeginCatchFn() {
673 std::vector<const llvm::Type*> Params;
674 Params.push_back(Int8PtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000675 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
Chris Lattner8a569112009-04-22 02:15:23 +0000676 Params, false),
677 "objc_begin_catch");
678 }
Daniel Dunbare588b992009-03-01 04:46:24 +0000679
680 const llvm::StructType *EHTypeTy;
681 const llvm::Type *EHTypePtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000682
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000683 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
684 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000685};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000686
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000687class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000688public:
689 // FIXME - accessibility
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000690 class GC_IVAR {
Fariborz Jahanian820e0202009-03-11 00:07:04 +0000691 public:
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000692 unsigned ivar_bytepos;
693 unsigned ivar_size;
694 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000695 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar0941b492009-04-23 01:29:05 +0000696
697 // Allow sorting based on byte pos.
698 bool operator<(const GC_IVAR &b) const {
699 return ivar_bytepos < b.ivar_bytepos;
700 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000701 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000702
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000703 class SKIP_SCAN {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000704 public:
705 unsigned skip;
706 unsigned scan;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000707 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000708 : skip(_skip), scan(_scan) {}
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000709 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000710
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000711protected:
712 CodeGen::CodeGenModule &CGM;
Owen Anderson69243822009-07-13 04:10:07 +0000713 llvm::LLVMContext &VMContext;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000714 // FIXME! May not be needing this after all.
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000715 unsigned ObjCABI;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000716
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000717 // gc ivar layout bitmap calculation helper caches.
718 llvm::SmallVector<GC_IVAR, 16> SkipIvars;
719 llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000720
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000721 /// LazySymbols - Symbols to generate a lazy reference for. See
722 /// DefinedSymbols and FinishModule().
Daniel Dunbar33063492009-09-07 00:20:42 +0000723 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000724
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000725 /// DefinedSymbols - External symbols which are defined by this
726 /// module. The symbols in this list and LazySymbols are used to add
727 /// special linker symbols which ensure that Objective-C modules are
728 /// linked properly.
Daniel Dunbar33063492009-09-07 00:20:42 +0000729 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000730
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000731 /// ClassNames - uniqued class names.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000732 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000733
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000734 /// MethodVarNames - uniqued method variable names.
735 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000736
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +0000737 /// DefinedCategoryNames - list of category names in form Class_Category.
738 llvm::SetVector<std::string> DefinedCategoryNames;
739
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000740 /// MethodVarTypes - uniqued method type signatures. We have to use
741 /// a StringMap here because have no other unique reference.
742 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000743
Daniel Dunbarc45ef602008-08-26 21:51:14 +0000744 /// MethodDefinitions - map of methods which have been defined in
745 /// this translation unit.
746 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000747
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000748 /// PropertyNames - uniqued method variable names.
749 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000750
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000751 /// ClassReferences - uniqued class references.
752 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000753
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000754 /// SelectorReferences - uniqued selector references.
755 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000756
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000757 /// Protocols - Protocols for which an objc_protocol structure has
758 /// been emitted. Forward declarations are handled by creating an
759 /// empty structure whose initializer is filled in when/if defined.
760 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000761
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000762 /// DefinedProtocols - Protocols which have actually been
763 /// defined. We should not need this, see FIXME in GenerateProtocol.
764 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000765
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000766 /// DefinedClasses - List of defined classes.
767 std::vector<llvm::GlobalValue*> DefinedClasses;
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000768
769 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
770 std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000771
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000772 /// DefinedCategories - List of defined categories.
773 std::vector<llvm::GlobalValue*> DefinedCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000774
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000775 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
776 std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000777
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000778 /// GetNameForMethod - Return a name for the given method.
779 /// \param[out] NameOut - The return value.
780 void GetNameForMethod(const ObjCMethodDecl *OMD,
781 const ObjCContainerDecl *CD,
Daniel Dunbarc575ce72009-10-19 01:21:19 +0000782 llvm::SmallVectorImpl<char> &NameOut);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000783
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000784 /// GetMethodVarName - Return a unique constant for the given
785 /// selector's name. The return value has type char *.
786 llvm::Constant *GetMethodVarName(Selector Sel);
787 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000788
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000789 /// GetMethodVarType - Return a unique constant for the given
790 /// selector's name. The return value has type char *.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000791
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000792 // FIXME: This is a horrible name.
793 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +0000794 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000795
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000796 /// GetPropertyName - Return a unique constant for the given
797 /// name. The return value has type char *.
798 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000799
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000800 // FIXME: This can be dropped once string functions are unified.
801 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
802 const Decl *Container);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000803
Fariborz Jahanian058a1b72009-01-24 20:21:50 +0000804 /// GetClassName - Return a unique constant for the given selector's
805 /// name. The return value has type char *.
806 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000807
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +0000808 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
809
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000810 /// BuildIvarLayout - Builds ivar layout bitmap for the class
811 /// implementation for the __strong or __weak case.
812 ///
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000813 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
814 bool ForStrongLayout);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +0000815
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +0000816 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000817
Daniel Dunbard58edcb2009-05-03 14:10:34 +0000818 void BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000819 unsigned int BytePos, bool ForStrongLayout,
820 bool &HasUnion);
Daniel Dunbar5a5a8032009-05-03 21:05:10 +0000821 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000822 const llvm::StructLayout *Layout,
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000823 const RecordDecl *RD,
Chris Lattnerf1690852009-03-31 08:48:01 +0000824 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000825 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahanian81adc052009-04-24 16:17:09 +0000826 bool &HasUnion);
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000827
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +0000828 /// GetIvarLayoutName - Returns a unique constant for the given
829 /// ivar layout bitmap.
830 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
831 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000832
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000833 /// EmitPropertyList - Emit the given property list. The return
834 /// value has type PropertyListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000835 llvm::Constant *EmitPropertyList(llvm::Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000836 const Decl *Container,
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000837 const ObjCContainerDecl *OCD,
838 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000839
Fariborz Jahanian191dcd72009-12-12 21:26:21 +0000840 /// PushProtocolProperties - Push protocol's property on the input stack.
841 void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
842 std::vector<llvm::Constant*> &Properties,
843 const Decl *Container,
844 const ObjCProtocolDecl *PROTO,
845 const ObjCCommonTypesHelper &ObjCTypes);
846
Fariborz Jahanianda320092009-01-29 19:24:30 +0000847 /// GetProtocolRef - Return a reference to the internal protocol
848 /// description, creating an empty one if it has not been
849 /// defined. The return value has type ProtocolPtrTy.
850 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanianb21f07e2009-03-08 20:18:37 +0000851
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000852 /// CreateMetadataVar - Create a global variable with internal
853 /// linkage for use by the Objective-C runtime.
854 ///
855 /// This is a convenience wrapper which not only creates the
856 /// variable, but also sets the section and alignment and adds the
Chris Lattnerad64e022009-07-17 23:57:13 +0000857 /// global to the "llvm.used" list.
Daniel Dunbar35bd7632009-03-09 20:50:13 +0000858 ///
859 /// \param Name - The variable name.
860 /// \param Init - The variable initializer; this is also used to
861 /// define the type of the variable.
862 /// \param Section - The section the variable should go into, or 0.
863 /// \param Align - The alignment for the variable, or 0.
864 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbarc1583062009-04-14 17:42:51 +0000865 /// "llvm.used".
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000866 llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000867 llvm::Constant *Init,
868 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +0000869 unsigned Align,
870 bool AddToUsed);
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000871
John McCall944c8432011-05-14 03:10:52 +0000872 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
873 ReturnValueSlot Return,
874 QualType ResultType,
875 llvm::Value *Sel,
876 llvm::Value *Arg0,
877 QualType Arg0Ty,
878 bool IsSuper,
879 const CallArgList &CallArgs,
880 const ObjCMethodDecl *OMD,
881 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +0000882
Daniel Dunbarfce176b2010-04-25 20:39:01 +0000883 /// EmitImageInfo - Emit the image info marker used to encode some module
884 /// level information.
885 void EmitImageInfo();
886
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000887public:
Owen Anderson69243822009-07-13 04:10:07 +0000888 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
Mike Stump1eb44332009-09-09 15:08:12 +0000889 CGM(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000890
David Chisnall0d13f6f2010-01-23 02:40:42 +0000891 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000892
Fariborz Jahanian493dab72009-01-26 21:38:32 +0000893 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
894 const ObjCContainerDecl *CD=0);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000895
Fariborz Jahanianda320092009-01-29 19:24:30 +0000896 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000897
Fariborz Jahanianda320092009-01-29 19:24:30 +0000898 /// GetOrEmitProtocol - Get the protocol object for the given
899 /// declaration, emitting it if necessary. The return value has type
900 /// ProtocolPtrTy.
901 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000902
Fariborz Jahanianda320092009-01-29 19:24:30 +0000903 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
904 /// object for the given declaration, emitting it if needed. These
905 /// forward references will be filled in with empty bodies if no
906 /// definition is seen. The return value has type ProtocolPtrTy.
907 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCall6b5a61b2011-02-07 10:33:21 +0000908 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
909 const CGBlockInfo &blockInfo);
Fariborz Jahanian89ecd412010-08-04 16:57:49 +0000910
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000911};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000912
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000913class CGObjCMac : public CGObjCCommonMac {
914private:
915 ObjCTypesHelper ObjCTypes;
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000916
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000917 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000918 /// information.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000919 void EmitModuleInfo();
920
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000921 /// EmitModuleSymols - Emit module symbols, the list of defined
922 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000923 llvm::Constant *EmitModuleSymbols();
924
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000925 /// FinishModule - Write out global data structures at the end of
926 /// processing a translation unit.
927 void FinishModule();
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000928
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000929 /// EmitClassExtension - Generate the class extension structure used
930 /// to store the weak ivar layout and properties. The return value
931 /// has type ClassExtensionPtrTy.
932 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
933
934 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
935 /// for the given class.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000936 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000937 const ObjCInterfaceDecl *ID);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +0000938
939 /// EmitSuperClassRef - Emits reference to class's main metadata class.
940 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000941
942 /// EmitIvarList - Emit the ivar list for the given
943 /// implementation. If ForClass is true the list of class ivars
944 /// (i.e. metaclass ivars) is emitted, otherwise the list of
945 /// interface ivars will be emitted. The return value has type
946 /// IvarListPtrTy.
947 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +0000948 bool ForClass);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000949
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000950 /// EmitMetaClass - Emit a forward reference to the class structure
951 /// for the metaclass of the given interface. The return value has
952 /// type ClassPtrTy.
953 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
954
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000955 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000956 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000957 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
958 llvm::Constant *Protocols,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000959 const ConstantVector &Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000960
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000961 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000962
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000963 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000964
965 /// EmitMethodList - Emit the method list for the given
Daniel Dunbaraf05bb92008-08-26 08:29:31 +0000966 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000967 llvm::Constant *EmitMethodList(llvm::Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000968 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000969 const ConstantVector &Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000970
971 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000972 /// method declarations.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000973 /// - TypeName: The name for the type containing the methods.
974 /// - IsProtocol: True iff these methods are for a protocol.
975 /// - ClassMethds: True iff these are class methods.
976 /// - Required: When true, only "required" methods are
977 /// listed. Similarly, when false only "optional" methods are
978 /// listed. For classes this should always be true.
979 /// - begin, end: The method list to output.
980 ///
981 /// The return value has type MethodDescriptionListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000982 llvm::Constant *EmitMethodDescList(llvm::Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000983 const char *Section,
984 const ConstantVector &Methods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000985
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000986 /// GetOrEmitProtocol - Get the protocol object for the given
987 /// declaration, emitting it if necessary. The return value has type
988 /// ProtocolPtrTy.
Fariborz Jahanianda320092009-01-29 19:24:30 +0000989 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000990
991 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
992 /// object for the given declaration, emitting it if needed. These
993 /// forward references will be filled in with empty bodies if no
994 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanianda320092009-01-29 19:24:30 +0000995 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000996
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000997 /// EmitProtocolExtension - Generate the protocol extension
998 /// structure used to store optional instance and class methods, and
999 /// protocol properties. The return value has type
1000 /// ProtocolExtensionPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001001 llvm::Constant *
1002 EmitProtocolExtension(const ObjCProtocolDecl *PD,
1003 const ConstantVector &OptInstanceMethods,
1004 const ConstantVector &OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001005
1006 /// EmitProtocolList - Generate the list of referenced
1007 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001008 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Daniel Dunbardbc933702008-08-21 21:57:41 +00001009 ObjCProtocolDecl::protocol_iterator begin,
1010 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001011
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001012 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1013 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001014 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1015 bool lval=false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001016
1017public:
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001018 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001019
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001020 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001021
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001022 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001023 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001024 QualType ResultType,
1025 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001026 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001027 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001028 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001029 const ObjCMethodDecl *Method);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001030
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001031 virtual CodeGen::RValue
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001032 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001033 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001034 QualType ResultType,
1035 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001036 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001037 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001038 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001039 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001040 const CallArgList &CallArgs,
1041 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001042
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001043 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001044 const ObjCInterfaceDecl *ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001045
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001046 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1047 bool lval = false);
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001048
1049 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1050 /// untyped one.
1051 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1052 const ObjCMethodDecl *Method);
1053
John McCall5a180392010-07-24 00:37:23 +00001054 virtual llvm::Constant *GetEHType(QualType T);
1055
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001056 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001057
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001058 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001059
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001060 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001061 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001062
Chris Lattner74391b42009-03-22 21:03:39 +00001063 virtual llvm::Constant *GetPropertyGetFunction();
1064 virtual llvm::Constant *GetPropertySetFunction();
David Chisnall8fac25d2010-12-26 22:13:16 +00001065 virtual llvm::Constant *GetGetStructFunction();
1066 virtual llvm::Constant *GetSetStructFunction();
Chris Lattner74391b42009-03-22 21:03:39 +00001067 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001068
John McCallf1549f62010-07-06 01:34:17 +00001069 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1070 const ObjCAtTryStmt &S);
1071 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1072 const ObjCAtSynchronizedStmt &S);
1073 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00001074 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1075 const ObjCAtThrowStmt &S);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001076 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001077 llvm::Value *AddrWeakObj);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001078 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001079 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001080 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001081 llvm::Value *src, llvm::Value *dest,
1082 bool threadlocal = false);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00001083 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001084 llvm::Value *src, llvm::Value *dest,
1085 llvm::Value *ivarOffset);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001086 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1087 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001088 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1089 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001090 llvm::Value *size);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001091
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001092 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1093 QualType ObjectTy,
1094 llvm::Value *BaseValue,
1095 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001096 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001097 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001098 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001099 const ObjCIvarDecl *Ivar);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001100};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001101
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001102class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001103private:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001104 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001105 llvm::GlobalVariable* ObjCEmptyCacheVar;
1106 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001107
Daniel Dunbar11394522009-04-18 08:51:00 +00001108 /// SuperClassReferences - uniqued super class references.
1109 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001110
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001111 /// MetaClassReferences - uniqued meta class references.
1112 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbare588b992009-03-01 04:46:24 +00001113
1114 /// EHTypeReferences - uniqued class ehtype references.
1115 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001116
John McCall944c8432011-05-14 03:10:52 +00001117 /// VTableDispatchMethods - List of methods for which we generate
1118 /// vtable-based message dispatch.
1119 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001120
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00001121 /// DefinedMetaClasses - List of defined meta-classes.
1122 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1123
John McCall944c8432011-05-14 03:10:52 +00001124 /// isVTableDispatchedSelector - Returns true if SEL is a
1125 /// vtable-based selector.
1126 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001127
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001128 /// FinishNonFragileABIModule - Write out global data structures at the end of
1129 /// processing a translation unit.
1130 void FinishNonFragileABIModule();
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001131
Daniel Dunbar463b8762009-05-15 21:48:48 +00001132 /// AddModuleClassList - Add the given list of class pointers to the
1133 /// module with the provided symbol and section names.
1134 void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
1135 const char *SymbolName,
1136 const char *SectionName);
1137
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001138 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1139 unsigned InstanceStart,
1140 unsigned InstanceSize,
1141 const ObjCImplementationDecl *ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001142 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001143 llvm::Constant *IsAGV,
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001144 llvm::Constant *SuperClassGV,
Fariborz Jahaniancf555162009-01-31 00:59:10 +00001145 llvm::Constant *ClassRoGV,
1146 bool HiddenVisibility);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001147
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001148 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001149
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00001150 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001151
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001152 /// EmitMethodList - Emit the method list for the given
1153 /// implementation. The return value has type MethodListnfABITy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001154 llvm::Constant *EmitMethodList(llvm::Twine Name,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001155 const char *Section,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00001156 const ConstantVector &Methods);
1157 /// EmitIvarList - Emit the ivar list for the given
1158 /// implementation. If ForClass is true the list of class ivars
1159 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1160 /// interface ivars will be emitted. The return value has type
1161 /// IvarListnfABIPtrTy.
1162 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001163
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001164 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00001165 const ObjCIvarDecl *Ivar,
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00001166 unsigned long int offset);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001167
Fariborz Jahanianda320092009-01-29 19:24:30 +00001168 /// GetOrEmitProtocol - Get the protocol object for the given
1169 /// declaration, emitting it if necessary. The return value has type
1170 /// ProtocolPtrTy.
1171 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001172
Fariborz Jahanianda320092009-01-29 19:24:30 +00001173 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1174 /// object for the given declaration, emitting it if needed. These
1175 /// forward references will be filled in with empty bodies if no
1176 /// definition is seen. The return value has type ProtocolPtrTy.
1177 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001178
Fariborz Jahanianda320092009-01-29 19:24:30 +00001179 /// EmitProtocolList - Generate the list of referenced
1180 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001181 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Fariborz Jahanianda320092009-01-29 19:24:30 +00001182 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian46551122009-02-04 00:22:57 +00001183 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001184
John McCall944c8432011-05-14 03:10:52 +00001185 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1186 ReturnValueSlot Return,
1187 QualType ResultType,
1188 Selector Sel,
1189 llvm::Value *Receiver,
1190 QualType Arg0Ty,
1191 bool IsSuper,
1192 const CallArgList &CallArgs,
1193 const ObjCMethodDecl *Method);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00001194
1195 /// GetClassGlobal - Return the global variable for the Objective-C
1196 /// class of the given name.
Fariborz Jahanian0f902942009-04-14 18:41:56 +00001197 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001198
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001199 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar11394522009-04-18 08:51:00 +00001200 /// for the given class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001201 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00001202 const ObjCInterfaceDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001203
Daniel Dunbar11394522009-04-18 08:51:00 +00001204 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1205 /// for the given super class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001206 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1207 const ObjCInterfaceDecl *ID);
1208
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001209 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1210 /// meta-data
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001211 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001212 const ObjCInterfaceDecl *ID);
1213
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001214 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1215 /// the given ivar.
1216 ///
Daniel Dunbar5e88bea2009-04-19 00:31:15 +00001217 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001218 const ObjCInterfaceDecl *ID,
1219 const ObjCIvarDecl *Ivar);
1220
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00001221 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1222 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001223 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1224 bool lval=false);
Daniel Dunbare588b992009-03-01 04:46:24 +00001225
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001226 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbare588b992009-03-01 04:46:24 +00001227 /// interface. The return value has type EHTypePtrTy.
John McCall5a180392010-07-24 00:37:23 +00001228 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001229 bool ForDefinition);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001230
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001231 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001232 return "OBJC_METACLASS_$_";
1233 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001234
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001235 const char *getClassSymbolPrefix() const {
1236 return "OBJC_CLASS_$_";
1237 }
1238
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00001239 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001240 uint32_t &InstanceStart,
1241 uint32_t &InstanceSize);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001242
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001243 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001244 Selector GetNullarySelector(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(0, &II);
1247 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001248
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001249 Selector GetUnarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001250 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1251 return CGM.getContext().Selectors.getSelector(1, &II);
1252 }
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001253
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001254 /// ImplementationIsNonLazy - Check whether the given category or
1255 /// class implementation is "non-lazy".
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00001256 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001257
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001258public:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001259 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001260 // FIXME. All stubs for now!
1261 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001262
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001263 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001264 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001265 QualType ResultType,
1266 Selector Sel,
1267 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001268 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001269 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001270 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001271
1272 virtual CodeGen::RValue
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001273 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001274 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001275 QualType ResultType,
1276 Selector Sel,
1277 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001278 bool isCategoryImpl,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001279 llvm::Value *Receiver,
1280 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001281 const CallArgList &CallArgs,
1282 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001283
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001284 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001285 const ObjCInterfaceDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001286
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001287 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1288 bool lvalue = false)
1289 { return EmitSelector(Builder, Sel, lvalue); }
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001290
1291 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1292 /// untyped one.
1293 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1294 const ObjCMethodDecl *Method)
1295 { return EmitSelector(Builder, Method->getSelector()); }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001296
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00001297 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001298
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001299 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001300 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00001301 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001302
John McCall5a180392010-07-24 00:37:23 +00001303 virtual llvm::Constant *GetEHType(QualType T);
1304
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001305 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001306 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001307 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001308 virtual llvm::Constant *GetPropertySetFunction() {
1309 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001310 }
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001311
David Chisnall8fac25d2010-12-26 22:13:16 +00001312 virtual llvm::Constant *GetSetStructFunction() {
1313 return ObjCTypes.getCopyStructFn();
1314 }
1315 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001316 return ObjCTypes.getCopyStructFn();
1317 }
1318
Chris Lattner74391b42009-03-22 21:03:39 +00001319 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001320 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbar28ed0842009-02-16 18:48:45 +00001321 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001322
John McCallf1549f62010-07-06 01:34:17 +00001323 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1324 const ObjCAtTryStmt &S);
1325 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1326 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001327 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlssonf57c5b22009-02-16 22:59:18 +00001328 const ObjCAtThrowStmt &S);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001329 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001330 llvm::Value *AddrWeakObj);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001331 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001332 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001333 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001334 llvm::Value *src, llvm::Value *dest,
1335 bool threadlocal = false);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001336 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001337 llvm::Value *src, llvm::Value *dest,
1338 llvm::Value *ivarOffset);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001339 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001340 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001341 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1342 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001343 llvm::Value *size);
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001344 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1345 QualType ObjectTy,
1346 llvm::Value *BaseValue,
1347 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001348 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001349 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001350 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001351 const ObjCIvarDecl *Ivar);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001352};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001353
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001354} // end anonymous namespace
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001355
1356/* *** Helper Functions *** */
1357
1358/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Andersona1cf15f2009-07-14 23:10:40 +00001359static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001360 llvm::Constant *C,
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001361 unsigned idx0,
1362 unsigned idx1) {
1363 llvm::Value *Idxs[] = {
Owen Anderson0032b272009-08-13 21:57:51 +00001364 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1365 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001366 };
Owen Anderson3c4972d2009-07-29 18:54:39 +00001367 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001368}
1369
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001370/// hasObjCExceptionAttribute - Return true if this class or any super
1371/// class has the __objc_exception__ attribute.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001372static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor68584ed2009-06-18 16:11:24 +00001373 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidis40b598e2009-06-30 02:34:44 +00001374 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001375 return true;
1376 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor68584ed2009-06-18 16:11:24 +00001377 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001378 return false;
1379}
1380
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001381/* *** CGObjCMac Public Interface *** */
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001382
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001383CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00001384 ObjCTypes(cgm) {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001385 ObjCABI = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001386 EmitImageInfo();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001387}
1388
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +00001389/// GetClass - Return a reference to the class for the given interface
1390/// decl.
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001391llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001392 const ObjCInterfaceDecl *ID) {
1393 return EmitClassRef(Builder, ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001394}
1395
1396/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001397llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1398 bool lval) {
1399 return EmitSelector(Builder, Sel, lval);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001400}
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001401llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001402 *Method) {
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001403 return EmitSelector(Builder, Method->getSelector());
1404}
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001405
John McCall5a180392010-07-24 00:37:23 +00001406llvm::Constant *CGObjCMac::GetEHType(QualType T) {
1407 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
1408 return 0;
1409}
1410
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001411/// Generate a constant CFString object.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001412/*
1413 struct __builtin_CFString {
1414 const int *isa; // point to __CFConstantStringClassReference
1415 int flags;
1416 const char *str;
1417 long length;
1418 };
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001419*/
1420
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001421/// or Generate a constant NSString object.
1422/*
1423 struct __builtin_NSString {
1424 const int *isa; // point to __NSConstantStringClassReference
1425 const char *str;
1426 unsigned int length;
1427 };
1428*/
1429
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001430llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall0d13f6f2010-01-23 02:40:42 +00001431 const StringLiteral *SL) {
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001432 return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
1433 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian4c733072010-10-19 17:19:29 +00001434 CGM.GetAddrOfConstantString(SL));
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001435}
1436
1437/// Generates a message send where the super is the receiver. This is
1438/// a message send to self with special delivery semantics indicating
1439/// which class's method should be called.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001440CodeGen::RValue
1441CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001442 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001443 QualType ResultType,
1444 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001445 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001446 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001447 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001448 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001449 const CodeGen::CallArgList &CallArgs,
1450 const ObjCMethodDecl *Method) {
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001451 // Create and init a super structure; this is a (receiver, class)
1452 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001453 llvm::Value *ObjCSuper =
John McCall604da292011-03-04 08:00:29 +00001454 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001455 llvm::Value *ReceiverAsObject =
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001456 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001457 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001458 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001459
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001460 // If this is a class message the metaclass is passed as the target.
1461 llvm::Value *Target;
1462 if (IsClassMessage) {
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001463 if (isCategoryImpl) {
1464 // Message sent to 'super' in a class method defined in a category
1465 // implementation requires an odd treatment.
1466 // If we are in a class method, we must retrieve the
1467 // _metaclass_ for the current class, pointed at by
1468 // the class's "isa" pointer. The following assumes that
1469 // isa" is the first ivar in a class (which it must be).
1470 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1471 Target = CGF.Builder.CreateStructGEP(Target, 0);
1472 Target = CGF.Builder.CreateLoad(Target);
Mike Stumpb3589f42009-07-30 22:28:39 +00001473 } else {
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001474 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1475 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1476 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1477 Target = Super;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001478 }
Fariborz Jahanian182f2682009-11-14 02:18:31 +00001479 }
1480 else if (isCategoryImpl)
1481 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1482 else {
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00001483 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1484 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1485 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001486 }
Mike Stumpf5408fe2009-05-16 07:57:57 +00001487 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1488 // ObjCTypes types.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001489 const llvm::Type *ClassTy =
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001490 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001491 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001492 CGF.Builder.CreateStore(Target,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001493 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall944c8432011-05-14 03:10:52 +00001494 return EmitMessageSend(CGF, Return, ResultType,
1495 EmitSelector(CGF.Builder, Sel),
1496 ObjCSuper, ObjCTypes.SuperPtrCTy,
1497 true, CallArgs, Method, ObjCTypes);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001498}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001499
1500/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001501CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001502 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001503 QualType ResultType,
1504 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001505 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001506 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001507 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001508 const ObjCMethodDecl *Method) {
John McCall944c8432011-05-14 03:10:52 +00001509 return EmitMessageSend(CGF, Return, ResultType,
1510 EmitSelector(CGF.Builder, Sel),
1511 Receiver, CGF.getContext().getObjCIdType(),
1512 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00001513}
1514
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001515CodeGen::RValue
John McCall944c8432011-05-14 03:10:52 +00001516CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1517 ReturnValueSlot Return,
1518 QualType ResultType,
1519 llvm::Value *Sel,
1520 llvm::Value *Arg0,
1521 QualType Arg0Ty,
1522 bool IsSuper,
1523 const CallArgList &CallArgs,
1524 const ObjCMethodDecl *Method,
1525 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001526 CallArgList ActualArgs;
Fariborz Jahaniand019d962009-04-24 21:07:43 +00001527 if (!IsSuper)
1528 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Eli Friedman04c9a492011-05-02 17:57:46 +00001529 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1530 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001531 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001532
Daniel Dunbar541b63b2009-02-02 23:23:47 +00001533 CodeGenTypes &Types = CGM.getTypes();
John McCall04a67a62010-02-05 21:31:56 +00001534 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindola264ba482010-03-30 20:24:48 +00001535 FunctionType::ExtInfo());
Daniel Dunbar67939662009-09-17 04:01:40 +00001536 const llvm::FunctionType *FTy =
1537 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001538
Anders Carlsson7e70fb22010-06-21 20:59:55 +00001539 if (Method)
1540 assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1541 CGM.getContext().getCanonicalType(ResultType) &&
1542 "Result type mismatch!");
1543
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001544 llvm::Constant *Fn = NULL;
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001545 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
John McCall448d2cd2011-02-26 09:48:59 +00001546 EmitNullReturnInitialization(CGF, Return, ResultType);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001547 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001548 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001549 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1550 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1551 : ObjCTypes.getSendFpretFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001552 } else {
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001553 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001554 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001555 }
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001556 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
John McCallef072fd2010-05-22 01:48:05 +00001557 return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001558}
1559
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001560static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1561 if (FQT.isObjCGCStrong())
1562 return Qualifiers::Strong;
1563
1564 if (FQT.isObjCGCWeak())
1565 return Qualifiers::Weak;
1566
1567 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1568 return Qualifiers::Strong;
1569
1570 if (const PointerType *PT = FQT->getAs<PointerType>())
1571 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1572
1573 return Qualifiers::GCNone;
1574}
1575
John McCall6b5a61b2011-02-07 10:33:21 +00001576llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1577 const CGBlockInfo &blockInfo) {
1578 llvm::Constant *nullPtr =
Fariborz Jahanian44034db2010-08-04 18:44:59 +00001579 llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
John McCall6b5a61b2011-02-07 10:33:21 +00001580
Fariborz Jahanianfb550312010-09-13 16:09:44 +00001581 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
John McCall6b5a61b2011-02-07 10:33:21 +00001582 return nullPtr;
1583
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001584 bool hasUnion = false;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001585 SkipIvars.clear();
1586 IvarsInfo.clear();
1587 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
1588 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
1589
Fariborz Jahanian81979822010-09-09 00:21:45 +00001590 // __isa is the first field in block descriptor and must assume by runtime's
1591 // convention that it is GC'able.
1592 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall6b5a61b2011-02-07 10:33:21 +00001593
1594 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1595
1596 // Calculate the basic layout of the block structure.
1597 const llvm::StructLayout *layout =
1598 CGM.getTargetData().getStructLayout(blockInfo.StructureType);
1599
1600 // Ignore the optional 'this' capture: C++ objects are not assumed
1601 // to be GC'ed.
1602
1603 // Walk the captured variables.
1604 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1605 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1606 const VarDecl *variable = ci->getVariable();
1607 QualType type = variable->getType();
1608
1609 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1610
1611 // Ignore constant captures.
1612 if (capture.isConstant()) continue;
1613
1614 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
1615
1616 // __block variables are passed by their descriptor address.
1617 if (ci->isByRef()) {
1618 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanianc5904b42010-09-11 01:27:29 +00001619 continue;
John McCall6b5a61b2011-02-07 10:33:21 +00001620 }
1621
1622 assert(!type->isArrayType() && "array variable should not be caught");
1623 if (const RecordType *record = type->getAs<RecordType>()) {
1624 BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
Fariborz Jahaniane1a48982010-08-05 21:00:25 +00001625 continue;
1626 }
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001627
John McCall6b5a61b2011-02-07 10:33:21 +00001628 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
1629 unsigned fieldSize = CGM.getContext().getTypeSize(type);
1630
1631 if (GCAttr == Qualifiers::Strong)
1632 IvarsInfo.push_back(GC_IVAR(fieldOffset,
1633 fieldSize / WordSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001634 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
John McCall6b5a61b2011-02-07 10:33:21 +00001635 SkipIvars.push_back(GC_IVAR(fieldOffset,
1636 fieldSize / ByteSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001637 }
1638
1639 if (IvarsInfo.empty())
John McCall6b5a61b2011-02-07 10:33:21 +00001640 return nullPtr;
1641
1642 // Sort on byte position; captures might not be allocated in order,
1643 // and unions can do funny things.
1644 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
1645 llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001646
1647 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00001648 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001649 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
1650 printf("\n block variable layout for block: ");
1651 const unsigned char *s = (unsigned char*)BitMap.c_str();
1652 for (unsigned i = 0; i < BitMap.size(); i++)
1653 if (!(s[i] & 0xf0))
1654 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1655 else
1656 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
1657 printf("\n");
1658 }
1659
1660 return C;
Fariborz Jahanian89ecd412010-08-04 16:57:49 +00001661}
1662
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001663llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001664 const ObjCProtocolDecl *PD) {
Daniel Dunbarc67876d2008-09-04 04:33:15 +00001665 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00001666 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc67876d2008-09-04 04:33:15 +00001667 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1668
Owen Anderson3c4972d2009-07-29 18:54:39 +00001669 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001670 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001671}
1672
Fariborz Jahanianda320092009-01-29 19:24:30 +00001673void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stumpf5408fe2009-05-16 07:57:57 +00001674 // FIXME: We shouldn't need this, the protocol decl should contain enough
1675 // information to tell us whether this was a declaration or a definition.
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001676 DefinedProtocols.insert(PD->getIdentifier());
1677
1678 // If we have generated a forward reference to this protocol, emit
1679 // it now. Otherwise do nothing, the protocol objects are lazily
1680 // emitted.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001681 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001682 GetOrEmitProtocol(PD);
1683}
1684
Fariborz Jahanianda320092009-01-29 19:24:30 +00001685llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001686 if (DefinedProtocols.count(PD->getIdentifier()))
1687 return GetOrEmitProtocol(PD);
1688 return GetOrEmitProtocolRef(PD);
1689}
1690
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001691/*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001692// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1693struct _objc_protocol {
1694struct _objc_protocol_extension *isa;
1695char *protocol_name;
1696struct _objc_protocol_list *protocol_list;
1697struct _objc__method_prototype_list *instance_methods;
1698struct _objc__method_prototype_list *class_methods
1699};
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001700
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001701See EmitProtocolExtension().
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001702*/
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001703llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1704 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1705
1706 // Early exit if a defining object has already been generated.
1707 if (Entry && Entry->hasInitializer())
1708 return Entry;
1709
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00001710 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00001711 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00001712 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1713
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001714 // Construct method lists.
1715 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1716 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001717 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001718 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001719 ObjCMethodDecl *MD = *i;
1720 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1721 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1722 OptInstanceMethods.push_back(C);
1723 } else {
1724 InstanceMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001725 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001726 }
1727
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001728 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001729 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001730 ObjCMethodDecl *MD = *i;
1731 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1732 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1733 OptClassMethods.push_back(C);
1734 } else {
1735 ClassMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001736 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001737 }
1738
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001739 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001740 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001741 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001742 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001743 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardbc933702008-08-21 21:57:41 +00001744 PD->protocol_begin(),
1745 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001746 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001747 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001748 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1749 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001750 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001751 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001752 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1753 ClassMethods);
Owen Anderson08e25242009-07-27 22:29:56 +00001754 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001755 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001756
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001757 if (Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001758 // Already created, fix the linkage and update the initializer.
1759 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001760 Entry->setInitializer(Init);
1761 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001762 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00001763 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001764 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001765 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001766 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001767 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001768 // FIXME: Is this necessary? Why only for protocol?
1769 Entry->setAlignment(4);
1770 }
Chris Lattnerad64e022009-07-17 23:57:13 +00001771 CGM.AddUsedGlobal(Entry);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001772
1773 return Entry;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001774}
1775
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001776llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001777 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1778
1779 if (!Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001780 // We use the initializer as a marker of whether this is a forward
1781 // reference or not. At module finalization we add the empty
1782 // contents for protocols which were referenced but never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001783 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00001784 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001785 llvm::GlobalValue::ExternalLinkage,
1786 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001787 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001788 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001789 // FIXME: Is this necessary? Why only for protocol?
1790 Entry->setAlignment(4);
1791 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001792
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001793 return Entry;
1794}
1795
1796/*
1797 struct _objc_protocol_extension {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001798 uint32_t size;
1799 struct objc_method_description_list *optional_instance_methods;
1800 struct objc_method_description_list *optional_class_methods;
1801 struct objc_property_list *instance_properties;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001802 };
1803*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001804llvm::Constant *
1805CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1806 const ConstantVector &OptInstanceMethods,
1807 const ConstantVector &OptClassMethods) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001808 uint64_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00001809 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001810 std::vector<llvm::Constant*> Values(4);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001811 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001812 Values[1] =
1813 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001814 + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001815 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1816 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001817 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001818 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001819 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1820 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001821 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00001822 0, PD, ObjCTypes);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001823
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001824 // Return null if no extension bits are used.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001825 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001826 Values[3]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001827 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001828
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001829 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00001830 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001831
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001832 // No special section, but goes in llvm.used
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001833 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001834 Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001835 0, 0, true);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001836}
1837
1838/*
1839 struct objc_protocol_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001840 struct objc_protocol_list *next;
1841 long count;
1842 Protocol *list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001843 };
1844*/
Daniel Dunbardbc933702008-08-21 21:57:41 +00001845llvm::Constant *
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001846CGObjCMac::EmitProtocolList(llvm::Twine Name,
Daniel Dunbardbc933702008-08-21 21:57:41 +00001847 ObjCProtocolDecl::protocol_iterator begin,
1848 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001849 std::vector<llvm::Constant*> ProtocolRefs;
1850
Daniel Dunbardbc933702008-08-21 21:57:41 +00001851 for (; begin != end; ++begin)
1852 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001853
1854 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001855 if (ProtocolRefs.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001856 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001857
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001858 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00001859 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001860
1861 std::vector<llvm::Constant*> Values(3);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001862 // This field is only used by the runtime.
Owen Andersonc9c88b42009-07-31 20:28:54 +00001863 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001864 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001865 ProtocolRefs.size() - 1);
1866 Values[2] =
1867 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1868 ProtocolRefs.size()),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001869 ProtocolRefs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001870
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001871 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001872 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001873 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00001874 4, false);
Owen Anderson3c4972d2009-07-29 18:54:39 +00001875 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001876}
1877
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001878void CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
1879 std::vector<llvm::Constant*> &Properties,
1880 const Decl *Container,
1881 const ObjCProtocolDecl *PROTO,
1882 const ObjCCommonTypesHelper &ObjCTypes) {
1883 std::vector<llvm::Constant*> Prop(2);
1884 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
1885 E = PROTO->protocol_end(); P != E; ++P)
1886 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
1887 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
1888 E = PROTO->prop_end(); I != E; ++I) {
1889 const ObjCPropertyDecl *PD = *I;
1890 if (!PropertySet.insert(PD->getIdentifier()))
1891 continue;
1892 Prop[0] = GetPropertyName(PD->getIdentifier());
1893 Prop[1] = GetPropertyTypeString(PD, Container);
1894 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
1895 }
1896}
1897
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001898/*
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001899 struct _objc_property {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001900 const char * const name;
1901 const char * const attributes;
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001902 };
1903
1904 struct _objc_property_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001905 uint32_t entsize; // sizeof (struct _objc_property)
1906 uint32_t prop_count;
1907 struct _objc_property[prop_count];
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001908 };
1909*/
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001910llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001911 const Decl *Container,
1912 const ObjCContainerDecl *OCD,
1913 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001914 std::vector<llvm::Constant*> Properties, Prop(2);
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001915 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001916 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1917 E = OCD->prop_end(); I != E; ++I) {
Steve Naroff93983f82009-01-11 12:47:58 +00001918 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001919 PropertySet.insert(PD->getIdentifier());
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001920 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00001921 Prop[1] = GetPropertyTypeString(PD, Container);
Owen Anderson08e25242009-07-27 22:29:56 +00001922 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001923 Prop));
1924 }
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00001925 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek53b94412010-09-01 01:21:15 +00001926 for (ObjCInterfaceDecl::all_protocol_iterator
1927 P = OID->all_referenced_protocol_begin(),
1928 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00001929 PushProtocolProperties(PropertySet, Properties, Container, (*P),
1930 ObjCTypes);
1931 }
1932 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
1933 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
1934 E = CD->protocol_end(); P != E; ++P)
1935 PushProtocolProperties(PropertySet, Properties, Container, (*P),
1936 ObjCTypes);
1937 }
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001938
1939 // Return null for empty list.
1940 if (Properties.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001941 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001942
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001943 unsigned PropertySize =
Duncan Sands9408c452009-05-09 07:08:47 +00001944 CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001945 std::vector<llvm::Constant*> Values(3);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001946 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
1947 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001948 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001949 Properties.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00001950 Values[2] = llvm::ConstantArray::get(AT, Properties);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001951 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001952
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001953 llvm::GlobalVariable *GV =
1954 CreateMetadataVar(Name, Init,
1955 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbar0bf21992009-04-15 02:56:18 +00001956 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001957 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbar0bf21992009-04-15 02:56:18 +00001958 true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00001959 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001960}
1961
1962/*
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001963 struct objc_method_description_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001964 int count;
1965 struct objc_method_description list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001966 };
1967*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001968llvm::Constant *
1969CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
1970 std::vector<llvm::Constant*> Desc(2);
Owen Andersona1cf15f2009-07-14 23:10:40 +00001971 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001972 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1973 ObjCTypes.SelectorPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001974 Desc[1] = GetMethodVarType(MD);
Owen Anderson08e25242009-07-27 22:29:56 +00001975 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001976 Desc);
1977}
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001978
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001979llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001980 const char *Section,
1981 const ConstantVector &Methods) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001982 // Return null for empty list.
1983 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001984 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001985
1986 std::vector<llvm::Constant*> Values(2);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001987 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001988 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001989 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00001990 Values[1] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001991 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001992
Daniel Dunbar0bf21992009-04-15 02:56:18 +00001993 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001994 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001995 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001996}
1997
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001998/*
1999 struct _objc_category {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002000 char *category_name;
2001 char *class_name;
2002 struct _objc_method_list *instance_methods;
2003 struct _objc_method_list *class_methods;
2004 struct _objc_protocol_list *protocols;
2005 uint32_t size; // <rdar://4585769>
2006 struct _objc_property_list *instance_properties;
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002007 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002008*/
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00002009void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Duncan Sands9408c452009-05-09 07:08:47 +00002010 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002011
Mike Stumpf5408fe2009-05-16 07:57:57 +00002012 // FIXME: This is poor design, the OCD should have a pointer to the category
2013 // decl. Additionally, note that Category can be null for the @implementation
2014 // w/o an @interface case. Sema should just create one for us as it does for
2015 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002016 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002017 const ObjCCategoryDecl *Category =
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002018 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002019
2020 llvm::SmallString<256> ExtName;
2021 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2022 << OCD->getName();
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002023
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002024 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002025 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002026 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002027 // Instance methods should always be defined.
2028 InstanceMethods.push_back(GetMethodConstant(*i));
2029 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002030 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002031 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002032 // Class methods should always be defined.
2033 ClassMethods.push_back(GetMethodConstant(*i));
2034 }
2035
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002036 std::vector<llvm::Constant*> Values(7);
2037 Values[0] = GetClassName(OCD->getIdentifier());
2038 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahanian679cd7f2009-04-29 20:40:05 +00002039 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002040 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002041 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002042 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002043 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002044 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002045 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002046 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002047 ClassMethods);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002048 if (Category) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002049 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002050 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002051 Category->protocol_begin(),
2052 Category->protocol_end());
2053 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002054 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002055 }
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002056 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002057
2058 // If there is no category @interface then there can be no properties.
2059 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002060 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002061 OCD, Category, ObjCTypes);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002062 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002063 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002064 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002065
Owen Anderson08e25242009-07-27 22:29:56 +00002066 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002067 Values);
2068
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002069 llvm::GlobalVariable *GV =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002070 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002071 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002072 4, true);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002073 DefinedCategories.push_back(GV);
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00002074 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00002075 // method definition entries must be clear for next implementation.
2076 MethodDefinitions.clear();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002077}
2078
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002079// FIXME: Get from somewhere?
2080enum ClassFlags {
2081 eClassFlags_Factory = 0x00001,
2082 eClassFlags_Meta = 0x00002,
2083 // <rdr://5142207>
2084 eClassFlags_HasCXXStructors = 0x02000,
2085 eClassFlags_Hidden = 0x20000,
2086 eClassFlags_ABI2_Hidden = 0x00010,
2087 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
2088};
2089
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002090/*
2091 struct _objc_class {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002092 Class isa;
2093 Class super_class;
2094 const char *name;
2095 long version;
2096 long info;
2097 long instance_size;
2098 struct _objc_ivar_list *ivars;
2099 struct _objc_method_list *methods;
2100 struct _objc_cache *cache;
2101 struct _objc_protocol_list *protocols;
2102 // Objective-C 1.0 extensions (<rdr://4585769>)
2103 const char *ivar_layout;
2104 struct _objc_class_ext *ext;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002105 };
2106
2107 See EmitClassExtension();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002108*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002109void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002110 DefinedSymbols.insert(ID->getIdentifier());
2111
Chris Lattner8ec03f52008-11-24 03:54:41 +00002112 std::string ClassName = ID->getNameAsString();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002113 // FIXME: Gross
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002114 ObjCInterfaceDecl *Interface =
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002115 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002116 llvm::Constant *Protocols =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002117 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00002118 Interface->all_referenced_protocol_begin(),
2119 Interface->all_referenced_protocol_end());
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002120 unsigned Flags = eClassFlags_Factory;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00002121 if (ID->getNumIvarInitializers())
2122 Flags |= eClassFlags_HasCXXStructors;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002123 unsigned Size =
Ken Dyck5f022d82011-02-09 01:59:34 +00002124 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002125
2126 // FIXME: Set CXX-structors flag.
John McCall1fb0caa2010-10-22 21:05:15 +00002127 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002128 Flags |= eClassFlags_Hidden;
2129
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002130 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002131 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002132 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002133 // Instance methods should always be defined.
2134 InstanceMethods.push_back(GetMethodConstant(*i));
2135 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002136 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002137 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002138 // Class methods should always be defined.
2139 ClassMethods.push_back(GetMethodConstant(*i));
2140 }
2141
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002142 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002143 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002144 ObjCPropertyImplDecl *PID = *i;
2145
2146 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2147 ObjCPropertyDecl *PD = PID->getPropertyDecl();
2148
2149 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2150 if (llvm::Constant *C = GetMethodConstant(MD))
2151 InstanceMethods.push_back(C);
2152 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2153 if (llvm::Constant *C = GetMethodConstant(MD))
2154 InstanceMethods.push_back(C);
2155 }
2156 }
2157
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002158 std::vector<llvm::Constant*> Values(12);
Daniel Dunbar5384b092009-05-03 08:56:52 +00002159 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002160 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002161 // Record a reference to the super class.
2162 LazySymbols.insert(Super->getIdentifier());
2163
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002164 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002165 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002166 ObjCTypes.ClassPtrTy);
2167 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002168 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002169 }
2170 Values[ 2] = GetClassName(ID->getIdentifier());
2171 // Version is always 0.
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002172 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2173 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2174 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002175 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002176 Values[ 7] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002177 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002178 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002179 InstanceMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002180 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002181 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002182 Values[ 9] = Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002183 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002184 Values[11] = EmitClassExtension(ID);
Owen Anderson08e25242009-07-27 22:29:56 +00002185 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002186 Values);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00002187 std::string Name("\01L_OBJC_CLASS_");
2188 Name += ClassName;
2189 const char *Section = "__OBJC,__class,regular,no_dead_strip";
2190 // Check for a forward reference.
2191 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2192 if (GV) {
2193 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2194 "Forward metaclass reference has incorrect type.");
2195 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2196 GV->setInitializer(Init);
2197 GV->setSection(Section);
2198 GV->setAlignment(4);
2199 CGM.AddUsedGlobal(GV);
2200 }
2201 else
2202 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002203 DefinedClasses.push_back(GV);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00002204 // method definition entries must be clear for next implementation.
2205 MethodDefinitions.clear();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002206}
2207
2208llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2209 llvm::Constant *Protocols,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002210 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002211 unsigned Flags = eClassFlags_Meta;
Duncan Sands9408c452009-05-09 07:08:47 +00002212 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002213
John McCall1fb0caa2010-10-22 21:05:15 +00002214 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002215 Flags |= eClassFlags_Hidden;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002216
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002217 std::vector<llvm::Constant*> Values(12);
2218 // The isa for the metaclass is the root of the hierarchy.
2219 const ObjCInterfaceDecl *Root = ID->getClassInterface();
2220 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2221 Root = Super;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002222 Values[ 0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002223 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002224 ObjCTypes.ClassPtrTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002225 // The super class for the metaclass is emitted as the name of the
2226 // super class. The runtime fixes this up to point to the
2227 // *metaclass* for the super class.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002228 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002229 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002230 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002231 ObjCTypes.ClassPtrTy);
2232 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002233 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002234 }
2235 Values[ 2] = GetClassName(ID->getIdentifier());
2236 // Version is always 0.
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002237 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2238 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2239 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002240 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002241 Values[ 7] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00002242 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002243 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002244 Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002245 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002246 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002247 Values[ 9] = Protocols;
2248 // ivar_layout for metaclass is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002249 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002250 // The class extension is always unused for metaclasses.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002251 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00002252 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002253 Values);
2254
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002255 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner8ec03f52008-11-24 03:54:41 +00002256 Name += ID->getNameAsCString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002257
2258 // Check for a forward reference.
2259 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2260 if (GV) {
2261 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2262 "Forward metaclass reference has incorrect type.");
2263 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2264 GV->setInitializer(Init);
2265 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00002266 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002267 llvm::GlobalValue::InternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00002268 Init, Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002269 }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002270 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbar58a29122009-03-09 22:18:41 +00002271 GV->setAlignment(4);
Chris Lattnerad64e022009-07-17 23:57:13 +00002272 CGM.AddUsedGlobal(GV);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002273
2274 return GV;
2275}
2276
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002277llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00002278 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002279
Mike Stumpf5408fe2009-05-16 07:57:57 +00002280 // FIXME: Should we look these up somewhere other than the module. Its a bit
2281 // silly since we only generate these while processing an implementation, so
2282 // exactly one pointer would work if know when we entered/exitted an
2283 // implementation block.
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002284
2285 // Check for an existing forward reference.
Fariborz Jahanianb0d27942009-01-07 20:11:22 +00002286 // Previously, metaclass with internal linkage may have been defined.
2287 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002288 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2289 true)) {
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002290 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2291 "Forward metaclass reference has incorrect type.");
2292 return GV;
2293 } else {
2294 // Generate as an external reference to keep a consistent
2295 // module. This will be patched up when we emit the metaclass.
Owen Anderson1c431b32009-07-08 19:05:04 +00002296 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002297 llvm::GlobalValue::ExternalLinkage,
2298 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00002299 Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002300 }
2301}
2302
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00002303llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2304 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2305
2306 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2307 true)) {
2308 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2309 "Forward class metadata reference has incorrect type.");
2310 return GV;
2311 } else {
2312 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2313 llvm::GlobalValue::ExternalLinkage,
2314 0,
2315 Name);
2316 }
2317}
2318
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002319/*
2320 struct objc_class_ext {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002321 uint32_t size;
2322 const char *weak_ivar_layout;
2323 struct _objc_property_list *properties;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002324 };
2325*/
2326llvm::Constant *
2327CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002328 uint64_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00002329 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002330
2331 std::vector<llvm::Constant*> Values(3);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002332 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanianc71303d2009-04-22 23:00:43 +00002333 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002334 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002335 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002336
2337 // Return null if no extension bits are used.
2338 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002339 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002340
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002341 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00002342 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002343 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002344 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002345 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002346}
2347
2348/*
2349 struct objc_ivar {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002350 char *ivar_name;
2351 char *ivar_type;
2352 int ivar_offset;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002353 };
2354
2355 struct objc_ivar_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002356 int ivar_count;
2357 struct objc_ivar list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002358 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002359*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002360llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002361 bool ForClass) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002362 std::vector<llvm::Constant*> Ivars, Ivar(3);
2363
2364 // When emitting the root class GCC emits ivar entries for the
2365 // actual class structure. It is not clear if we need to follow this
2366 // behavior; for now lets try and get away with not doing it. If so,
2367 // the cleanest solution would be to make up an ObjCInterfaceDecl
2368 // for the class.
2369 if (ForClass)
Owen Andersonc9c88b42009-07-31 20:28:54 +00002370 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002371
2372 ObjCInterfaceDecl *OID =
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002373 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002374
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00002375 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00002376 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002377
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00002378 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2379 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00002380 // Ignore unnamed bit-fields.
2381 if (!IVD->getDeclName())
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002382 continue;
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00002383 Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2384 Ivar[1] = GetMethodVarType(IVD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002385 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
Daniel Dunbar97776872009-04-22 07:32:20 +00002386 ComputeIvarBaseOffset(CGM, OID, IVD));
Owen Anderson08e25242009-07-27 22:29:56 +00002387 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002388 }
2389
2390 // Return null for empty list.
2391 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002392 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002393
2394 std::vector<llvm::Constant*> Values(2);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002395 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00002396 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002397 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002398 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002399 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002400
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002401 llvm::GlobalVariable *GV;
2402 if (ForClass)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002403 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002404 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002405 4, true);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002406 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002407 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002408 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002409 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002410 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002411}
2412
2413/*
2414 struct objc_method {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002415 SEL method_name;
2416 char *method_types;
2417 void *method;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002418 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002419
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002420 struct objc_method_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002421 struct objc_method_list *obsolete;
2422 int count;
2423 struct objc_method methods_list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002424 };
2425*/
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002426
2427/// GetMethodConstant - Return a struct objc_method constant for the
2428/// given method if it has been defined. The result is null if the
2429/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002430llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00002431 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002432 if (!Fn)
2433 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002434
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002435 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002436 Method[0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002437 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002438 ObjCTypes.SelectorPtrTy);
2439 Method[1] = GetMethodVarType(MD);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002440 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00002441 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002442}
2443
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002444llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002445 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002446 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002447 // Return null for empty list.
2448 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002449 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002450
2451 std::vector<llvm::Constant*> Values(3);
Owen Andersonc9c88b42009-07-31 20:28:54 +00002452 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002453 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00002454 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002455 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002456 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002457 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002458
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002459 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002460 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002461 ObjCTypes.MethodListPtrTy);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002462}
2463
Fariborz Jahanian493dab72009-01-26 21:38:32 +00002464llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002465 const ObjCContainerDecl *CD) {
Daniel Dunbarc575ce72009-10-19 01:21:19 +00002466 llvm::SmallString<256> Name;
Fariborz Jahanian679a5022009-01-10 21:06:09 +00002467 GetNameForMethod(OMD, CD, Name);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002468
Daniel Dunbar541b63b2009-02-02 23:23:47 +00002469 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00002470 const llvm::FunctionType *MethodTy =
Daniel Dunbar541b63b2009-02-02 23:23:47 +00002471 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002472 llvm::Function *Method =
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00002473 llvm::Function::Create(MethodTy,
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002474 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00002475 Name.str(),
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002476 &CGM.getModule());
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002477 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002478
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002479 return Method;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002480}
2481
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002482llvm::GlobalVariable *
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002483CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002484 llvm::Constant *Init,
2485 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +00002486 unsigned Align,
2487 bool AddToUsed) {
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002488 const llvm::Type *Ty = Init->getType();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002489 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00002490 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerad64e022009-07-17 23:57:13 +00002491 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002492 if (Section)
2493 GV->setSection(Section);
Daniel Dunbar35bd7632009-03-09 20:50:13 +00002494 if (Align)
2495 GV->setAlignment(Align);
2496 if (AddToUsed)
Chris Lattnerad64e022009-07-17 23:57:13 +00002497 CGM.AddUsedGlobal(GV);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002498 return GV;
2499}
2500
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002501llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002502 // Abuse this interface function as a place to finalize.
2503 FinishModule();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002504 return NULL;
2505}
2506
Chris Lattner74391b42009-03-22 21:03:39 +00002507llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002508 return ObjCTypes.getGetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00002509}
2510
Chris Lattner74391b42009-03-22 21:03:39 +00002511llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002512 return ObjCTypes.getSetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00002513}
2514
David Chisnall8fac25d2010-12-26 22:13:16 +00002515llvm::Constant *CGObjCMac::GetGetStructFunction() {
2516 return ObjCTypes.getCopyStructFn();
2517}
2518llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00002519 return ObjCTypes.getCopyStructFn();
2520}
2521
Chris Lattner74391b42009-03-22 21:03:39 +00002522llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002523 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson2abd89c2008-08-31 04:05:03 +00002524}
2525
John McCallf1549f62010-07-06 01:34:17 +00002526void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
2527 return EmitTryOrSynchronizedStmt(CGF, S);
2528}
2529
2530void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
2531 const ObjCAtSynchronizedStmt &S) {
2532 return EmitTryOrSynchronizedStmt(CGF, S);
2533}
2534
John McCallcc505292010-07-21 06:59:36 +00002535namespace {
John McCall1f0fca52010-07-21 07:22:38 +00002536 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCallcc505292010-07-21 06:59:36 +00002537 const Stmt &S;
John McCall0b251722010-08-04 05:59:32 +00002538 llvm::Value *SyncArgSlot;
John McCallcc505292010-07-21 06:59:36 +00002539 llvm::Value *CallTryExitVar;
2540 llvm::Value *ExceptionData;
2541 ObjCTypesHelper &ObjCTypes;
2542 PerformFragileFinally(const Stmt *S,
John McCall0b251722010-08-04 05:59:32 +00002543 llvm::Value *SyncArgSlot,
John McCallcc505292010-07-21 06:59:36 +00002544 llvm::Value *CallTryExitVar,
2545 llvm::Value *ExceptionData,
2546 ObjCTypesHelper *ObjCTypes)
John McCall0b251722010-08-04 05:59:32 +00002547 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCallcc505292010-07-21 06:59:36 +00002548 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
2549
2550 void Emit(CodeGenFunction &CGF, bool IsForEH) {
2551 // Check whether we need to call objc_exception_try_exit.
2552 // In optimized code, this branch will always be folded.
2553 llvm::BasicBlock *FinallyCallExit =
2554 CGF.createBasicBlock("finally.call_exit");
2555 llvm::BasicBlock *FinallyNoCallExit =
2556 CGF.createBasicBlock("finally.no_call_exit");
2557 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
2558 FinallyCallExit, FinallyNoCallExit);
2559
2560 CGF.EmitBlock(FinallyCallExit);
2561 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
2562 ->setDoesNotThrow();
2563
2564 CGF.EmitBlock(FinallyNoCallExit);
2565
2566 if (isa<ObjCAtTryStmt>(S)) {
2567 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCalld96a8e72010-08-11 00:16:14 +00002568 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
2569 // Save the current cleanup destination in case there's
2570 // control flow inside the finally statement.
2571 llvm::Value *CurCleanupDest =
2572 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
2573
John McCallcc505292010-07-21 06:59:36 +00002574 CGF.EmitStmt(FinallyStmt->getFinallyBody());
2575
John McCalld96a8e72010-08-11 00:16:14 +00002576 if (CGF.HaveInsertPoint()) {
2577 CGF.Builder.CreateStore(CurCleanupDest,
2578 CGF.getNormalCleanupDestSlot());
2579 } else {
2580 // Currently, the end of the cleanup must always exist.
2581 CGF.EnsureInsertPoint();
2582 }
2583 }
John McCallcc505292010-07-21 06:59:36 +00002584 } else {
2585 // Emit objc_sync_exit(expr); as finally's sole statement for
2586 // @synchronized.
John McCall0b251722010-08-04 05:59:32 +00002587 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCallcc505292010-07-21 06:59:36 +00002588 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2589 ->setDoesNotThrow();
2590 }
2591 }
2592 };
John McCall87bb5822010-07-31 23:20:56 +00002593
2594 class FragileHazards {
2595 CodeGenFunction &CGF;
2596 llvm::SmallVector<llvm::Value*, 20> Locals;
2597 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
2598
2599 llvm::InlineAsm *ReadHazard;
2600 llvm::InlineAsm *WriteHazard;
2601
2602 llvm::FunctionType *GetAsmFnType();
2603
2604 void collectLocals();
2605 void emitReadHazard(CGBuilderTy &Builder);
2606
2607 public:
2608 FragileHazards(CodeGenFunction &CGF);
John McCall0b251722010-08-04 05:59:32 +00002609
John McCall87bb5822010-07-31 23:20:56 +00002610 void emitWriteHazard();
John McCall0b251722010-08-04 05:59:32 +00002611 void emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00002612 };
2613}
2614
2615/// Create the fragile-ABI read and write hazards based on the current
2616/// state of the function, which is presumed to be immediately prior
2617/// to a @try block. These hazards are used to maintain correct
2618/// semantics in the face of optimization and the fragile ABI's
2619/// cavalier use of setjmp/longjmp.
2620FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
2621 collectLocals();
2622
2623 if (Locals.empty()) return;
2624
2625 // Collect all the blocks in the function.
2626 for (llvm::Function::iterator
2627 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
2628 BlocksBeforeTry.insert(&*I);
2629
2630 llvm::FunctionType *AsmFnTy = GetAsmFnType();
2631
2632 // Create a read hazard for the allocas. This inhibits dead-store
2633 // optimizations and forces the values to memory. This hazard is
2634 // inserted before any 'throwing' calls in the protected scope to
2635 // reflect the possibility that the variables might be read from the
2636 // catch block if the call throws.
2637 {
2638 std::string Constraint;
2639 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2640 if (I) Constraint += ',';
2641 Constraint += "*m";
2642 }
2643
2644 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2645 }
2646
2647 // Create a write hazard for the allocas. This inhibits folding
2648 // loads across the hazard. This hazard is inserted at the
2649 // beginning of the catch path to reflect the possibility that the
2650 // variables might have been written within the protected scope.
2651 {
2652 std::string Constraint;
2653 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2654 if (I) Constraint += ',';
2655 Constraint += "=*m";
2656 }
2657
2658 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2659 }
2660}
2661
2662/// Emit a write hazard at the current location.
2663void FragileHazards::emitWriteHazard() {
2664 if (Locals.empty()) return;
2665
2666 CGF.Builder.CreateCall(WriteHazard, Locals.begin(), Locals.end())
2667 ->setDoesNotThrow();
2668}
2669
John McCall87bb5822010-07-31 23:20:56 +00002670void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
2671 assert(!Locals.empty());
2672 Builder.CreateCall(ReadHazard, Locals.begin(), Locals.end())
2673 ->setDoesNotThrow();
2674}
2675
2676/// Emit read hazards in all the protected blocks, i.e. all the blocks
2677/// which have been inserted since the beginning of the try.
John McCall0b251722010-08-04 05:59:32 +00002678void FragileHazards::emitHazardsInNewBlocks() {
John McCall87bb5822010-07-31 23:20:56 +00002679 if (Locals.empty()) return;
2680
2681 CGBuilderTy Builder(CGF.getLLVMContext());
2682
2683 // Iterate through all blocks, skipping those prior to the try.
2684 for (llvm::Function::iterator
2685 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
2686 llvm::BasicBlock &BB = *FI;
2687 if (BlocksBeforeTry.count(&BB)) continue;
2688
2689 // Walk through all the calls in the block.
2690 for (llvm::BasicBlock::iterator
2691 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
2692 llvm::Instruction &I = *BI;
2693
2694 // Ignore instructions that aren't non-intrinsic calls.
2695 // These are the only calls that can possibly call longjmp.
2696 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
2697 if (isa<llvm::IntrinsicInst>(I))
2698 continue;
2699
2700 // Ignore call sites marked nounwind. This may be questionable,
2701 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
2702 llvm::CallSite CS(&I);
2703 if (CS.doesNotThrow()) continue;
2704
John McCall0b251722010-08-04 05:59:32 +00002705 // Insert a read hazard before the call. This will ensure that
2706 // any writes to the locals are performed before making the
2707 // call. If the call throws, then this is sufficient to
2708 // guarantee correctness as long as it doesn't also write to any
2709 // locals.
John McCall87bb5822010-07-31 23:20:56 +00002710 Builder.SetInsertPoint(&BB, BI);
2711 emitReadHazard(Builder);
2712 }
2713 }
2714}
2715
2716static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
2717 if (V) S.insert(V);
2718}
2719
2720void FragileHazards::collectLocals() {
2721 // Compute a set of allocas to ignore.
2722 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
2723 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
2724 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
2725 addIfPresent(AllocasToIgnore, CGF.EHCleanupDest);
2726
2727 // Collect all the allocas currently in the function. This is
2728 // probably way too aggressive.
2729 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
2730 for (llvm::BasicBlock::iterator
2731 I = Entry.begin(), E = Entry.end(); I != E; ++I)
2732 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
2733 Locals.push_back(&*I);
2734}
2735
2736llvm::FunctionType *FragileHazards::GetAsmFnType() {
2737 std::vector<const llvm::Type *> Tys(Locals.size());
2738 for (unsigned I = 0, E = Locals.size(); I != E; ++I)
2739 Tys[I] = Locals[I]->getType();
2740 return llvm::FunctionType::get(CGF.Builder.getVoidTy(), Tys, false);
John McCallcc505292010-07-21 06:59:36 +00002741}
2742
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002743/*
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002744
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002745 Objective-C setjmp-longjmp (sjlj) Exception Handling
2746 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002747
John McCallf1549f62010-07-06 01:34:17 +00002748 A catch buffer is a setjmp buffer plus:
2749 - a pointer to the exception that was caught
2750 - a pointer to the previous exception data buffer
2751 - two pointers of reserved storage
2752 Therefore catch buffers form a stack, with a pointer to the top
2753 of the stack kept in thread-local storage.
2754
2755 objc_exception_try_enter pushes a catch buffer onto the EH stack.
2756 objc_exception_try_exit pops the given catch buffer, which is
2757 required to be the top of the EH stack.
2758 objc_exception_throw pops the top of the EH stack, writes the
2759 thrown exception into the appropriate field, and longjmps
2760 to the setjmp buffer. It crashes the process (with a printf
2761 and an abort()) if there are no catch buffers on the stack.
2762 objc_exception_extract just reads the exception pointer out of the
2763 catch buffer.
2764
2765 There's no reason an implementation couldn't use a light-weight
2766 setjmp here --- something like __builtin_setjmp, but API-compatible
2767 with the heavyweight setjmp. This will be more important if we ever
2768 want to implement correct ObjC/C++ exception interactions for the
2769 fragile ABI.
2770
2771 Note that for this use of setjmp/longjmp to be correct, we may need
2772 to mark some local variables volatile: if a non-volatile local
2773 variable is modified between the setjmp and the longjmp, it has
2774 indeterminate value. For the purposes of LLVM IR, it may be
2775 sufficient to make loads and stores within the @try (to variables
2776 declared outside the @try) volatile. This is necessary for
2777 optimized correctness, but is not currently being done; this is
2778 being tracked as rdar://problem/8160285
2779
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002780 The basic framework for a @try-catch-finally is as follows:
2781 {
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002782 objc_exception_data d;
2783 id _rethrow = null;
Anders Carlsson190d00e2009-02-07 21:26:04 +00002784 bool _call_try_exit = true;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002785
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002786 objc_exception_try_enter(&d);
2787 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002788 ... try body ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002789 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002790 // exception path
2791 id _caught = objc_exception_extract(&d);
2792
2793 // enter new try scope for handlers
2794 if (!setjmp(d.jmp_buf)) {
2795 ... match exception and execute catch blocks ...
2796
2797 // fell off end, rethrow.
2798 _rethrow = _caught;
2799 ... jump-through-finally to finally_rethrow ...
2800 } else {
2801 // exception in catch block
2802 _rethrow = objc_exception_extract(&d);
2803 _call_try_exit = false;
2804 ... jump-through-finally to finally_rethrow ...
2805 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002806 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00002807 ... jump-through-finally to finally_end ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002808
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002809 finally:
Anders Carlsson190d00e2009-02-07 21:26:04 +00002810 if (_call_try_exit)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002811 objc_exception_try_exit(&d);
Anders Carlsson190d00e2009-02-07 21:26:04 +00002812
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002813 ... finally block ....
Daniel Dunbar898d5082008-09-30 01:06:03 +00002814 ... dispatch to finally destination ...
2815
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002816 finally_rethrow:
Daniel Dunbar898d5082008-09-30 01:06:03 +00002817 objc_exception_throw(_rethrow);
2818
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002819 finally_end:
2820 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002821
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002822 This framework differs slightly from the one gcc uses, in that gcc
2823 uses _rethrow to determine if objc_exception_try_exit should be called
2824 and if the object should be rethrown. This breaks in the face of
2825 throwing nil and introduces unnecessary branches.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002826
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002827 We specialize this framework for a few particular circumstances:
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002828
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002829 - If there are no catch blocks, then we avoid emitting the second
2830 exception handling context.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002831
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002832 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2833 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002834
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002835 - FIXME: If there is no @finally block we can do a few more
2836 simplifications.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002837
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002838 Rethrows and Jumps-Through-Finally
2839 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002840
John McCallf1549f62010-07-06 01:34:17 +00002841 '@throw;' is supported by pushing the currently-caught exception
2842 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002843
John McCallf1549f62010-07-06 01:34:17 +00002844 Branches through the @finally block are handled with an ordinary
2845 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
2846 exceptions are not compatible with C++ exceptions, and this is
2847 hardly the only place where this will go wrong.
Daniel Dunbar898d5082008-09-30 01:06:03 +00002848
John McCallf1549f62010-07-06 01:34:17 +00002849 @synchronized(expr) { stmt; } is emitted as if it were:
2850 id synch_value = expr;
2851 objc_sync_enter(synch_value);
2852 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002853*/
2854
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00002855void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2856 const Stmt &S) {
2857 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallf1549f62010-07-06 01:34:17 +00002858
2859 // A destination for the fall-through edges of the catch handlers to
2860 // jump to.
2861 CodeGenFunction::JumpDest FinallyEnd =
2862 CGF.getJumpDestInCurrentScope("finally.end");
2863
2864 // A destination for the rethrow edge of the catch handlers to jump
2865 // to.
2866 CodeGenFunction::JumpDest FinallyRethrow =
2867 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002868
Daniel Dunbar1c566672009-02-24 01:43:46 +00002869 // For @synchronized, call objc_sync_enter(sync.expr). The
2870 // evaluation of the expression must occur before we enter the
John McCall0b251722010-08-04 05:59:32 +00002871 // @synchronized. We can't avoid a temp here because we need the
2872 // value to be preserved. If the backend ever does liveness
2873 // correctly after setjmp, this will be unnecessary.
2874 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar1c566672009-02-24 01:43:46 +00002875 if (!isTry) {
John McCall0b251722010-08-04 05:59:32 +00002876 llvm::Value *SyncArg =
Daniel Dunbar1c566672009-02-24 01:43:46 +00002877 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2878 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallf1549f62010-07-06 01:34:17 +00002879 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
2880 ->setDoesNotThrow();
John McCall0b251722010-08-04 05:59:32 +00002881
2882 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
2883 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar1c566672009-02-24 01:43:46 +00002884 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00002885
John McCall0b251722010-08-04 05:59:32 +00002886 // Allocate memory for the setjmp buffer. This needs to be kept
2887 // live throughout the try and catch blocks.
2888 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2889 "exceptiondata.ptr");
2890
John McCall87bb5822010-07-31 23:20:56 +00002891 // Create the fragile hazards. Note that this will not capture any
2892 // of the allocas required for exception processing, but will
2893 // capture the current basic block (which extends all the way to the
2894 // setjmp call) as "before the @try".
2895 FragileHazards Hazards(CGF);
2896
John McCallf1549f62010-07-06 01:34:17 +00002897 // Create a flag indicating whether the cleanup needs to call
2898 // objc_exception_try_exit. This is true except when
2899 // - no catches match and we're branching through the cleanup
2900 // just to rethrow the exception, or
2901 // - a catch matched and we're falling out of the catch handler.
John McCall0b251722010-08-04 05:59:32 +00002902 // The setjmp-safety rule here is that we should always store to this
2903 // variable in a place that dominates the branch through the cleanup
2904 // without passing through any setjmps.
John McCallf1549f62010-07-06 01:34:17 +00002905 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlsson190d00e2009-02-07 21:26:04 +00002906 "_call_try_exit");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002907
John McCall9e2213d2010-10-04 23:42:51 +00002908 // A slot containing the exception to rethrow. Only needed when we
2909 // have both a @catch and a @finally.
2910 llvm::Value *PropagatingExnVar = 0;
2911
John McCallf1549f62010-07-06 01:34:17 +00002912 // Push a normal cleanup to leave the try scope.
John McCall1f0fca52010-07-21 07:22:38 +00002913 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall0b251722010-08-04 05:59:32 +00002914 SyncArgSlot,
John McCall1f0fca52010-07-21 07:22:38 +00002915 CallTryExitVar,
2916 ExceptionData,
2917 &ObjCTypes);
John McCallf1549f62010-07-06 01:34:17 +00002918
2919 // Enter a try block:
2920 // - Call objc_exception_try_enter to push ExceptionData on top of
2921 // the EH stack.
2922 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
2923 ->setDoesNotThrow();
2924
2925 // - Call setjmp on the exception data buffer.
2926 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
2927 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
2928 llvm::Value *SetJmpBuffer =
2929 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, GEPIndexes+3, "setjmp_buffer");
2930 llvm::CallInst *SetJmpResult =
2931 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
2932 SetJmpResult->setDoesNotThrow();
2933
2934 // If setjmp returned 0, enter the protected block; otherwise,
2935 // branch to the handler.
Daniel Dunbar55e87422008-11-11 02:29:29 +00002936 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2937 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallf1549f62010-07-06 01:34:17 +00002938 llvm::Value *DidCatch =
John McCalld96a8e72010-08-11 00:16:14 +00002939 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
2940 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson80f25672008-09-09 17:59:25 +00002941
John McCallf1549f62010-07-06 01:34:17 +00002942 // Emit the protected block.
Anders Carlsson80f25672008-09-09 17:59:25 +00002943 CGF.EmitBlock(TryBlock);
John McCall0b251722010-08-04 05:59:32 +00002944 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002945 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallf1549f62010-07-06 01:34:17 +00002946 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall0b251722010-08-04 05:59:32 +00002947
2948 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002949
John McCallf1549f62010-07-06 01:34:17 +00002950 // Emit the exception handler block.
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00002951 CGF.EmitBlock(TryHandler);
Daniel Dunbar55e40722008-09-27 07:03:52 +00002952
John McCall87bb5822010-07-31 23:20:56 +00002953 // Don't optimize loads of the in-scope locals across this point.
2954 Hazards.emitWriteHazard();
2955
John McCallf1549f62010-07-06 01:34:17 +00002956 // For a @synchronized (or a @try with no catches), just branch
2957 // through the cleanup to the rethrow block.
2958 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
2959 // Tell the cleanup not to re-pop the exit.
John McCall0b251722010-08-04 05:59:32 +00002960 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00002961 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallf1549f62010-07-06 01:34:17 +00002962
2963 // Otherwise, we have to match against the caught exceptions.
2964 } else {
John McCall0b251722010-08-04 05:59:32 +00002965 // Retrieve the exception object. We may emit multiple blocks but
2966 // nothing can cross this so the value is already in SSA form.
2967 llvm::CallInst *Caught =
2968 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2969 ExceptionData, "caught");
2970 Caught->setDoesNotThrow();
2971
John McCallf1549f62010-07-06 01:34:17 +00002972 // Push the exception to rethrow onto the EH value stack for the
2973 // benefit of any @throws in the handlers.
2974 CGF.ObjCEHValueStack.push_back(Caught);
2975
Douglas Gregor8f5e3dd2010-04-23 22:50:49 +00002976 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002977
John McCall0b251722010-08-04 05:59:32 +00002978 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallf1549f62010-07-06 01:34:17 +00002979
John McCall0b251722010-08-04 05:59:32 +00002980 llvm::BasicBlock *CatchBlock = 0;
2981 llvm::BasicBlock *CatchHandler = 0;
2982 if (HasFinally) {
John McCall9e2213d2010-10-04 23:42:51 +00002983 // Save the currently-propagating exception before
2984 // objc_exception_try_enter clears the exception slot.
2985 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
2986 "propagating_exception");
2987 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
2988
John McCall0b251722010-08-04 05:59:32 +00002989 // Enter a new exception try block (in case a @catch block
2990 // throws an exception).
2991 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
2992 ->setDoesNotThrow();
Anders Carlsson80f25672008-09-09 17:59:25 +00002993
John McCall0b251722010-08-04 05:59:32 +00002994 llvm::CallInst *SetJmpResult =
2995 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
2996 "setjmp.result");
2997 SetJmpResult->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002998
John McCall0b251722010-08-04 05:59:32 +00002999 llvm::Value *Threw =
3000 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3001
3002 CatchBlock = CGF.createBasicBlock("catch");
3003 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3004 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3005
3006 CGF.EmitBlock(CatchBlock);
3007 }
3008
3009 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003010
Daniel Dunbar55e40722008-09-27 07:03:52 +00003011 // Handle catch list. As a special case we check if everything is
3012 // matched and avoid generating code for falling off the end if
3013 // so.
3014 bool AllMatched = false;
Douglas Gregor8f5e3dd2010-04-23 22:50:49 +00003015 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3016 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson80f25672008-09-09 17:59:25 +00003017
Douglas Gregorc00d8e12010-04-26 16:46:50 +00003018 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff14108da2009-07-10 23:34:53 +00003019 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar129271a2008-09-27 07:36:24 +00003020
Anders Carlsson80f25672008-09-09 17:59:25 +00003021 // catch(...) always matches.
Daniel Dunbar55e40722008-09-27 07:03:52 +00003022 if (!CatchParam) {
3023 AllMatched = true;
3024 } else {
John McCall183700f2009-09-21 23:43:11 +00003025 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003026
John McCallf1549f62010-07-06 01:34:17 +00003027 // catch(id e) always matches under this ABI, since only
3028 // ObjC exceptions end up here in the first place.
Daniel Dunbar97f61d12008-09-27 22:21:14 +00003029 // FIXME: For the time being we also match id<X>; this should
3030 // be rejected by Sema instead.
Eli Friedman818e96f2009-07-11 00:57:02 +00003031 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbar55e40722008-09-27 07:03:52 +00003032 AllMatched = true;
Anders Carlsson80f25672008-09-09 17:59:25 +00003033 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003034
John McCallf1549f62010-07-06 01:34:17 +00003035 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003036 if (AllMatched) {
John McCallf1549f62010-07-06 01:34:17 +00003037 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3038
Anders Carlssondde0a942008-09-11 09:15:33 +00003039 if (CatchParam) {
John McCallb6bbcc92010-10-15 04:57:14 +00003040 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003041 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallf1549f62010-07-06 01:34:17 +00003042
3043 // These types work out because ConvertType(id) == i8*.
Steve Naroff7ba138a2009-03-03 19:52:17 +00003044 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlssondde0a942008-09-11 09:15:33 +00003045 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003046
Anders Carlssondde0a942008-09-11 09:15:33 +00003047 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003048
3049 // The scope of the catch variable ends right here.
3050 CatchVarCleanups.ForceCleanup();
3051
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003052 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson80f25672008-09-09 17:59:25 +00003053 break;
3054 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003055
Steve Naroff14108da2009-07-10 23:34:53 +00003056 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall506b57e2010-05-17 21:00:27 +00003057 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallf1549f62010-07-06 01:34:17 +00003058
3059 // FIXME: @catch (Class c) ?
John McCall506b57e2010-05-17 21:00:27 +00003060 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3061 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson80f25672008-09-09 17:59:25 +00003062
3063 // Check if the @catch block matches the exception object.
John McCall506b57e2010-05-17 21:00:27 +00003064 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003065
John McCallf1549f62010-07-06 01:34:17 +00003066 llvm::CallInst *Match =
Chris Lattner34b02a12009-04-22 02:26:14 +00003067 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3068 Class, Caught, "match");
John McCallf1549f62010-07-06 01:34:17 +00003069 Match->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003070
John McCallf1549f62010-07-06 01:34:17 +00003071 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3072 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003073
3074 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003075 MatchedBlock, NextCatchBlock);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003076
Anders Carlsson80f25672008-09-09 17:59:25 +00003077 // Emit the @catch block.
3078 CGF.EmitBlock(MatchedBlock);
John McCallf1549f62010-07-06 01:34:17 +00003079
3080 // Collect any cleanups for the catch variable. The scope lasts until
3081 // the end of the catch body.
John McCall0b251722010-08-04 05:59:32 +00003082 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallf1549f62010-07-06 01:34:17 +00003083
John McCallb6bbcc92010-10-15 04:57:14 +00003084 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003085 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003086
John McCallf1549f62010-07-06 01:34:17 +00003087 // Initialize the catch variable.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003088 llvm::Value *Tmp =
3089 CGF.Builder.CreateBitCast(Caught,
3090 CGF.ConvertType(CatchParam->getType()),
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003091 "tmp");
Steve Naroff7ba138a2009-03-03 19:52:17 +00003092 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003093
Anders Carlssondde0a942008-09-11 09:15:33 +00003094 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003095
3096 // We're done with the catch variable.
3097 CatchVarCleanups.ForceCleanup();
3098
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003099 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003100
Anders Carlsson80f25672008-09-09 17:59:25 +00003101 CGF.EmitBlock(NextCatchBlock);
3102 }
3103
John McCallf1549f62010-07-06 01:34:17 +00003104 CGF.ObjCEHValueStack.pop_back();
3105
John McCall0b251722010-08-04 05:59:32 +00003106 // If nothing wanted anything to do with the caught exception,
3107 // kill the extract call.
3108 if (Caught->use_empty())
3109 Caught->eraseFromParent();
3110
3111 if (!AllMatched)
3112 CGF.EmitBranchThroughCleanup(FinallyRethrow);
3113
3114 if (HasFinally) {
3115 // Emit the exception handler for the @catch blocks.
3116 CGF.EmitBlock(CatchHandler);
3117
3118 // In theory we might now need a write hazard, but actually it's
3119 // unnecessary because there's no local-accessing code between
3120 // the try's write hazard and here.
3121 //Hazards.emitWriteHazard();
3122
John McCall9e2213d2010-10-04 23:42:51 +00003123 // Extract the new exception and save it to the
3124 // propagating-exception slot.
3125 assert(PropagatingExnVar);
3126 llvm::CallInst *NewCaught =
3127 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3128 ExceptionData, "caught");
3129 NewCaught->setDoesNotThrow();
3130 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
3131
John McCall0b251722010-08-04 05:59:32 +00003132 // Don't pop the catch handler; the throw already did.
3133 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003134 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar55e40722008-09-27 07:03:52 +00003135 }
Anders Carlsson80f25672008-09-09 17:59:25 +00003136 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003137
John McCall87bb5822010-07-31 23:20:56 +00003138 // Insert read hazards as required in the new blocks.
John McCall0b251722010-08-04 05:59:32 +00003139 Hazards.emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00003140
John McCallf1549f62010-07-06 01:34:17 +00003141 // Pop the cleanup.
John McCall0b251722010-08-04 05:59:32 +00003142 CGF.Builder.restoreIP(TryFallthroughIP);
3143 if (CGF.HaveInsertPoint())
3144 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallf1549f62010-07-06 01:34:17 +00003145 CGF.PopCleanupBlock();
John McCall0b251722010-08-04 05:59:32 +00003146 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003147
John McCallf1549f62010-07-06 01:34:17 +00003148 // Emit the rethrow block.
John McCall87bb5822010-07-31 23:20:56 +00003149 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallff8e1152010-07-23 21:56:41 +00003150 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallf1549f62010-07-06 01:34:17 +00003151 if (CGF.HaveInsertPoint()) {
John McCall9e2213d2010-10-04 23:42:51 +00003152 // If we have a propagating-exception variable, check it.
3153 llvm::Value *PropagatingExn;
3154 if (PropagatingExnVar) {
3155 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall0b251722010-08-04 05:59:32 +00003156
John McCall9e2213d2010-10-04 23:42:51 +00003157 // Otherwise, just look in the buffer for the exception to throw.
3158 } else {
3159 llvm::CallInst *Caught =
3160 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3161 ExceptionData);
3162 Caught->setDoesNotThrow();
3163 PropagatingExn = Caught;
3164 }
3165
3166 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallf1549f62010-07-06 01:34:17 +00003167 ->setDoesNotThrow();
3168 CGF.Builder.CreateUnreachable();
Fariborz Jahanianf2878e52008-11-21 19:21:53 +00003169 }
Anders Carlsson80f25672008-09-09 17:59:25 +00003170
John McCall87bb5822010-07-31 23:20:56 +00003171 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00003172}
3173
3174void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar898d5082008-09-30 01:06:03 +00003175 const ObjCAtThrowStmt &S) {
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003176 llvm::Value *ExceptionAsObject;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003177
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003178 if (const Expr *ThrowExpr = S.getThrowExpr()) {
3179 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003180 ExceptionAsObject =
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003181 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
3182 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003183 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003184 "Unexpected rethrow outside @catch block.");
Anders Carlsson273558f2009-02-07 21:37:21 +00003185 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003186 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003187
John McCallf1549f62010-07-06 01:34:17 +00003188 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3189 ->setDoesNotReturn();
Anders Carlsson80f25672008-09-09 17:59:25 +00003190 CGF.Builder.CreateUnreachable();
Daniel Dunbara448fb22008-11-11 23:11:34 +00003191
3192 // Clear the insertion point to indicate we are in unreachable code.
3193 CGF.Builder.ClearInsertionPoint();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00003194}
3195
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003196/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00003197/// object: objc_read_weak (id *src)
3198///
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003199llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003200 llvm::Value *AddrWeakObj) {
Eli Friedman8339b352009-03-07 03:57:15 +00003201 const llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003202 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3203 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3204 ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00003205 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003206 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00003207 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00003208 return read_weak;
3209}
3210
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003211/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
3212/// objc_assign_weak (id src, id *dst)
3213///
3214void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003215 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003216 const llvm::Type * SrcTy = src->getType();
3217 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003218 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003219 assert(Size <= 8 && "does not support size > 8");
3220 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003221 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003222 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3223 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003224 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3225 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00003226 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003227 src, dst, "weakassign");
3228 return;
3229}
3230
Fariborz Jahanian58626502008-11-19 00:59:10 +00003231/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
3232/// objc_assign_global (id src, id *dst)
3233///
3234void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00003235 llvm::Value *src, llvm::Value *dst,
3236 bool threadlocal) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003237 const llvm::Type * SrcTy = src->getType();
3238 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003239 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003240 assert(Size <= 8 && "does not support size > 8");
3241 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003242 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003243 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3244 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003245 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3246 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00003247 if (!threadlocal)
3248 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
3249 src, dst, "globalassign");
3250 else
3251 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
3252 src, dst, "threadlocalassign");
Fariborz Jahanian58626502008-11-19 00:59:10 +00003253 return;
3254}
3255
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003256/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003257/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003258///
3259void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003260 llvm::Value *src, llvm::Value *dst,
3261 llvm::Value *ivarOffset) {
3262 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003263 const llvm::Type * SrcTy = src->getType();
3264 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003265 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003266 assert(Size <= 8 && "does not support size > 8");
3267 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003268 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003269 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3270 }
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003271 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3272 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003273 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3274 src, dst, ivarOffset);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003275 return;
3276}
3277
Fariborz Jahanian58626502008-11-19 00:59:10 +00003278/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
3279/// objc_assign_strongCast (id src, id *dst)
3280///
3281void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003282 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003283 const llvm::Type * SrcTy = src->getType();
3284 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003285 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003286 assert(Size <= 8 && "does not support size > 8");
3287 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003288 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003289 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3290 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003291 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3292 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00003293 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian58626502008-11-19 00:59:10 +00003294 src, dst, "weakassign");
3295 return;
3296}
3297
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003298void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003299 llvm::Value *DestPtr,
3300 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00003301 llvm::Value *size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003302 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3303 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003304 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00003305 DestPtr, SrcPtr, size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003306 return;
3307}
3308
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00003309/// EmitObjCValueForIvar - Code Gen for ivar reference.
3310///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00003311LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3312 QualType ObjectTy,
3313 llvm::Value *BaseValue,
3314 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00003315 unsigned CVRQualifiers) {
John McCallc12c5bb2010-05-15 11:32:37 +00003316 const ObjCInterfaceDecl *ID =
3317 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00003318 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3319 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00003320}
3321
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003322llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00003323 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003324 const ObjCIvarDecl *Ivar) {
Daniel Dunbar97776872009-04-22 07:32:20 +00003325 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003326 return llvm::ConstantInt::get(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003327 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3328 Offset);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003329}
3330
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003331/* *** Private Interface *** */
3332
3333/// EmitImageInfo - Emit the image info marker used to encode some module
3334/// level information.
3335///
3336/// See: <rdr://4810609&4810587&4810587>
3337/// struct IMAGE_INFO {
3338/// unsigned version;
3339/// unsigned flags;
3340/// };
3341enum ImageInfoFlags {
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003342 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003343 eImageInfo_GarbageCollected = (1 << 1),
3344 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003345 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3346
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003347 // A flag indicating that the module has no instances of a @synthesize of a
3348 // superclass variable. <rdar://problem/6803242>
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003349 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003350};
3351
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003352void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003353 unsigned version = 0; // Version is unused?
3354 unsigned flags = 0;
3355
3356 // FIXME: Fix and continue?
3357 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
3358 flags |= eImageInfo_GarbageCollected;
3359 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
3360 flags |= eImageInfo_GCOnly;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003361
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003362 // We never allow @synthesize of a superclass property.
3363 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003364
Chris Lattner77b89b82010-06-27 07:15:29 +00003365 const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
3366
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003367 // Emitted as int[2];
3368 llvm::Constant *values[2] = {
Chris Lattner77b89b82010-06-27 07:15:29 +00003369 llvm::ConstantInt::get(Int32Ty, version),
3370 llvm::ConstantInt::get(Int32Ty, flags)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003371 };
Chris Lattner77b89b82010-06-27 07:15:29 +00003372 llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003373
3374 const char *Section;
3375 if (ObjCABI == 1)
3376 Section = "__OBJC, __image_info,regular";
3377 else
3378 Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003379 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003380 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
Owen Anderson7db6d832009-07-28 18:33:04 +00003381 llvm::ConstantArray::get(AT, values, 2),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003382 Section,
3383 0,
3384 true);
3385 GV->setConstant(true);
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003386}
3387
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003388
3389// struct objc_module {
3390// unsigned long version;
3391// unsigned long size;
3392// const char *name;
3393// Symtab symtab;
3394// };
3395
3396// FIXME: Get from somewhere
3397static const int ModuleVersion = 7;
3398
3399void CGObjCMac::EmitModuleInfo() {
Duncan Sands9408c452009-05-09 07:08:47 +00003400 uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003401
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003402 std::vector<llvm::Constant*> Values(4);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003403 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
3404 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00003405 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003406 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003407 Values[3] = EmitModuleSymbols();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003408 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson08e25242009-07-27 22:29:56 +00003409 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003410 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00003411 4, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003412}
3413
3414llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003415 unsigned NumClasses = DefinedClasses.size();
3416 unsigned NumCategories = DefinedCategories.size();
3417
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003418 // Return null if no symbols were defined.
3419 if (!NumClasses && !NumCategories)
Owen Andersonc9c88b42009-07-31 20:28:54 +00003420 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003421
3422 std::vector<llvm::Constant*> Values(5);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003423 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Andersonc9c88b42009-07-31 20:28:54 +00003424 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003425 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3426 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003427
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003428 // The runtime expects exactly the list of defined classes followed
3429 // by the list of defined categories, in a single array.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003430 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003431 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00003432 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003433 ObjCTypes.Int8PtrTy);
3434 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003435 Symbols[NumClasses + i] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003436 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003437 ObjCTypes.Int8PtrTy);
3438
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003439 Values[4] =
Owen Anderson96e0fc72009-07-29 22:16:19 +00003440 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003441 NumClasses + NumCategories),
3442 Symbols);
3443
Nick Lewycky0d36dd22009-09-19 20:00:52 +00003444 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003445
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003446 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003447 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3448 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003449 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00003450 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003451}
3452
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003453llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003454 const ObjCInterfaceDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003455 LazySymbols.insert(ID->getIdentifier());
3456
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003457 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003458
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003459 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003460 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003461 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003462 ObjCTypes.ClassPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003463 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003464 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3465 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003466 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003467 }
3468
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00003469 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003470}
3471
Fariborz Jahanian03b29602010-06-17 19:56:20 +00003472llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3473 bool lvalue) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003474 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003475
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003476 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003477 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003478 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003479 ObjCTypes.SelectorPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003480 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003481 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3482 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003483 4, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003484 }
3485
Fariborz Jahanian03b29602010-06-17 19:56:20 +00003486 if (lvalue)
3487 return Entry;
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00003488 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003489}
3490
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00003491llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003492 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003493
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003494 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003495 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003496 llvm::ConstantArray::get(VMContext,
3497 Ident->getNameStart()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003498 ((ObjCABI == 2) ?
3499 "__TEXT,__objc_classname,cstring_literals" :
3500 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003501 1, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003502
Owen Andersona1cf15f2009-07-14 23:10:40 +00003503 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003504}
3505
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00003506llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
3507 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
3508 I = MethodDefinitions.find(MD);
3509 if (I != MethodDefinitions.end())
3510 return I->second;
3511
3512 if (MD->hasBody() && MD->getPCHLevel() > 0) {
3513 // MD isn't emitted yet because it comes from PCH.
3514 CGM.EmitTopLevelDecl(const_cast<ObjCMethodDecl*>(MD));
3515 assert(MethodDefinitions[MD] && "EmitTopLevelDecl didn't emit the method!");
3516 return MethodDefinitions[MD];
3517 }
3518
3519 return NULL;
3520}
3521
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00003522/// GetIvarLayoutName - Returns a unique constant for the given
3523/// ivar layout bitmap.
3524llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003525 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Andersonc9c88b42009-07-31 20:28:54 +00003526 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00003527}
3528
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003529void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003530 unsigned int BytePos,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003531 bool ForStrongLayout,
3532 bool &HasUnion) {
3533 const RecordDecl *RD = RT->getDecl();
3534 // FIXME - Use iterator.
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00003535 llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003536 const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003537 const llvm::StructLayout *RecLayout =
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003538 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003539
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003540 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3541 ForStrongLayout, HasUnion);
3542}
3543
Daniel Dunbar5a5a8032009-05-03 21:05:10 +00003544void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003545 const llvm::StructLayout *Layout,
3546 const RecordDecl *RD,
Chris Lattnerf1690852009-03-31 08:48:01 +00003547 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003548 unsigned int BytePos, bool ForStrongLayout,
3549 bool &HasUnion) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003550 bool IsUnion = (RD && RD->isUnion());
3551 uint64_t MaxUnionIvarSize = 0;
3552 uint64_t MaxSkippedUnionIvarSize = 0;
3553 FieldDecl *MaxField = 0;
3554 FieldDecl *MaxSkippedField = 0;
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003555 FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003556 uint64_t MaxFieldOffset = 0;
3557 uint64_t MaxSkippedFieldOffset = 0;
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003558 uint64_t LastBitfieldOrUnnamedOffset = 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003559
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003560 if (RecFields.empty())
3561 return;
Chris Lattnerf1690852009-03-31 08:48:01 +00003562 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3563 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3564
Chris Lattnerf1690852009-03-31 08:48:01 +00003565 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003566 FieldDecl *Field = RecFields[i];
Daniel Dunbare05cc982009-05-03 23:35:23 +00003567 uint64_t FieldOffset;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00003568 if (RD) {
Daniel Dunbarf8f8eba2010-04-14 17:02:21 +00003569 // Note that 'i' here is actually the field index inside RD of Field,
3570 // although this dependency is hidden.
3571 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Ken Dyckfb67ccd2011-04-14 00:43:09 +00003572 FieldOffset = RL.getFieldOffset(i) / ByteSizeInBits;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00003573 } else
Daniel Dunbare05cc982009-05-03 23:35:23 +00003574 FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003575
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003576 // Skip over unnamed or bitfields
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003577 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003578 LastFieldBitfieldOrUnnamed = Field;
3579 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003580 continue;
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003581 }
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003582
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003583 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003584 QualType FQT = Field->getType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003585 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003586 if (FQT->isUnionType())
3587 HasUnion = true;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003588
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003589 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003590 BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003591 ForStrongLayout, HasUnion);
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003592 continue;
3593 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003594
Chris Lattnerf1690852009-03-31 08:48:01 +00003595 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003596 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003597 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003598 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003599 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003600 FQT = CArray->getElementType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003601 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3602 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003603 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003604 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003605 FQT = CArray->getElementType();
3606 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003607
3608 assert(!FQT->isUnionType() &&
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003609 "layout for array of unions not supported");
Fariborz Jahanianf96bdf42011-01-03 19:23:18 +00003610 if (FQT->isRecordType() && ElCount) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003611 int OldIndex = IvarsInfo.size() - 1;
3612 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003613
Ted Kremenek6217b802009-07-29 21:53:49 +00003614 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003615 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003616 ForStrongLayout, HasUnion);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003617
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003618 // Replicate layout information for each array element. Note that
3619 // one element is already done.
3620 uint64_t ElIx = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003621 for (int FirstIndex = IvarsInfo.size() - 1,
3622 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003623 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003624 for (int i = OldIndex+1; i <= FirstIndex; ++i)
3625 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3626 IvarsInfo[i].ivar_size));
3627 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3628 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3629 SkipIvars[i].ivar_size));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003630 }
3631 continue;
3632 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003633 }
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003634 // At this point, we are done with Record/Union and array there of.
3635 // For other arrays we are down to its element type.
John McCall0953e762009-09-24 19:53:00 +00003636 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003637
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003638 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall0953e762009-09-24 19:53:00 +00003639 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3640 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00003641 if (IsUnion) {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003642 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar487993b2009-05-03 13:32:01 +00003643 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003644 MaxUnionIvarSize = UnionIvarSize;
3645 MaxField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003646 MaxFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003647 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00003648 } else {
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003649 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003650 FieldSize / WordSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003651 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003652 } else if ((ForStrongLayout &&
John McCall0953e762009-09-24 19:53:00 +00003653 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3654 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00003655 if (IsUnion) {
Mike Stumpf5408fe2009-05-16 07:57:57 +00003656 // FIXME: Why the asymmetry? We divide by word size in bits on other
3657 // side.
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003658 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar487993b2009-05-03 13:32:01 +00003659 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003660 MaxSkippedUnionIvarSize = UnionIvarSize;
3661 MaxSkippedField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003662 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003663 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00003664 } else {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003665 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003666 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003667 FieldSize / ByteSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003668 }
3669 }
3670 }
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003671
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003672 if (LastFieldBitfieldOrUnnamed) {
3673 if (LastFieldBitfieldOrUnnamed->isBitField()) {
3674 // Last field was a bitfield. Must update skip info.
3675 Expr *BitWidth = LastFieldBitfieldOrUnnamed->getBitWidth();
3676 uint64_t BitFieldSize =
3677 BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
3678 GC_IVAR skivar;
3679 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
3680 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3681 + ((BitFieldSize % ByteSizeInBits) != 0);
3682 SkipIvars.push_back(skivar);
3683 } else {
3684 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
3685 // Last field was unnamed. Must update skip info.
3686 unsigned FieldSize
3687 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
3688 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
3689 FieldSize / ByteSizeInBits));
3690 }
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003691 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003692
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003693 if (MaxField)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003694 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003695 MaxUnionIvarSize));
3696 if (MaxSkippedField)
Daniel Dunbar900c1982009-05-03 23:31:46 +00003697 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003698 MaxSkippedUnionIvarSize));
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00003699}
3700
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003701/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
3702/// the computations and returning the layout bitmap (for ivar or blocks) in
3703/// the given argument BitMap string container. Routine reads
3704/// two containers, IvarsInfo and SkipIvars which are assumed to be
3705/// filled already by the caller.
3706llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003707 unsigned int WordsToScan, WordsToSkip;
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00003708 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003709
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003710 // Build the string of skip/scan nibbles
Fariborz Jahanian8c2f2d12009-04-24 17:15:27 +00003711 llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003712 unsigned int WordSize =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003713 CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003714 if (IvarsInfo[0].ivar_bytepos == 0) {
3715 WordsToSkip = 0;
3716 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003717 } else {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003718 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3719 WordsToScan = IvarsInfo[0].ivar_size;
3720 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003721 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003722 unsigned int TailPrevGCObjC =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003723 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003724 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003725 // consecutive 'scanned' object pointers.
3726 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003727 } else {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003728 // Skip over 'gc'able object pointer which lay over each other.
3729 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3730 continue;
3731 // Must skip over 1 or more words. We save current skip/scan values
3732 // and start a new pair.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003733 SKIP_SCAN SkScan;
3734 SkScan.skip = WordsToSkip;
3735 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003736 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003737
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003738 // Skip the hole.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003739 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3740 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003741 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003742 WordsToSkip = 0;
3743 WordsToScan = IvarsInfo[i].ivar_size;
3744 }
3745 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003746 if (WordsToScan > 0) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003747 SKIP_SCAN SkScan;
3748 SkScan.skip = WordsToSkip;
3749 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003750 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003751 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003752
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003753 if (!SkipIvars.empty()) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003754 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003755 int LastByteSkipped =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003756 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003757 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003758 int LastByteScanned =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003759 IvarsInfo[LastIndex].ivar_bytepos +
3760 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003761 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramer54d76db2009-12-25 15:43:36 +00003762 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003763 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003764 SKIP_SCAN SkScan;
3765 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3766 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003767 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003768 }
3769 }
3770 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3771 // as 0xMN.
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003772 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003773 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003774 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3775 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3776 // 0xM0 followed by 0x0N detected.
3777 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3778 for (int j = i+1; j < SkipScan; j++)
3779 SkipScanIvars[j] = SkipScanIvars[j+1];
3780 --SkipScan;
3781 }
3782 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003783
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003784 // Generate the string.
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003785 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003786 unsigned char byte;
3787 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3788 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3789 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
3790 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003791
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003792 // first skip big.
3793 for (unsigned int ix = 0; ix < skip_big; ix++)
3794 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003795
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003796 // next (skip small, scan)
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003797 if (skip_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003798 byte = skip_small << 4;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003799 if (scan_big > 0) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003800 byte |= 0xf;
3801 --scan_big;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003802 } else if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003803 byte |= scan_small;
3804 scan_small = 0;
3805 }
3806 BitMap += byte;
3807 }
3808 // next scan big
3809 for (unsigned int ix = 0; ix < scan_big; ix++)
3810 BitMap += (unsigned char)(0x0f);
3811 // last scan small
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003812 if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003813 byte = scan_small;
3814 BitMap += byte;
3815 }
3816 }
3817 // null terminate string.
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003818 unsigned char zero = 0;
3819 BitMap += zero;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003820
3821 llvm::GlobalVariable * Entry =
3822 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3823 llvm::ConstantArray::get(VMContext, BitMap.c_str()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003824 ((ObjCABI == 2) ?
3825 "__TEXT,__objc_classname,cstring_literals" :
3826 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003827 1, true);
3828 return getConstantGEP(VMContext, Entry, 0, 0);
3829}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003830
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003831/// BuildIvarLayout - Builds ivar layout bitmap for the class
3832/// implementation for the __strong or __weak case.
3833/// The layout map displays which words in ivar list must be skipped
3834/// and which must be scanned by GC (see below). String is built of bytes.
3835/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
3836/// of words to skip and right nibble is count of words to scan. So, each
3837/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
3838/// represented by a 0x00 byte which also ends the string.
3839/// 1. when ForStrongLayout is true, following ivars are scanned:
3840/// - id, Class
3841/// - object *
3842/// - __strong anything
3843///
3844/// 2. When ForStrongLayout is false, following ivars are scanned:
3845/// - __weak anything
3846///
3847llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
3848 const ObjCImplementationDecl *OMD,
3849 bool ForStrongLayout) {
3850 bool hasUnion = false;
3851
3852 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3853 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
3854 return llvm::Constant::getNullValue(PtrTy);
3855
Fariborz Jahanian2c18bb72010-08-20 21:21:08 +00003856 llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003857 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
Fariborz Jahanian2c18bb72010-08-20 21:21:08 +00003858 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003859
Fariborz Jahanian2c18bb72010-08-20 21:21:08 +00003860 llvm::SmallVector<FieldDecl*, 32> RecFields;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003861 for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
3862 RecFields.push_back(cast<FieldDecl>(Ivars[k]));
3863
3864 if (RecFields.empty())
3865 return llvm::Constant::getNullValue(PtrTy);
3866
3867 SkipIvars.clear();
3868 IvarsInfo.clear();
3869
3870 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
3871 if (IvarsInfo.empty())
3872 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003873 // Sort on byte position in case we encounterred a union nested in
3874 // the ivar list.
3875 if (hasUnion && !IvarsInfo.empty())
3876 std::sort(IvarsInfo.begin(), IvarsInfo.end());
3877 if (hasUnion && !SkipIvars.empty())
3878 std::sort(SkipIvars.begin(), SkipIvars.end());
3879
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003880 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003881 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003882
3883 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003884 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian3d2ad662009-04-20 22:03:45 +00003885 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar4087f272010-08-17 22:39:59 +00003886 OMD->getClassInterface()->getName().data());
Fariborz Jahanian3d2ad662009-04-20 22:03:45 +00003887 const unsigned char *s = (unsigned char*)BitMap.c_str();
3888 for (unsigned i = 0; i < BitMap.size(); i++)
3889 if (!(s[i] & 0xf0))
3890 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3891 else
3892 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
3893 printf("\n");
3894 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003895 return C;
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00003896}
3897
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003898llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003899 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3900
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003901 // FIXME: Avoid std::string copying.
3902 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003903 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Owen Anderson0032b272009-08-13 21:57:51 +00003904 llvm::ConstantArray::get(VMContext, Sel.getAsString()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003905 ((ObjCABI == 2) ?
3906 "__TEXT,__objc_methname,cstring_literals" :
3907 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003908 1, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003909
Owen Andersona1cf15f2009-07-14 23:10:40 +00003910 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003911}
3912
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003913// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003914llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003915 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3916}
3917
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00003918llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel7794bb82009-03-04 18:21:39 +00003919 std::string TypeStr;
3920 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
3921
3922 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003923
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003924 if (!Entry)
3925 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson0032b272009-08-13 21:57:51 +00003926 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003927 ((ObjCABI == 2) ?
3928 "__TEXT,__objc_methtype,cstring_literals" :
3929 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003930 1, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003931
Owen Andersona1cf15f2009-07-14 23:10:40 +00003932 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003933}
3934
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003935llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003936 std::string TypeStr;
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003937 CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
3938 TypeStr);
Devang Patel7794bb82009-03-04 18:21:39 +00003939
3940 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3941
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003942 if (!Entry)
3943 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson0032b272009-08-13 21:57:51 +00003944 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003945 ((ObjCABI == 2) ?
3946 "__TEXT,__objc_methtype,cstring_literals" :
3947 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003948 1, true);
Devang Patel7794bb82009-03-04 18:21:39 +00003949
Owen Andersona1cf15f2009-07-14 23:10:40 +00003950 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003951}
3952
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003953// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003954llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003955 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003956
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003957 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003958 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003959 llvm::ConstantArray::get(VMContext,
3960 Ident->getNameStart()),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003961 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003962 1, true);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003963
Owen Andersona1cf15f2009-07-14 23:10:40 +00003964 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003965}
3966
3967// FIXME: Merge into a single cstring creation function.
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00003968// FIXME: This Decl should be more precise.
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003969llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003970CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
3971 const Decl *Container) {
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00003972 std::string TypeStr;
3973 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003974 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
3975}
3976
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003977void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003978 const ObjCContainerDecl *CD,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00003979 llvm::SmallVectorImpl<char> &Name) {
3980 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian679a5022009-01-10 21:06:09 +00003981 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbarc575ce72009-10-19 01:21:19 +00003982 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
3983 << '[' << CD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003984 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbarc575ce72009-10-19 01:21:19 +00003985 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer900fc632010-04-17 09:33:03 +00003986 OS << '(' << CID << ')';
Daniel Dunbarc575ce72009-10-19 01:21:19 +00003987 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00003988}
3989
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003990void CGObjCMac::FinishModule() {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003991 EmitModuleInfo();
3992
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00003993 // Emit the dummy bodies for any protocols which were referenced but
3994 // never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003995 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerad64e022009-07-17 23:57:13 +00003996 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
3997 if (I->second->hasInitializer())
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00003998 continue;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003999
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004000 std::vector<llvm::Constant*> Values(5);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004001 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004002 Values[1] = GetClassName(I->first);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004003 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004004 Values[3] = Values[4] =
Owen Andersonc9c88b42009-07-31 20:28:54 +00004005 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004006 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson08e25242009-07-27 22:29:56 +00004007 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004008 Values));
Chris Lattnerad64e022009-07-17 23:57:13 +00004009 CGM.AddUsedGlobal(I->second);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004010 }
4011
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004012 // Add assembler directives to add lazy undefined symbol references
4013 // for classes which are referenced but not defined. This is
4014 // important for correct linker interaction.
Daniel Dunbar33063492009-09-07 00:20:42 +00004015 //
4016 // FIXME: It would be nice if we had an LLVM construct for this.
4017 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
4018 llvm::SmallString<256> Asm;
4019 Asm += CGM.getModule().getModuleInlineAsm();
4020 if (!Asm.empty() && Asm.back() != '\n')
4021 Asm += '\n';
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004022
Daniel Dunbar33063492009-09-07 00:20:42 +00004023 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbar33063492009-09-07 00:20:42 +00004024 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4025 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00004026 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4027 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004028 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004029 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004030 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004031 }
4032
4033 for (size_t i = 0; i < DefinedCategoryNames.size(); ++i) {
4034 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4035 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4036 }
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004037
Daniel Dunbar33063492009-09-07 00:20:42 +00004038 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004039 }
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004040}
4041
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004042CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004043 : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00004044 ObjCTypes(cgm) {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004045 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004046 ObjCABI = 2;
4047}
4048
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004049/* *** */
4050
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004051ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004052 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004053 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4054 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004055
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004056 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004057 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004058 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004059 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00004060 Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004061
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004062 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004063 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004064 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004065
Mike Stumpf5408fe2009-05-16 07:57:57 +00004066 // FIXME: It would be nice to unify this with the opaque type, so that the IR
4067 // comes out a bit cleaner.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004068 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004069 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004070
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004071 // I'm not sure I like this. The implicit coordination is a bit
4072 // gross. We should solve this in a reasonable fashion because this
4073 // is a pretty common task (match some runtime data structure with
4074 // an LLVM data structure).
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004075
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004076 // FIXME: This is leaked.
4077 // FIXME: Merge with rewriter code?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004078
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004079 // struct _objc_super {
4080 // id self;
4081 // Class cls;
4082 // }
Abramo Bagnara465d41b2010-05-11 21:36:43 +00004083 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00004084 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00004085 SourceLocation(), SourceLocation(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004086 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004087 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004088 Ctx.getObjCIdType(), 0, 0, false));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004089 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004090 Ctx.getObjCClassType(), 0, 0, false));
Douglas Gregor838db382010-02-11 01:19:42 +00004091 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004092
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004093 SuperCTy = Ctx.getTagDeclType(RD);
4094 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004095
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004096 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004097 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4098
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004099 // struct _prop_t {
4100 // char *name;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004101 // char *attributes;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004102 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004103 PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004104 CGM.getModule().addTypeName("struct._prop_t",
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004105 PropertyTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004106
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004107 // struct _prop_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004108 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004109 // uint32_t count_of_properties;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004110 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004111 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004112 PropertyListTy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004113 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004114 llvm::ArrayType::get(PropertyTy, 0),
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004115 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004116 CGM.getModule().addTypeName("struct._prop_list_t",
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004117 PropertyListTy);
4118 // struct _prop_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004119 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004120
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004121 // struct _objc_method {
4122 // SEL _cmd;
4123 // char *method_type;
4124 // char *_imp;
4125 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004126 MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004127 Int8PtrTy,
4128 Int8PtrTy,
4129 NULL);
4130 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004131
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004132 // struct _objc_cache *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004133 CacheTy = llvm::OpaqueType::get(VMContext);
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004134 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004135 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004136}
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004137
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004138ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004139 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004140 // struct _objc_method_description {
4141 // SEL name;
4142 // char *types;
4143 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004144 MethodDescriptionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004145 llvm::StructType::get(VMContext, SelectorPtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004146 Int8PtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004147 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004148 CGM.getModule().addTypeName("struct._objc_method_description",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004149 MethodDescriptionTy);
4150
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004151 // struct _objc_method_description_list {
4152 // int count;
4153 // struct _objc_method_description[1];
4154 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004155 MethodDescriptionListTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004156 llvm::StructType::get(VMContext, IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004157 llvm::ArrayType::get(MethodDescriptionTy, 0),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004158 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004159 CGM.getModule().addTypeName("struct._objc_method_description_list",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004160 MethodDescriptionListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004161
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004162 // struct _objc_method_description_list *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004163 MethodDescriptionListPtrTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004164 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004165
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004166 // Protocol description structures
4167
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004168 // struct _objc_protocol_extension {
4169 // uint32_t size; // sizeof(struct _objc_protocol_extension)
4170 // struct _objc_method_description_list *optional_instance_methods;
4171 // struct _objc_method_description_list *optional_class_methods;
4172 // struct _objc_property_list *instance_properties;
4173 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004174 ProtocolExtensionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004175 llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004176 MethodDescriptionListPtrTy,
4177 MethodDescriptionListPtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004178 PropertyListPtrTy,
4179 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004180 CGM.getModule().addTypeName("struct._objc_protocol_extension",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004181 ProtocolExtensionTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004182
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004183 // struct _objc_protocol_extension *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004184 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004185
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004186 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004187
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004188 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
4189 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004190
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004191 const llvm::Type *T =
Mike Stump1eb44332009-09-09 15:08:12 +00004192 llvm::StructType::get(VMContext,
Owen Anderson47a434f2009-08-05 23:18:46 +00004193 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004194 LongTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004195 llvm::ArrayType::get(ProtocolTyHolder, 0),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004196 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004197 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
4198
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004199 // struct _objc_protocol {
4200 // struct _objc_protocol_extension *isa;
4201 // char *protocol_name;
4202 // struct _objc_protocol **_objc_protocol_list;
4203 // struct _objc_method_description_list *instance_methods;
4204 // struct _objc_method_description_list *class_methods;
4205 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004206 T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004207 Int8PtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004208 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004209 MethodDescriptionListPtrTy,
4210 MethodDescriptionListPtrTy,
4211 NULL);
4212 cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
4213
4214 ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004215 CGM.getModule().addTypeName("struct._objc_protocol_list",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004216 ProtocolListTy);
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004217 // struct _objc_protocol_list *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004218 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004219
4220 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004221 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004222 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004223
4224 // Class description structures
4225
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004226 // struct _objc_ivar {
4227 // char *ivar_name;
4228 // char *ivar_type;
4229 // int ivar_offset;
4230 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004231 IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004232 Int8PtrTy,
4233 IntTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004234 NULL);
4235 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
4236
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004237 // struct _objc_ivar_list *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004238 IvarListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004239 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004240 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004241
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004242 // struct _objc_method_list *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004243 MethodListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004244 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004245 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004246
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004247 // struct _objc_class_extension *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004248 ClassExtensionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004249 llvm::StructType::get(VMContext, IntTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004250 Int8PtrTy,
4251 PropertyListPtrTy,
4252 NULL);
4253 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004254 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004255
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004256 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004257
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004258 // struct _objc_class {
4259 // Class isa;
4260 // Class super_class;
4261 // char *name;
4262 // long version;
4263 // long info;
4264 // long instance_size;
4265 // struct _objc_ivar_list *ivars;
4266 // struct _objc_method_list *methods;
4267 // struct _objc_cache *cache;
4268 // struct _objc_protocol_list *protocols;
4269 // char *ivar_layout;
4270 // struct _objc_class_ext *ext;
4271 // };
Owen Anderson47a434f2009-08-05 23:18:46 +00004272 T = llvm::StructType::get(VMContext,
4273 llvm::PointerType::getUnqual(ClassTyHolder),
Owen Anderson96e0fc72009-07-29 22:16:19 +00004274 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004275 Int8PtrTy,
4276 LongTy,
4277 LongTy,
4278 LongTy,
4279 IvarListPtrTy,
4280 MethodListPtrTy,
4281 CachePtrTy,
4282 ProtocolListPtrTy,
4283 Int8PtrTy,
4284 ClassExtensionPtrTy,
4285 NULL);
4286 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004287
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004288 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
4289 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004290 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004291
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004292 // struct _objc_category {
4293 // char *category_name;
4294 // char *class_name;
4295 // struct _objc_method_list *instance_method;
4296 // struct _objc_method_list *class_method;
4297 // uint32_t size; // sizeof(struct _objc_category)
4298 // struct _objc_property_list *instance_properties;// category's @property
4299 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004300 CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00004301 Int8PtrTy,
4302 MethodListPtrTy,
4303 MethodListPtrTy,
4304 ProtocolListPtrTy,
4305 IntTy,
4306 PropertyListPtrTy,
4307 NULL);
4308 CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
4309
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004310 // Global metadata structures
4311
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004312 // struct _objc_symtab {
4313 // long sel_ref_cnt;
4314 // SEL *refs;
4315 // short cls_def_cnt;
4316 // short cat_def_cnt;
4317 // char *defs[cls_def_cnt + cat_def_cnt];
4318 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004319 SymtabTy = llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004320 SelectorPtrTy,
4321 ShortTy,
4322 ShortTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004323 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004324 NULL);
4325 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004326 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004327
Fariborz Jahaniandb286862009-01-22 00:37:21 +00004328 // struct _objc_module {
4329 // long version;
4330 // long size; // sizeof(struct _objc_module)
4331 // char *name;
4332 // struct _objc_symtab* symtab;
4333 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004334 ModuleTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004335 llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004336 LongTy,
4337 Int8PtrTy,
4338 SymtabPtrTy,
4339 NULL);
4340 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00004341
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004342
Mike Stumpf5408fe2009-05-16 07:57:57 +00004343 // FIXME: This is the size of the setjmp buffer and should be target
4344 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson124526b2008-09-09 10:10:21 +00004345 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004346
Anders Carlsson124526b2008-09-09 10:10:21 +00004347 // Exceptions
Owen Anderson96e0fc72009-07-29 22:16:19 +00004348 const llvm::Type *StackPtrTy = llvm::ArrayType::get(
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00004349 llvm::Type::getInt8PtrTy(VMContext), 4);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004350
4351 ExceptionDataTy =
Chris Lattner77b89b82010-06-27 07:15:29 +00004352 llvm::StructType::get(VMContext,
4353 llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
4354 SetJmpBufferSize),
Anders Carlsson124526b2008-09-09 10:10:21 +00004355 StackPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004356 CGM.getModule().addTypeName("struct._objc_exception_data",
Anders Carlsson124526b2008-09-09 10:10:21 +00004357 ExceptionDataTy);
4358
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00004359}
4360
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004361ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004362 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004363 // struct _method_list_t {
4364 // uint32_t entsize; // sizeof(struct _objc_method)
4365 // uint32_t method_count;
4366 // struct _objc_method method_list[method_count];
4367 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004368 MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004369 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004370 llvm::ArrayType::get(MethodTy, 0),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004371 NULL);
4372 CGM.getModule().addTypeName("struct.__method_list_t",
4373 MethodListnfABITy);
4374 // struct method_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004375 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004376
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004377 // struct _protocol_t {
4378 // id isa; // NULL
4379 // const char * const protocol_name;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004380 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004381 // const struct method_list_t * const instance_methods;
4382 // const struct method_list_t * const class_methods;
4383 // const struct method_list_t *optionalInstanceMethods;
4384 // const struct method_list_t *optionalClassMethods;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004385 // const struct _prop_list_t * properties;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004386 // const uint32_t size; // sizeof(struct _protocol_t)
4387 // const uint32_t flags; // = 0
4388 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004389
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004390 // Holder for struct _protocol_list_t *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004391 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004392
Owen Anderson47a434f2009-08-05 23:18:46 +00004393 ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004394 Int8PtrTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004395 llvm::PointerType::getUnqual(
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004396 ProtocolListTyHolder),
4397 MethodListnfABIPtrTy,
4398 MethodListnfABIPtrTy,
4399 MethodListnfABIPtrTy,
4400 MethodListnfABIPtrTy,
4401 PropertyListPtrTy,
4402 IntTy,
4403 IntTy,
4404 NULL);
4405 CGM.getModule().addTypeName("struct._protocol_t",
4406 ProtocolnfABITy);
Daniel Dunbar948e2582009-02-15 07:36:20 +00004407
4408 // struct _protocol_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004409 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004410
Fariborz Jahanianda320092009-01-29 19:24:30 +00004411 // struct _protocol_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004412 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar948e2582009-02-15 07:36:20 +00004413 // struct _protocol_t *[protocol_count];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004414 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004415 ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004416 llvm::ArrayType::get(
Daniel Dunbar948e2582009-02-15 07:36:20 +00004417 ProtocolnfABIPtrTy, 0),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004418 NULL);
4419 CGM.getModule().addTypeName("struct._objc_protocol_list",
4420 ProtocolListnfABITy);
Daniel Dunbar948e2582009-02-15 07:36:20 +00004421 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004422 ProtocolListnfABITy);
4423
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004424 // struct _objc_protocol_list*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004425 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004426
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004427 // struct _ivar_t {
4428 // unsigned long int *offset; // pointer to ivar offset location
4429 // char *name;
4430 // char *type;
4431 // uint32_t alignment;
4432 // uint32_t size;
4433 // }
Mike Stump1eb44332009-09-09 15:08:12 +00004434 IvarnfABITy = llvm::StructType::get(VMContext,
Owen Anderson47a434f2009-08-05 23:18:46 +00004435 llvm::PointerType::getUnqual(LongTy),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004436 Int8PtrTy,
4437 Int8PtrTy,
4438 IntTy,
4439 IntTy,
4440 NULL);
4441 CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004442
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004443 // struct _ivar_list_t {
4444 // uint32 entsize; // sizeof(struct _ivar_t)
4445 // uint32 count;
4446 // struct _iver_t list[count];
4447 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004448 IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004449 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004450 llvm::ArrayType::get(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004451 IvarnfABITy, 0),
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004452 NULL);
4453 CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004454
Owen Anderson96e0fc72009-07-29 22:16:19 +00004455 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004456
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004457 // struct _class_ro_t {
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004458 // uint32_t const flags;
4459 // uint32_t const instanceStart;
4460 // uint32_t const instanceSize;
4461 // uint32_t const reserved; // only when building for 64bit targets
4462 // const uint8_t * const ivarLayout;
4463 // const char *const name;
4464 // const struct _method_list_t * const baseMethods;
4465 // const struct _objc_protocol_list *const baseProtocols;
4466 // const struct _ivar_list_t *const ivars;
4467 // const uint8_t * const weakIvarLayout;
4468 // const struct _prop_list_t * const properties;
4469 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004470
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004471 // FIXME. Add 'reserved' field in 64bit abi mode!
Owen Anderson47a434f2009-08-05 23:18:46 +00004472 ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004473 IntTy,
4474 IntTy,
4475 Int8PtrTy,
4476 Int8PtrTy,
4477 MethodListnfABIPtrTy,
4478 ProtocolListnfABIPtrTy,
4479 IvarListnfABIPtrTy,
4480 Int8PtrTy,
4481 PropertyListPtrTy,
4482 NULL);
4483 CGM.getModule().addTypeName("struct._class_ro_t",
4484 ClassRonfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004485
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004486 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
4487 std::vector<const llvm::Type*> Params;
4488 Params.push_back(ObjectPtrTy);
4489 Params.push_back(SelectorPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004490 ImpnfABITy = llvm::PointerType::getUnqual(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004491 llvm::FunctionType::get(ObjectPtrTy, Params, false));
4492
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004493 // struct _class_t {
4494 // struct _class_t *isa;
4495 // struct _class_t * const superclass;
4496 // void *cache;
4497 // IMP *vtable;
4498 // struct class_ro_t *ro;
4499 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004500
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004501 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Owen Andersona1cf15f2009-07-14 23:10:40 +00004502 ClassnfABITy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004503 llvm::StructType::get(VMContext,
4504 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004505 llvm::PointerType::getUnqual(ClassTyHolder),
4506 CachePtrTy,
4507 llvm::PointerType::getUnqual(ImpnfABITy),
4508 llvm::PointerType::getUnqual(ClassRonfABITy),
4509 NULL);
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004510 CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4511
4512 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004513 ClassnfABITy);
4514
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004515 // LLVM for struct _class_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004516 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004517
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004518 // struct _category_t {
4519 // const char * const name;
4520 // struct _class_t *const cls;
4521 // const struct _method_list_t * const instance_methods;
4522 // const struct _method_list_t * const class_methods;
4523 // const struct _protocol_list_t * const protocols;
4524 // const struct _prop_list_t * const properties;
Fariborz Jahanian45c2ba02009-01-23 17:41:22 +00004525 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004526 CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004527 ClassnfABIPtrTy,
Fariborz Jahanian45c2ba02009-01-23 17:41:22 +00004528 MethodListnfABIPtrTy,
4529 MethodListnfABIPtrTy,
4530 ProtocolListnfABIPtrTy,
4531 PropertyListPtrTy,
4532 NULL);
4533 CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004534
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004535 // New types for nonfragile abi messaging.
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004536 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4537 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004538
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004539 // MessageRefTy - LLVM for:
4540 // struct _message_ref_t {
4541 // IMP messenger;
4542 // SEL name;
4543 // };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004544
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004545 // First the clang type for struct _message_ref_t
Abramo Bagnara465d41b2010-05-11 21:36:43 +00004546 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00004547 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00004548 SourceLocation(), SourceLocation(),
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004549 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004550 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004551 Ctx.VoidPtrTy, 0, 0, false));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004552 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004553 Ctx.getObjCSelType(), 0, 0, false));
Douglas Gregor838db382010-02-11 01:19:42 +00004554 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004555
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004556 MessageRefCTy = Ctx.getTagDeclType(RD);
4557 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4558 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004559
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004560 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004561 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004562
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004563 // SuperMessageRefTy - LLVM for:
4564 // struct _super_message_ref_t {
4565 // SUPER_IMP messenger;
4566 // SEL name;
4567 // };
Owen Anderson47a434f2009-08-05 23:18:46 +00004568 SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004569 SelectorPtrTy,
4570 NULL);
4571 CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004572
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004573 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004574 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4575
Daniel Dunbare588b992009-03-01 04:46:24 +00004576
4577 // struct objc_typeinfo {
4578 // const void** vtable; // objc_ehtype_vtable + 2
4579 // const char* name; // c++ typeinfo string
4580 // Class cls;
4581 // };
Owen Anderson47a434f2009-08-05 23:18:46 +00004582 EHTypeTy = llvm::StructType::get(VMContext,
4583 llvm::PointerType::getUnqual(Int8PtrTy),
Daniel Dunbare588b992009-03-01 04:46:24 +00004584 Int8PtrTy,
4585 ClassnfABIPtrTy,
4586 NULL);
Daniel Dunbar4ff36842009-03-02 06:08:11 +00004587 CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004588 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00004589}
4590
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004591llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004592 FinishNonFragileABIModule();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004593
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004594 return NULL;
4595}
4596
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004597void CGObjCNonFragileABIMac::AddModuleClassList(const
4598 std::vector<llvm::GlobalValue*>
4599 &Container,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004600 const char *SymbolName,
4601 const char *SectionName) {
4602 unsigned NumClasses = Container.size();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004603
Daniel Dunbar463b8762009-05-15 21:48:48 +00004604 if (!NumClasses)
4605 return;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004606
Daniel Dunbar463b8762009-05-15 21:48:48 +00004607 std::vector<llvm::Constant*> Symbols(NumClasses);
4608 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00004609 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar463b8762009-05-15 21:48:48 +00004610 ObjCTypes.Int8PtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004611 llvm::Constant* Init =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004612 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004613 NumClasses),
4614 Symbols);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004615
Daniel Dunbar463b8762009-05-15 21:48:48 +00004616 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00004617 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004618 llvm::GlobalValue::InternalLinkage,
4619 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00004620 SymbolName);
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004621 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Daniel Dunbar463b8762009-05-15 21:48:48 +00004622 GV->setSection(SectionName);
Chris Lattnerad64e022009-07-17 23:57:13 +00004623 CGM.AddUsedGlobal(GV);
Daniel Dunbar463b8762009-05-15 21:48:48 +00004624}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004625
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004626void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4627 // nonfragile abi has no module definition.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004628
Daniel Dunbar463b8762009-05-15 21:48:48 +00004629 // Build list of all implemented class addresses in array
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004630 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004631 AddModuleClassList(DefinedClasses,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004632 "\01L_OBJC_LABEL_CLASS_$",
4633 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004634
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004635 for (unsigned i = 0; i < DefinedClasses.size(); i++) {
4636 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
4637 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4638 continue;
4639 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004640 }
4641
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004642 for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
4643 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
4644 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4645 continue;
4646 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4647 }
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004648
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004649 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004650 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4651 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004652
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004653 // Build list of all implemented category addresses in array
4654 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004655 AddModuleClassList(DefinedCategories,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004656 "\01L_OBJC_LABEL_CATEGORY_$",
4657 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004658 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004659 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4660 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004661
Daniel Dunbarfce176b2010-04-25 20:39:01 +00004662 EmitImageInfo();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004663}
4664
John McCall944c8432011-05-14 03:10:52 +00004665/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
4666/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004667/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004668/// message dispatch call for all the rest.
John McCall944c8432011-05-14 03:10:52 +00004669bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
4670 // At various points we've experimented with using vtable-based
4671 // dispatch for all methods.
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004672 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
4673 default:
John McCall944c8432011-05-14 03:10:52 +00004674 llvm_unreachable("Invalid dispatch method!");
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004675 case CodeGenOptions::Legacy:
Fariborz Jahanian776dbf92010-04-19 17:53:30 +00004676 return false;
John McCall944c8432011-05-14 03:10:52 +00004677 case CodeGenOptions::NonLegacy:
4678 return true;
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004679 case CodeGenOptions::Mixed:
4680 break;
4681 }
4682
4683 // If so, see whether this selector is in the white-list of things which must
4684 // use the new dispatch convention. We lazily build a dense set for this.
John McCall944c8432011-05-14 03:10:52 +00004685 if (VTableDispatchMethods.empty()) {
4686 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
4687 VTableDispatchMethods.insert(GetNullarySelector("class"));
4688 VTableDispatchMethods.insert(GetNullarySelector("self"));
4689 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
4690 VTableDispatchMethods.insert(GetNullarySelector("length"));
4691 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004692
John McCall944c8432011-05-14 03:10:52 +00004693 // These are vtable-based if GC is disabled.
4694 // Optimistically use vtable dispatch for hybrid compiles.
4695 if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) {
4696 VTableDispatchMethods.insert(GetNullarySelector("retain"));
4697 VTableDispatchMethods.insert(GetNullarySelector("release"));
4698 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
4699 }
4700
4701 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
4702 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
4703 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
4704 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
4705 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
4706 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
4707 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
4708
4709 // These are vtable-based if GC is enabled.
4710 // Optimistically use vtable dispatch for hybrid compiles.
4711 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
4712 VTableDispatchMethods.insert(GetNullarySelector("hash"));
4713 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
4714
4715 // "countByEnumeratingWithState:objects:count"
4716 IdentifierInfo *KeyIdents[] = {
4717 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4718 &CGM.getContext().Idents.get("objects"),
4719 &CGM.getContext().Idents.get("count")
4720 };
4721 VTableDispatchMethods.insert(
4722 CGM.getContext().Selectors.getSelector(3, KeyIdents));
4723 }
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004724 }
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004725
John McCall944c8432011-05-14 03:10:52 +00004726 return VTableDispatchMethods.count(Sel);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004727}
4728
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004729// Metadata flags
4730enum MetaDataDlags {
4731 CLS = 0x0,
4732 CLS_META = 0x1,
4733 CLS_ROOT = 0x2,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004734 OBJC2_CLS_HIDDEN = 0x10,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004735 CLS_EXCEPTION = 0x20
4736};
4737/// BuildClassRoTInitializer - generate meta-data for:
4738/// struct _class_ro_t {
4739/// uint32_t const flags;
4740/// uint32_t const instanceStart;
4741/// uint32_t const instanceSize;
4742/// uint32_t const reserved; // only when building for 64bit targets
4743/// const uint8_t * const ivarLayout;
4744/// const char *const name;
4745/// const struct _method_list_t * const baseMethods;
Fariborz Jahanianda320092009-01-29 19:24:30 +00004746/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004747/// const struct _ivar_list_t *const ivars;
4748/// const uint8_t * const weakIvarLayout;
4749/// const struct _prop_list_t * const properties;
4750/// }
4751///
4752llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004753 unsigned flags,
4754 unsigned InstanceStart,
4755 unsigned InstanceSize,
4756 const ObjCImplementationDecl *ID) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004757 std::string ClassName = ID->getNameAsString();
4758 std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
Owen Anderson4a28d5d2009-07-24 23:12:58 +00004759 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4760 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4761 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004762 // FIXME. For 64bit targets add 0 here.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004763 Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4764 : BuildIvarLayout(ID, true);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004765 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004766 // const struct _method_list_t * const baseMethods;
4767 std::vector<llvm::Constant*> Methods;
4768 std::string MethodListName("\01l_OBJC_$_");
4769 if (flags & CLS_META) {
4770 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004771 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004772 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004773 // Class methods should always be defined.
4774 Methods.push_back(GetMethodConstant(*i));
4775 }
4776 } else {
4777 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004778 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004779 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004780 // Instance methods should always be defined.
4781 Methods.push_back(GetMethodConstant(*i));
4782 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004783 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004784 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004785 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004786
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004787 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4788 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004789
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004790 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4791 if (llvm::Constant *C = GetMethodConstant(MD))
4792 Methods.push_back(C);
4793 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4794 if (llvm::Constant *C = GetMethodConstant(MD))
4795 Methods.push_back(C);
4796 }
4797 }
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004798 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004799 Values[ 5] = EmitMethodList(MethodListName,
4800 "__DATA, __objc_const", Methods);
4801
Fariborz Jahanianda320092009-01-29 19:24:30 +00004802 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4803 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004804 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004805 + OID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00004806 OID->all_referenced_protocol_begin(),
4807 OID->all_referenced_protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004808
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00004809 if (flags & CLS_META)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004810 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00004811 else
4812 Values[ 7] = EmitIvarList(ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004813 Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4814 : BuildIvarLayout(ID, false);
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00004815 if (flags & CLS_META)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004816 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00004817 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004818 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4819 ID, ID->getClassInterface(), ObjCTypes);
Owen Anderson08e25242009-07-27 22:29:56 +00004820 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004821 Values);
4822 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004823 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
4824 llvm::GlobalValue::InternalLinkage,
4825 Init,
4826 (flags & CLS_META) ?
4827 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4828 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00004829 CLASS_RO_GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004830 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00004831 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004832 return CLASS_RO_GV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00004833
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004834}
4835
4836/// BuildClassMetaData - This routine defines that to-level meta-data
4837/// for the given ClassName for:
4838/// struct _class_t {
4839/// struct _class_t *isa;
4840/// struct _class_t * const superclass;
4841/// void *cache;
4842/// IMP *vtable;
4843/// struct class_ro_t *ro;
4844/// }
4845///
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004846llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004847 std::string &ClassName,
4848 llvm::Constant *IsAGV,
4849 llvm::Constant *SuperClassGV,
4850 llvm::Constant *ClassRoGV,
4851 bool HiddenVisibility) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004852 std::vector<llvm::Constant*> Values(5);
4853 Values[0] = IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004854 Values[1] = SuperClassGV;
4855 if (!Values[1])
4856 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004857 Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
4858 Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4859 Values[4] = ClassRoGV; // &CLASS_RO_GV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004860 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004861 Values);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004862 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4863 GV->setInitializer(Init);
Fariborz Jahaniandd0db2a2009-01-31 01:07:39 +00004864 GV->setSection("__DATA, __objc_data");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00004865 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004866 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004867 if (HiddenVisibility)
4868 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004869 return GV;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004870}
4871
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004872bool
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00004873CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004874 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004875}
4876
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00004877void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00004878 uint32_t &InstanceStart,
4879 uint32_t &InstanceSize) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004880 const ASTRecordLayout &RL =
Daniel Dunbarb4c79e02009-05-04 21:26:30 +00004881 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004882
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00004883 // InstanceSize is really instance end.
Ken Dyckec299032011-02-11 02:20:09 +00004884 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00004885
4886 // If there are no fields, the start is the same as the end.
4887 if (!RL.getFieldCount())
4888 InstanceStart = InstanceSize;
4889 else
Ken Dyckfb67ccd2011-04-14 00:43:09 +00004890 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbarb02532a2009-04-19 23:41:48 +00004891}
4892
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004893void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
4894 std::string ClassName = ID->getNameAsString();
4895 if (!ObjCEmptyCacheVar) {
4896 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004897 CGM.getModule(),
4898 ObjCTypes.CacheTy,
4899 false,
4900 llvm::GlobalValue::ExternalLinkage,
4901 0,
4902 "_objc_empty_cache");
4903
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004904 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004905 CGM.getModule(),
4906 ObjCTypes.ImpnfABITy,
4907 false,
4908 llvm::GlobalValue::ExternalLinkage,
4909 0,
4910 "_objc_empty_vtable");
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004911 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004912 assert(ID->getClassInterface() &&
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004913 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbar6c1aac82009-04-20 20:18:54 +00004914 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004915 uint32_t InstanceStart =
Duncan Sands9408c452009-05-09 07:08:47 +00004916 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004917 uint32_t InstanceSize = InstanceStart;
4918 uint32_t flags = CLS_META;
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00004919 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4920 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004921
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004922 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004923
4924 bool classIsHidden =
John McCall1fb0caa2010-10-22 21:05:15 +00004925 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004926 if (classIsHidden)
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004927 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00004928 if (ID->getNumIvarInitializers())
4929 flags |= eClassFlags_ABI2_HasCXXStructors;
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004930 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004931 // class is root
4932 flags |= CLS_ROOT;
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004933 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004934 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004935 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004936 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004937 const ObjCInterfaceDecl *Root = ID->getClassInterface();
4938 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4939 Root = Super;
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004940 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004941 if (Root->isWeakImported())
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004942 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004943 // work on super class metadata symbol.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004944 std::string SuperClassName =
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004945 ObjCMetaClassName +
4946 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004947 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004948 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004949 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004950 }
4951 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4952 InstanceStart,
4953 InstanceSize,ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004954 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004955 llvm::GlobalVariable *MetaTClass =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004956 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4957 classIsHidden);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004958 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00004959
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004960 // Metadata for the class
4961 flags = CLS;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004962 if (classIsHidden)
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004963 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00004964 if (ID->getNumIvarInitializers())
4965 flags |= eClassFlags_ABI2_HasCXXStructors;
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004966
Douglas Gregor68584ed2009-06-18 16:11:24 +00004967 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004968 flags |= CLS_EXCEPTION;
4969
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004970 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004971 flags |= CLS_ROOT;
4972 SuperClassGV = 0;
Chris Lattnerb7b58b12009-04-19 06:02:28 +00004973 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004974 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004975 std::string RootClassName =
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004976 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004977 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004978 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004979 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004980 }
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00004981 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004982 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00004983 InstanceStart,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004984 InstanceSize,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00004985 ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004986
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004987 TClassName = ObjCClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004988 llvm::GlobalVariable *ClassMD =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004989 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
4990 classIsHidden);
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004991 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004992
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004993 // Determine if this class is also "non-lazy".
4994 if (ImplementationIsNonLazy(ID))
4995 DefinedNonLazyClasses.push_back(ClassMD);
4996
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004997 // Force the definition of the EHType if necessary.
4998 if (flags & CLS_EXCEPTION)
4999 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00005000 // Make sure method definition entries are all clear for next implementation.
5001 MethodDefinitions.clear();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005002}
5003
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005004/// GenerateProtocolRef - This routine is called to generate code for
5005/// a protocol reference expression; as in:
5006/// @code
5007/// @protocol(Proto1);
5008/// @endcode
5009/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5010/// which will hold address of the protocol meta-data.
5011///
5012llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005013 const ObjCProtocolDecl *PD) {
5014
Fariborz Jahanian960cd062009-04-10 18:47:34 +00005015 // This routine is called for @protocol only. So, we must build definition
5016 // of protocol's meta-data (not a reference to it!)
5017 //
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005018 llvm::Constant *Init =
5019 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5020 ObjCTypes.ExternalProtocolPtrTy);
5021
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005022 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar4087f272010-08-17 22:39:59 +00005023 ProtocolName += PD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005024
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005025 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5026 if (PTGV)
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005027 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005028 PTGV = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005029 CGM.getModule(),
5030 Init->getType(), false,
5031 llvm::GlobalValue::WeakAnyLinkage,
5032 Init,
5033 ProtocolName);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005034 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5035 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005036 CGM.AddUsedGlobal(PTGV);
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005037 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005038}
5039
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005040/// GenerateCategory - Build metadata for a category implementation.
5041/// struct _category_t {
5042/// const char * const name;
5043/// struct _class_t *const cls;
5044/// const struct _method_list_t * const instance_methods;
5045/// const struct _method_list_t * const class_methods;
5046/// const struct _protocol_list_t * const protocols;
5047/// const struct _prop_list_t * const properties;
5048/// }
5049///
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005050void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005051 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005052 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005053 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5054 "_$_" + OCD->getNameAsString());
5055 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005056 Interface->getNameAsString());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005057
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005058 std::vector<llvm::Constant*> Values(6);
5059 Values[0] = GetClassName(OCD->getIdentifier());
5060 // meta-class entry symbol
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005061 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005062 if (Interface->isWeakImported())
Fariborz Jahanian2cdcc4c2009-11-17 22:02:21 +00005063 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5064
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005065 Values[1] = ClassGV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005066 std::vector<llvm::Constant*> Methods;
5067 std::string MethodListName(Prefix);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005068 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005069 "_$_" + OCD->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005070
5071 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005072 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005073 // Instance methods should always be defined.
5074 Methods.push_back(GetMethodConstant(*i));
5075 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005076
5077 Values[2] = EmitMethodList(MethodListName,
5078 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005079 Methods);
5080
5081 MethodListName = Prefix;
5082 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5083 OCD->getNameAsString();
5084 Methods.clear();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005085 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005086 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005087 // Class methods should always be defined.
5088 Methods.push_back(GetMethodConstant(*i));
5089 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005090
5091 Values[3] = EmitMethodList(MethodListName,
5092 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005093 Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005094 const ObjCCategoryDecl *Category =
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00005095 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005096 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005097 llvm::SmallString<256> ExtName;
5098 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5099 << OCD->getName();
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005100 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005101 + Interface->getName() + "_$_"
5102 + Category->getName(),
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005103 Category->protocol_begin(),
5104 Category->protocol_end());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005105 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5106 OCD, Category, ObjCTypes);
Mike Stumpb3589f42009-07-30 22:28:39 +00005107 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00005108 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5109 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005110 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005111
5112 llvm::Constant *Init =
5113 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005114 Values);
5115 llvm::GlobalVariable *GCATV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005116 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005117 false,
5118 llvm::GlobalValue::InternalLinkage,
5119 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005120 ExtCatName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005121 GCATV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005122 CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005123 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerad64e022009-07-17 23:57:13 +00005124 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005125 DefinedCategories.push_back(GCATV);
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005126
5127 // Determine if this category is also "non-lazy".
5128 if (ImplementationIsNonLazy(OCD))
5129 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00005130 // method definition entries must be clear for next implementation.
5131 MethodDefinitions.clear();
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005132}
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005133
5134/// GetMethodConstant - Return a struct objc_method constant for the
5135/// given method if it has been defined. The result is null if the
5136/// method has not been defined. The return value has type MethodPtrTy.
5137llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005138 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00005139 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005140 if (!Fn)
5141 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005142
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005143 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005144 Method[0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00005145 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005146 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005147 Method[1] = GetMethodVarType(MD);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005148 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005149 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005150}
5151
5152/// EmitMethodList - Build meta-data for method declarations
5153/// struct _method_list_t {
5154/// uint32_t entsize; // sizeof(struct _objc_method)
5155/// uint32_t method_count;
5156/// struct _objc_method method_list[method_count];
5157/// }
5158///
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005159llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
5160 const char *Section,
5161 const ConstantVector &Methods) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005162 // Return null for empty list.
5163 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00005164 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005165
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005166 std::vector<llvm::Constant*> Values(3);
5167 // sizeof(struct _objc_method)
Duncan Sands9408c452009-05-09 07:08:47 +00005168 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005169 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005170 // method_count
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005171 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00005172 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005173 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00005174 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005175 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005176
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005177 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005178 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005179 llvm::GlobalValue::InternalLinkage,
5180 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005181 Name);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005182 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005183 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005184 GV->setSection(Section);
Chris Lattnerad64e022009-07-17 23:57:13 +00005185 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005186 return llvm::ConstantExpr::getBitCast(GV,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005187 ObjCTypes.MethodListnfABIPtrTy);
5188}
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005189
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005190/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5191/// the given ivar.
Daniel Dunbare83be122010-04-02 21:14:02 +00005192llvm::GlobalVariable *
5193CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5194 const ObjCIvarDecl *Ivar) {
5195 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbara81419d2009-05-05 00:36:57 +00005196 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregor6ab35242009-04-09 21:40:53 +00005197 '.' + Ivar->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005198 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005199 CGM.getModule().getGlobalVariable(Name);
5200 if (!IvarOffsetGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005201 IvarOffsetGV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005202 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005203 false,
5204 llvm::GlobalValue::ExternalLinkage,
5205 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00005206 Name);
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005207 return IvarOffsetGV;
5208}
5209
Daniel Dunbare83be122010-04-02 21:14:02 +00005210llvm::Constant *
5211CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5212 const ObjCIvarDecl *Ivar,
5213 unsigned long int Offset) {
Daniel Dunbar737c5022009-04-19 00:44:02 +00005214 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005215 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar737c5022009-04-19 00:44:02 +00005216 Offset));
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005217 IvarOffsetGV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005218 CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbar737c5022009-04-19 00:44:02 +00005219
Mike Stumpf5408fe2009-05-16 07:57:57 +00005220 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
5221 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbar737c5022009-04-19 00:44:02 +00005222 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5223 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall1fb0caa2010-10-22 21:05:15 +00005224 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00005225 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar04d40782009-04-14 06:00:08 +00005226 else
Fariborz Jahanian77c9fd22009-04-06 18:30:00 +00005227 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendling1f382512011-05-04 21:37:25 +00005228 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005229 return IvarOffsetGV;
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005230}
5231
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005232/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar11394522009-04-18 08:51:00 +00005233/// implementation. The return value has type
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005234/// IvarListnfABIPtrTy.
5235/// struct _ivar_t {
5236/// unsigned long int *offset; // pointer to ivar offset location
5237/// char *name;
5238/// char *type;
5239/// uint32_t alignment;
5240/// uint32_t size;
5241/// }
5242/// struct _ivar_list_t {
5243/// uint32 entsize; // sizeof(struct _ivar_t)
5244/// uint32 count;
5245/// struct _iver_t list[count];
5246/// }
5247///
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00005248
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005249llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005250 const ObjCImplementationDecl *ID) {
5251
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005252 std::vector<llvm::Constant*> Ivars, Ivar(5);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005253
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005254 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5255 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005256
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005257 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005258
Daniel Dunbar91636d62009-04-20 00:33:43 +00005259 // Collect declared and synthesized ivars in a small vector.
Fariborz Jahanian18191882009-03-31 18:11:23 +00005260 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00005261 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005262
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00005263 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
5264 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00005265 // Ignore unnamed bit-fields.
5266 if (!IVD->getDeclName())
5267 continue;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005268 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005269 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00005270 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5271 Ivar[2] = GetMethodVarType(IVD);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005272 const llvm::Type *FieldTy =
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00005273 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Duncan Sands9408c452009-05-09 07:08:47 +00005274 unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005275 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005276 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005277 Align = llvm::Log2_32(Align);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005278 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbar91636d62009-04-20 00:33:43 +00005279 // NOTE. Size of a bitfield does not match gcc's, because of the
5280 // way bitfields are treated special in each. But I am told that
5281 // 'size' for bitfield ivars is ignored by the runtime so it does
5282 // not matter. If it matters, there is enough info to get the
5283 // bitfield right!
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005284 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson08e25242009-07-27 22:29:56 +00005285 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005286 }
5287 // Return null for empty list.
5288 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00005289 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005290 std::vector<llvm::Constant*> Values(3);
Duncan Sands9408c452009-05-09 07:08:47 +00005291 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005292 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5293 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00005294 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005295 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00005296 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005297 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005298 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5299 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005300 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005301 llvm::GlobalValue::InternalLinkage,
5302 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005303 Prefix + OID->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005304 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005305 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005306 GV->setSection("__DATA, __objc_const");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005307
Chris Lattnerad64e022009-07-17 23:57:13 +00005308 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005309 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005310}
5311
5312llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005313 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005314 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005315
Fariborz Jahanianda320092009-01-29 19:24:30 +00005316 if (!Entry) {
5317 // We use the initializer as a marker of whether this is a forward
5318 // reference or not. At module finalization we add the empty
5319 // contents for protocols which were referenced but never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005320 Entry =
5321 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5322 llvm::GlobalValue::ExternalLinkage,
5323 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005324 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianda320092009-01-29 19:24:30 +00005325 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00005326 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005327
Fariborz Jahanianda320092009-01-29 19:24:30 +00005328 return Entry;
5329}
5330
5331/// GetOrEmitProtocol - Generate the protocol meta-data:
5332/// @code
5333/// struct _protocol_t {
5334/// id isa; // NULL
5335/// const char * const protocol_name;
5336/// const struct _protocol_list_t * protocol_list; // super protocols
5337/// const struct method_list_t * const instance_methods;
5338/// const struct method_list_t * const class_methods;
5339/// const struct method_list_t *optionalInstanceMethods;
5340/// const struct method_list_t *optionalClassMethods;
5341/// const struct _prop_list_t * properties;
5342/// const uint32_t size; // sizeof(struct _protocol_t)
5343/// const uint32_t flags; // = 0
5344/// }
5345/// @endcode
5346///
5347
5348llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005349 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005350 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005351
Fariborz Jahanianda320092009-01-29 19:24:30 +00005352 // Early exit if a defining object has already been generated.
5353 if (Entry && Entry->hasInitializer())
5354 return Entry;
5355
Fariborz Jahanianda320092009-01-29 19:24:30 +00005356 // Construct method lists.
5357 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5358 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005359 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005360 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005361 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005362 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005363 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5364 OptInstanceMethods.push_back(C);
5365 } else {
5366 InstanceMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005367 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00005368 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005369
5370 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005371 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005372 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005373 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005374 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5375 OptClassMethods.push_back(C);
5376 } else {
5377 ClassMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005378 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00005379 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005380
Fariborz Jahanianda320092009-01-29 19:24:30 +00005381 std::vector<llvm::Constant*> Values(10);
5382 // isa is NULL
Owen Andersonc9c88b42009-07-31 20:28:54 +00005383 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005384 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005385 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5386 PD->protocol_begin(),
5387 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005388
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005389 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005390 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005391 "__DATA, __objc_const",
5392 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005393 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005394 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005395 "__DATA, __objc_const",
5396 ClassMethods);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005397 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005398 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005399 "__DATA, __objc_const",
5400 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005401 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005402 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005403 "__DATA, __objc_const",
5404 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005405 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005406 0, PD, ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005407 uint32_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00005408 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005409 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Andersonc9c88b42009-07-31 20:28:54 +00005410 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005411 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanianda320092009-01-29 19:24:30 +00005412 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005413
Fariborz Jahanianda320092009-01-29 19:24:30 +00005414 if (Entry) {
5415 // Already created, fix the linkage and update the initializer.
Mike Stump286acbd2009-03-07 16:33:28 +00005416 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005417 Entry->setInitializer(Init);
5418 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005419 Entry =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005420 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
5421 false, llvm::GlobalValue::WeakAnyLinkage, Init,
5422 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005423 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005424 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanianda320092009-01-29 19:24:30 +00005425 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00005426 }
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005427 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005428 CGM.AddUsedGlobal(Entry);
5429
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005430 // Use this protocol meta-data to build protocol list table in section
5431 // __DATA, __objc_protolist
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005432 llvm::GlobalVariable *PTGV =
5433 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
5434 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
5435 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005436 PTGV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005437 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbar0bf21992009-04-15 02:56:18 +00005438 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005439 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005440 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005441 return Entry;
5442}
5443
5444/// EmitProtocolList - Generate protocol list meta-data:
5445/// @code
5446/// struct _protocol_list_t {
5447/// long protocol_count; // Note, this is 32/64 bit
5448/// struct _protocol_t[protocol_count];
5449/// }
5450/// @endcode
5451///
5452llvm::Constant *
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005453CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
5454 ObjCProtocolDecl::protocol_iterator begin,
5455 ObjCProtocolDecl::protocol_iterator end) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005456 std::vector<llvm::Constant*> ProtocolRefs;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005457
Fariborz Jahanianda320092009-01-29 19:24:30 +00005458 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005459 if (begin == end)
Owen Andersonc9c88b42009-07-31 20:28:54 +00005460 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005461
Daniel Dunbar948e2582009-02-15 07:36:20 +00005462 // FIXME: We shouldn't need to do this lookup here, should we?
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005463 llvm::SmallString<256> TmpName;
5464 Name.toVector(TmpName);
5465 llvm::GlobalVariable *GV =
5466 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005467 if (GV)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005468 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005469
Daniel Dunbar948e2582009-02-15 07:36:20 +00005470 for (; begin != end; ++begin)
5471 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5472
Fariborz Jahanianda320092009-01-29 19:24:30 +00005473 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00005474 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005475 ObjCTypes.ProtocolnfABIPtrTy));
5476
Fariborz Jahanianda320092009-01-29 19:24:30 +00005477 std::vector<llvm::Constant*> Values(2);
Owen Andersona1cf15f2009-07-14 23:10:40 +00005478 Values[0] =
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005479 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005480 Values[1] =
Owen Anderson7db6d832009-07-28 18:33:04 +00005481 llvm::ConstantArray::get(
Owen Anderson96e0fc72009-07-29 22:16:19 +00005482 llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005483 ProtocolRefs.size()),
5484 ProtocolRefs);
5485
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005486 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Owen Anderson1c431b32009-07-08 19:05:04 +00005487 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanianda320092009-01-29 19:24:30 +00005488 llvm::GlobalValue::InternalLinkage,
5489 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005490 Name);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005491 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005492 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005493 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Chris Lattnerad64e022009-07-17 23:57:13 +00005494 CGM.AddUsedGlobal(GV);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005495 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar948e2582009-02-15 07:36:20 +00005496 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005497}
5498
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005499/// GetMethodDescriptionConstant - This routine build following meta-data:
5500/// struct _objc_method {
5501/// SEL _cmd;
5502/// char *method_type;
5503/// char *_imp;
5504/// }
5505
5506llvm::Constant *
5507CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
5508 std::vector<llvm::Constant*> Desc(3);
Owen Andersona1cf15f2009-07-14 23:10:40 +00005509 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005510 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5511 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005512 Desc[1] = GetMethodVarType(MD);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005513 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00005514 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005515 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005516}
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005517
5518/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
5519/// This code gen. amounts to generating code for:
5520/// @code
5521/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
5522/// @encode
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005523///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00005524LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall506b57e2010-05-17 21:00:27 +00005525 CodeGen::CodeGenFunction &CGF,
5526 QualType ObjectTy,
5527 llvm::Value *BaseValue,
5528 const ObjCIvarDecl *Ivar,
5529 unsigned CVRQualifiers) {
5530 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00005531 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5532 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005533}
5534
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00005535llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005536 CodeGen::CodeGenFunction &CGF,
5537 const ObjCInterfaceDecl *Interface,
5538 const ObjCIvarDecl *Ivar) {
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005539 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00005540}
5541
John McCallb1e81442011-05-13 23:16:18 +00005542static void appendSelectorForMessageRefTable(std::string &buffer,
5543 Selector selector) {
5544 if (selector.isUnarySelector()) {
5545 buffer += selector.getNameForSlot(0);
5546 return;
5547 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005548
John McCallb1e81442011-05-13 23:16:18 +00005549 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
5550 buffer += selector.getNameForSlot(i);
5551 buffer += '_';
5552 }
5553}
5554
John McCall944c8432011-05-14 03:10:52 +00005555/// Emit a "v-table" message send. We emit a weak hidden-visibility
5556/// struct, initially containing the selector pointer and a pointer to
5557/// a "fixup" variant of the appropriate objc_msgSend. To call, we
5558/// load and call the function pointer, passing the address of the
5559/// struct as the second parameter. The runtime determines whether
5560/// the selector is currently emitted using vtable dispatch; if so, it
5561/// substitutes a stub function which simply tail-calls through the
5562/// appropriate vtable slot, and if not, it substitues a stub function
5563/// which tail-calls objc_msgSend. Both stubs adjust the selector
5564/// argument to correctly point to the selector.
5565RValue
5566CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
5567 ReturnValueSlot returnSlot,
5568 QualType resultType,
5569 Selector selector,
5570 llvm::Value *arg0,
5571 QualType arg0Type,
5572 bool isSuper,
5573 const CallArgList &formalArgs,
5574 const ObjCMethodDecl *method) {
John McCallb1e81442011-05-13 23:16:18 +00005575 // Compute the actual arguments.
5576 CallArgList args;
5577
John McCall944c8432011-05-14 03:10:52 +00005578 // First argument: the receiver / super-call structure.
John McCallb1e81442011-05-13 23:16:18 +00005579 if (!isSuper)
John McCall944c8432011-05-14 03:10:52 +00005580 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
5581 args.add(RValue::get(arg0), arg0Type);
John McCallb1e81442011-05-13 23:16:18 +00005582
John McCall944c8432011-05-14 03:10:52 +00005583 // Second argument: a pointer to the message ref structure. Leave
5584 // the actual argument value blank for now.
John McCallb1e81442011-05-13 23:16:18 +00005585 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
5586
5587 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
5588
5589 const CGFunctionInfo &fnInfo =
5590 CGM.getTypes().getFunctionInfo(resultType, args,
5591 FunctionType::ExtInfo());
5592
John McCall944c8432011-05-14 03:10:52 +00005593 // Find the function to call and the mangled name for the message
5594 // ref structure. Using a different mangled name wouldn't actually
5595 // be a problem; it would just be a waste.
5596 //
5597 // The runtime currently never uses vtable dispatch for anything
5598 // except normal, non-super message-sends.
5599 // FIXME: don't use this for that.
John McCallb1e81442011-05-13 23:16:18 +00005600 llvm::Constant *fn = 0;
5601 std::string messageRefName("\01l_");
5602 if (CGM.ReturnTypeUsesSRet(fnInfo)) {
5603 EmitNullReturnInitialization(CGF, returnSlot, resultType);
5604 if (isSuper) {
5605 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5606 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005607 } else {
John McCallb1e81442011-05-13 23:16:18 +00005608 fn = ObjCTypes.getMessageSendStretFixupFn();
5609 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005610 }
John McCallb1e81442011-05-13 23:16:18 +00005611 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
5612 fn = ObjCTypes.getMessageSendFpretFixupFn();
5613 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stumpb3589f42009-07-30 22:28:39 +00005614 } else {
John McCallb1e81442011-05-13 23:16:18 +00005615 if (isSuper) {
5616 fn = ObjCTypes.getMessageSendSuper2FixupFn();
5617 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005618 } else {
John McCallb1e81442011-05-13 23:16:18 +00005619 fn = ObjCTypes.getMessageSendFixupFn();
5620 messageRefName += "objc_msgSend_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005621 }
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005622 }
John McCallb1e81442011-05-13 23:16:18 +00005623 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5624 messageRefName += '_';
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005625
John McCallb1e81442011-05-13 23:16:18 +00005626 // Append the selector name, except use underscores anywhere we
5627 // would have used colons.
5628 appendSelectorForMessageRefTable(messageRefName, selector);
5629
5630 llvm::GlobalVariable *messageRef
5631 = CGM.getModule().getGlobalVariable(messageRefName);
5632 if (!messageRef) {
John McCall944c8432011-05-14 03:10:52 +00005633 // Build the message ref structure.
John McCallb1e81442011-05-13 23:16:18 +00005634 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
5635 llvm::Constant *init =
5636 llvm::ConstantStruct::get(VMContext, values, 2, false);
5637 messageRef = new llvm::GlobalVariable(CGM.getModule(),
5638 init->getType(),
5639 /*constant*/ false,
5640 llvm::GlobalValue::WeakAnyLinkage,
5641 init,
5642 messageRefName);
5643 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
5644 messageRef->setAlignment(16);
5645 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
5646 }
5647 llvm::Value *mref =
5648 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
5649
John McCall944c8432011-05-14 03:10:52 +00005650 // Update the message ref argument.
John McCallb1e81442011-05-13 23:16:18 +00005651 args[1].RV = RValue::get(mref);
5652
5653 // Load the function to call from the message ref table.
5654 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
5655 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
5656
5657 bool variadic = method ? method->isVariadic() : false;
5658 const llvm::FunctionType *fnType =
5659 CGF.getTypes().GetFunctionType(fnInfo, variadic);
5660 callee = CGF.Builder.CreateBitCast(callee,
5661 llvm::PointerType::getUnqual(fnType));
5662
5663 return CGF.EmitCall(fnInfo, callee, returnSlot, args);
Fariborz Jahanian46551122009-02-04 00:22:57 +00005664}
5665
5666/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005667CodeGen::RValue
5668CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00005669 ReturnValueSlot Return,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005670 QualType ResultType,
5671 Selector Sel,
5672 llvm::Value *Receiver,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005673 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00005674 const ObjCInterfaceDecl *Class,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005675 const ObjCMethodDecl *Method) {
John McCall944c8432011-05-14 03:10:52 +00005676 return isVTableDispatchedSelector(Sel)
5677 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005678 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00005679 false, CallArgs, Method)
5680 : EmitMessageSend(CGF, Return, ResultType,
5681 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005682 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00005683 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian46551122009-02-04 00:22:57 +00005684}
5685
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005686llvm::GlobalVariable *
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005687CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005688 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5689
Daniel Dunbardfff2302009-03-02 05:18:14 +00005690 if (!GV) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005691 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005692 false, llvm::GlobalValue::ExternalLinkage,
5693 0, Name);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005694 }
5695
5696 return GV;
5697}
5698
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005699llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5700 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005701 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005702
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005703 if (!Entry) {
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005704 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005705 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005706 Entry =
5707 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005708 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005709 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005710 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005711 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005712 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005713 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00005714 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005715 CGM.AddUsedGlobal(Entry);
Daniel Dunbar11394522009-04-18 08:51:00 +00005716 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005717
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005718 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar11394522009-04-18 08:51:00 +00005719}
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005720
Daniel Dunbar11394522009-04-18 08:51:00 +00005721llvm::Value *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005722CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00005723 const ObjCInterfaceDecl *ID) {
5724 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005725
Daniel Dunbar11394522009-04-18 08:51:00 +00005726 if (!Entry) {
5727 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5728 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005729 Entry =
5730 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005731 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005732 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005733 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar11394522009-04-18 08:51:00 +00005734 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005735 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005736 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00005737 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005738 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005739 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005740
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005741 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005742}
5743
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005744/// EmitMetaClassRef - Return a Value * of the address of _class_t
5745/// meta-data
5746///
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005747llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5748 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005749 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5750 if (Entry)
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005751 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005752
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005753 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005754 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005755 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00005756 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005757 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005758 MetaClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005759 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005760 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005761 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005762 ObjCTypes.ClassnfABIPtrTy));
5763
Daniel Dunbar33af70f2009-04-15 19:03:14 +00005764 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005765 CGM.AddUsedGlobal(Entry);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005766
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005767 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005768}
5769
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005770/// GetClass - Return a reference to the class for the given interface
5771/// decl.
5772llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5773 const ObjCInterfaceDecl *ID) {
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005774 if (ID->isWeakImported()) {
Fariborz Jahanian269f8bc2009-11-17 22:42:00 +00005775 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5776 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5777 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5778 }
5779
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005780 return EmitClassRef(Builder, ID);
5781}
5782
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005783/// Generates a message send where the super is the receiver. This is
5784/// a message send to self with special delivery semantics indicating
5785/// which class's method should be called.
5786CodeGen::RValue
5787CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00005788 ReturnValueSlot Return,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005789 QualType ResultType,
5790 Selector Sel,
5791 const ObjCInterfaceDecl *Class,
5792 bool isCategoryImpl,
5793 llvm::Value *Receiver,
5794 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005795 const CodeGen::CallArgList &CallArgs,
5796 const ObjCMethodDecl *Method) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005797 // ...
5798 // Create and init a super structure; this is a (receiver, class)
5799 // pair we will pass to objc_msgSendSuper.
5800 llvm::Value *ObjCSuper =
John McCall604da292011-03-04 08:00:29 +00005801 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005802
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005803 llvm::Value *ReceiverAsObject =
5804 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5805 CGF.Builder.CreateStore(ReceiverAsObject,
5806 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005807
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005808 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005809 llvm::Value *Target;
5810 if (IsClassMessage) {
5811 if (isCategoryImpl) {
5812 // Message sent to "super' in a class method defined in
5813 // a category implementation.
Daniel Dunbar11394522009-04-18 08:51:00 +00005814 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005815 Target = CGF.Builder.CreateStructGEP(Target, 0);
5816 Target = CGF.Builder.CreateLoad(Target);
Mike Stumpb3589f42009-07-30 22:28:39 +00005817 } else
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005818 Target = EmitMetaClassRef(CGF.Builder, Class);
Mike Stumpb3589f42009-07-30 22:28:39 +00005819 } else
Daniel Dunbar11394522009-04-18 08:51:00 +00005820 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005821
Mike Stumpf5408fe2009-05-16 07:57:57 +00005822 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5823 // ObjCTypes types.
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005824 const llvm::Type *ClassTy =
5825 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
5826 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
5827 CGF.Builder.CreateStore(Target,
5828 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005829
John McCall944c8432011-05-14 03:10:52 +00005830 return (isVTableDispatchedSelector(Sel))
5831 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005832 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00005833 true, CallArgs, Method)
5834 : EmitMessageSend(CGF, Return, ResultType,
5835 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005836 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00005837 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005838}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005839
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005840llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian03b29602010-06-17 19:56:20 +00005841 Selector Sel, bool lval) {
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005842 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005843
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005844 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005845 llvm::Constant *Casted =
5846 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5847 ObjCTypes.SelectorPtrTy);
5848 Entry =
5849 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
5850 llvm::GlobalValue::InternalLinkage,
5851 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00005852 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005853 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005854 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005855
Fariborz Jahanian03b29602010-06-17 19:56:20 +00005856 if (lval)
5857 return Entry;
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005858 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005859}
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005860/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005861/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005862///
5863void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005864 llvm::Value *src,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005865 llvm::Value *dst,
5866 llvm::Value *ivarOffset) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005867 const llvm::Type * SrcTy = src->getType();
5868 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005869 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005870 assert(Size <= 8 && "does not support size > 8");
5871 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5872 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005873 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5874 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005875 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5876 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005877 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5878 src, dst, ivarOffset);
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005879 return;
5880}
5881
5882/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5883/// objc_assign_strongCast (id src, id *dst)
5884///
5885void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005886 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005887 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005888 const llvm::Type * SrcTy = src->getType();
5889 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005890 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005891 assert(Size <= 8 && "does not support size > 8");
5892 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005893 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005894 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5895 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005896 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5897 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00005898 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005899 src, dst, "weakassign");
5900 return;
5901}
5902
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005903void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005904 CodeGen::CodeGenFunction &CGF,
5905 llvm::Value *DestPtr,
5906 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00005907 llvm::Value *Size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005908 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5909 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005910 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00005911 DestPtr, SrcPtr, Size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005912 return;
5913}
5914
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005915/// EmitObjCWeakRead - Code gen for loading value of a __weak
5916/// object: objc_read_weak (id *src)
5917///
5918llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005919 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005920 llvm::Value *AddrWeakObj) {
Eli Friedman8339b352009-03-07 03:57:15 +00005921 const llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005922 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5923 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00005924 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005925 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00005926 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005927 return read_weak;
5928}
5929
5930/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
5931/// objc_assign_weak (id src, id *dst)
5932///
5933void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005934 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005935 const llvm::Type * SrcTy = src->getType();
5936 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005937 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005938 assert(Size <= 8 && "does not support size > 8");
5939 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5940 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005941 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5942 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005943 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5944 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00005945 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005946 src, dst, "weakassign");
5947 return;
5948}
5949
5950/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
5951/// objc_assign_global (id src, id *dst)
5952///
5953void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00005954 llvm::Value *src, llvm::Value *dst,
5955 bool threadlocal) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005956 const llvm::Type * SrcTy = src->getType();
5957 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005958 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005959 assert(Size <= 8 && "does not support size > 8");
5960 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5961 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005962 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5963 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005964 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5965 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00005966 if (!threadlocal)
5967 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
5968 src, dst, "globalassign");
5969 else
5970 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
5971 src, dst, "threadlocalassign");
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005972 return;
5973}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005974
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005975void
John McCallf1549f62010-07-06 01:34:17 +00005976CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
5977 const ObjCAtSynchronizedStmt &S) {
David Chisnall05dc91b2011-03-25 17:46:35 +00005978 EmitAtSynchronizedStmt(CGF, S,
5979 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
5980 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallf1549f62010-07-06 01:34:17 +00005981}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005982
John McCall5a180392010-07-24 00:37:23 +00005983llvm::Constant *
5984CGObjCNonFragileABIMac::GetEHType(QualType T) {
5985 // There's a particular fixed type info for 'id'.
5986 if (T->isObjCIdType() ||
5987 T->isObjCQualifiedIdType()) {
5988 llvm::Constant *IDEHType =
5989 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
5990 if (!IDEHType)
5991 IDEHType =
5992 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
5993 false,
5994 llvm::GlobalValue::ExternalLinkage,
5995 0, "OBJC_EHTYPE_id");
5996 return IDEHType;
5997 }
5998
5999 // All other types should be Objective-C interface pointer types.
6000 const ObjCObjectPointerType *PT =
6001 T->getAs<ObjCObjectPointerType>();
6002 assert(PT && "Invalid @catch type.");
6003 const ObjCInterfaceType *IT = PT->getInterfaceType();
6004 assert(IT && "Invalid @catch type.");
6005 return GetInterfaceEHType(IT->getDecl(), false);
6006}
6007
John McCallf1549f62010-07-06 01:34:17 +00006008void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6009 const ObjCAtTryStmt &S) {
David Chisnall05dc91b2011-03-25 17:46:35 +00006010 EmitTryCatchStmt(CGF, S,
6011 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6012 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6013 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006014}
6015
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006016/// EmitThrowStmt - Generate code for a throw statement.
6017void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6018 const ObjCAtThrowStmt &S) {
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006019 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall7ec404c2010-10-16 08:21:07 +00006020 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
John McCallfd186ac2010-10-16 16:34:08 +00006021 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy,
6022 "tmp");
John McCall7ec404c2010-10-16 08:21:07 +00006023 llvm::Value *Args[] = { Exception };
6024 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(),
6025 Args, Args+1)
6026 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006027 } else {
John McCall7ec404c2010-10-16 08:21:07 +00006028 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn(), 0, 0)
6029 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006030 }
6031
John McCall7ec404c2010-10-16 08:21:07 +00006032 CGF.Builder.CreateUnreachable();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006033 CGF.Builder.ClearInsertionPoint();
6034}
Daniel Dunbare588b992009-03-01 04:46:24 +00006035
John McCall5a180392010-07-24 00:37:23 +00006036llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006037CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006038 bool ForDefinition) {
Daniel Dunbare588b992009-03-01 04:46:24 +00006039 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbare588b992009-03-01 04:46:24 +00006040
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006041 // If we don't need a definition, return the entry if found or check
6042 // if we use an external reference.
6043 if (!ForDefinition) {
6044 if (Entry)
6045 return Entry;
Daniel Dunbar7e075cb2009-04-07 06:43:45 +00006046
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006047 // If this type (or a super class) has the __objc_exception__
6048 // attribute, emit an external reference.
Douglas Gregor68584ed2009-06-18 16:11:24 +00006049 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006050 return Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00006051 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006052 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006053 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006054 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006055 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006056 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006057
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006058 // Otherwise we need to either make a new entry or fill in the
6059 // initializer.
6060 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006061 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbare588b992009-03-01 04:46:24 +00006062 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006063 llvm::GlobalVariable *VTableGV =
Daniel Dunbare588b992009-03-01 04:46:24 +00006064 CGM.getModule().getGlobalVariable(VTableName);
6065 if (!VTableGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006066 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6067 false,
Daniel Dunbare588b992009-03-01 04:46:24 +00006068 llvm::GlobalValue::ExternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00006069 0, VTableName);
Daniel Dunbare588b992009-03-01 04:46:24 +00006070
Chris Lattner77b89b82010-06-27 07:15:29 +00006071 llvm::Value *VTableIdx =
6072 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
Daniel Dunbare588b992009-03-01 04:46:24 +00006073
6074 std::vector<llvm::Constant*> Values(3);
Owen Anderson3c4972d2009-07-29 18:54:39 +00006075 Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
Daniel Dunbare588b992009-03-01 04:46:24 +00006076 Values[1] = GetClassName(ID->getIdentifier());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00006077 Values[2] = GetClassGlobal(ClassName);
Owen Andersona1cf15f2009-07-14 23:10:40 +00006078 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00006079 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbare588b992009-03-01 04:46:24 +00006080
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006081 if (Entry) {
6082 Entry->setInitializer(Init);
6083 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00006084 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006085 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006086 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006087 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006088 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006089 }
6090
John McCall1fb0caa2010-10-22 21:05:15 +00006091 if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006092 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00006093 Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6094 ObjCTypes.EHTypeTy));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006095
6096 if (ForDefinition) {
6097 Entry->setSection("__DATA,__objc_const");
6098 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6099 } else {
6100 Entry->setSection("__DATA,__datacoal_nt,coalesced");
6101 }
Daniel Dunbare588b992009-03-01 04:46:24 +00006102
6103 return Entry;
6104}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006105
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00006106/* *** */
6107
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00006108CodeGen::CGObjCRuntime *
6109CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
David Chisnall60be6072011-03-22 21:21:24 +00006110 if (CGM.getLangOptions().ObjCNonFragileABI)
6111 return new CGObjCNonFragileABIMac(CGM);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00006112 return new CGObjCMac(CGM);
6113}