blob: 7cb51e2611a72e5da387a56b47c5073fb17d7ce8 [file] [log] [blame]
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattnerfc8f0e12011-04-15 05:22:18 +000010// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000015
Daniel Dunbar198bcb42010-03-31 01:09:11 +000016#include "CGRecordLayout.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000017#include "CodeGenModule.h"
Daniel Dunbarb7ec2462008-08-16 03:19:19 +000018#include "CodeGenFunction.h"
John McCalld16c2cf2011-02-08 08:22:06 +000019#include "CGBlocks.h"
John McCall36f893c2011-01-28 11:13:47 +000020#include "CGCleanup.h"
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000021#include "clang/AST/ASTContext.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000022#include "clang/AST/Decl.h"
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000023#include "clang/AST/DeclObjC.h"
Anders Carlsson19cc4ab2009-07-18 19:43:29 +000024#include "clang/AST/RecordLayout.h"
Chris Lattner16f00492009-04-26 01:32:48 +000025#include "clang/AST/StmtObjC.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000026#include "clang/Basic/LangOptions.h"
Chandler Carruth06057ce2010-06-15 23:19:56 +000027#include "clang/Frontend/CodeGenOptions.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000028
John McCall87bb5822010-07-31 23:20:56 +000029#include "llvm/InlineAsm.h"
30#include "llvm/IntrinsicInst.h"
Owen Anderson69243822009-07-13 04:10:07 +000031#include "llvm/LLVMContext.h"
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000032#include "llvm/Module.h"
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +000033#include "llvm/ADT/DenseSet.h"
Daniel Dunbar33063492009-09-07 00:20:42 +000034#include "llvm/ADT/SetVector.h"
35#include "llvm/ADT/SmallString.h"
Fariborz Jahanian191dcd72009-12-12 21:26:21 +000036#include "llvm/ADT/SmallPtrSet.h"
John McCall8e3f8612010-07-13 22:12:14 +000037#include "llvm/Support/CallSite.h"
Daniel Dunbar33063492009-09-07 00:20:42 +000038#include "llvm/Support/raw_ostream.h"
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +000039#include "llvm/Target/TargetData.h"
Torok Edwinf42e4a62009-08-24 13:25:12 +000040#include <cstdio>
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000041
42using namespace clang;
Daniel Dunbar46f45b92008-09-09 01:06:48 +000043using namespace CodeGen;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000044
Daniel Dunbar97776872009-04-22 07:32:20 +000045
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000046namespace {
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000047
Daniel Dunbar6bff2512009-08-03 17:06:42 +000048typedef std::vector<llvm::Constant*> ConstantVector;
Daniel Dunbarae226fa2008-08-27 02:31:56 +000049
Daniel Dunbar6bff2512009-08-03 17:06:42 +000050// FIXME: We should find a nicer way to make the labels for metadata, string
51// concatenation is lame.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000052
Fariborz Jahanianee0af742009-01-21 22:04:16 +000053class ObjCCommonTypesHelper {
Owen Andersona1cf15f2009-07-14 23:10:40 +000054protected:
55 llvm::LLVMContext &VMContext;
Daniel Dunbar6bff2512009-08-03 17:06:42 +000056
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000057private:
58 llvm::Constant *getMessageSendFn() const {
59 // id objc_msgSend (id, SEL, ...)
60 std::vector<const llvm::Type*> Params;
61 Params.push_back(ObjectPtrTy);
62 Params.push_back(SelectorPtrTy);
63 return
Daniel Dunbar6bff2512009-08-03 17:06:42 +000064 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +000065 Params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +000066 "objc_msgSend");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000067 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000068
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000069 llvm::Constant *getMessageSendStretFn() const {
70 // id objc_msgSend_stret (id, SEL, ...)
71 std::vector<const llvm::Type*> Params;
72 Params.push_back(ObjectPtrTy);
73 Params.push_back(SelectorPtrTy);
74 return
Owen Anderson0032b272009-08-13 21:57:51 +000075 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +000076 Params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +000077 "objc_msgSend_stret");
78
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 *getMessageSendFpretFn() const {
82 // FIXME: This should be long double on x86_64?
83 // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
84 std::vector<const llvm::Type*> Params;
85 Params.push_back(ObjectPtrTy);
86 Params.push_back(SelectorPtrTy);
87 return
Owen Anderson0032b272009-08-13 21:57:51 +000088 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
89 llvm::Type::getDoubleTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +000090 Params,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +000091 true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +000092 "objc_msgSend_fpret");
93
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000094 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +000095
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +000096 llvm::Constant *getMessageSendSuperFn() const {
97 // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
98 const char *SuperName = "objc_msgSendSuper";
99 std::vector<const llvm::Type*> Params;
100 Params.push_back(SuperPtrTy);
101 Params.push_back(SelectorPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000102 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000103 Params, true),
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000104 SuperName);
105 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000106
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000107 llvm::Constant *getMessageSendSuperFn2() const {
108 // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
109 const char *SuperName = "objc_msgSendSuper2";
110 std::vector<const llvm::Type*> Params;
111 Params.push_back(SuperPtrTy);
112 Params.push_back(SelectorPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000113 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000114 Params, true),
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000115 SuperName);
116 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000117
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000118 llvm::Constant *getMessageSendSuperStretFn() const {
119 // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
120 // SEL op, ...)
121 std::vector<const llvm::Type*> Params;
122 Params.push_back(Int8PtrTy);
123 Params.push_back(SuperPtrTy);
124 Params.push_back(SelectorPtrTy);
Owen Andersona1cf15f2009-07-14 23:10:40 +0000125 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000126 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000127 Params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000128 "objc_msgSendSuper_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000129 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000130
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000131 llvm::Constant *getMessageSendSuperStretFn2() const {
132 // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
133 // SEL op, ...)
134 std::vector<const llvm::Type*> Params;
135 Params.push_back(Int8PtrTy);
136 Params.push_back(SuperPtrTy);
137 Params.push_back(SelectorPtrTy);
Owen Andersona1cf15f2009-07-14 23:10:40 +0000138 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000139 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000140 Params, true),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000141 "objc_msgSendSuper2_stret");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000142 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000143
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000144 llvm::Constant *getMessageSendSuperFpretFn() const {
145 // There is no objc_msgSendSuper_fpret? How can that work?
146 return getMessageSendSuperFn();
147 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000148
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000149 llvm::Constant *getMessageSendSuperFpretFn2() const {
150 // There is no objc_msgSendSuper_fpret? How can that work?
151 return getMessageSendSuperFn2();
152 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000153
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000154protected:
155 CodeGen::CodeGenModule &CGM;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000156
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000157public:
Fariborz Jahanian0a855d02009-03-23 19:10:40 +0000158 const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000159 const llvm::Type *Int8PtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000160
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000161 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
162 const llvm::Type *ObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000163
Fariborz Jahanian6d657c42008-11-18 20:18:11 +0000164 /// PtrObjectPtrTy - LLVM type for id *
165 const llvm::Type *PtrObjectPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000166
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000167 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Daniel Dunbar2bedbf82008-08-12 05:28:47 +0000168 const llvm::Type *SelectorPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000169 /// ProtocolPtrTy - LLVM type for external protocol handles
170 /// (typeof(Protocol))
171 const llvm::Type *ExternalProtocolPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000172
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000173 // SuperCTy - clang type for struct objc_super.
174 QualType SuperCTy;
175 // SuperPtrCTy - clang type for struct objc_super *.
176 QualType SuperPtrCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000177
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000178 /// SuperTy - LLVM type for struct objc_super.
179 const llvm::StructType *SuperTy;
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000180 /// SuperPtrTy - LLVM type for struct objc_super *.
181 const llvm::Type *SuperPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000182
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000183 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
184 /// in GCC parlance).
185 const llvm::StructType *PropertyTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000186
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000187 /// PropertyListTy - LLVM type for struct objc_property_list
188 /// (_prop_list_t in GCC parlance).
189 const llvm::StructType *PropertyListTy;
190 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
191 const llvm::Type *PropertyListPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000192
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000193 // MethodTy - LLVM type for struct objc_method.
194 const llvm::StructType *MethodTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000195
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000196 /// CacheTy - LLVM type for struct objc_cache.
197 const llvm::Type *CacheTy;
198 /// CachePtrTy - LLVM type for struct objc_cache *.
199 const llvm::Type *CachePtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000200
Chris Lattner72db6c32009-04-22 02:44:54 +0000201 llvm::Constant *getGetPropertyFn() {
202 CodeGen::CodeGenTypes &Types = CGM.getTypes();
203 ASTContext &Ctx = CGM.getContext();
204 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
John McCallead608a2010-02-26 00:48:12 +0000205 llvm::SmallVector<CanQualType,4> Params;
206 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
207 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattner72db6c32009-04-22 02:44:54 +0000208 Params.push_back(IdType);
209 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000210 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000211 Params.push_back(Ctx.BoolTy);
212 const llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000213 Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000214 FunctionType::ExtInfo()),
215 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000216 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
217 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000218
Chris Lattner72db6c32009-04-22 02:44:54 +0000219 llvm::Constant *getSetPropertyFn() {
220 CodeGen::CodeGenTypes &Types = CGM.getTypes();
221 ASTContext &Ctx = CGM.getContext();
222 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
John McCallead608a2010-02-26 00:48:12 +0000223 llvm::SmallVector<CanQualType,6> Params;
224 CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
225 CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
Chris Lattner72db6c32009-04-22 02:44:54 +0000226 Params.push_back(IdType);
227 Params.push_back(SelType);
David Chisnallab5824e2011-03-22 20:03:13 +0000228 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattner72db6c32009-04-22 02:44:54 +0000229 Params.push_back(IdType);
230 Params.push_back(Ctx.BoolTy);
231 Params.push_back(Ctx.BoolTy);
232 const llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000233 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000234 FunctionType::ExtInfo()),
235 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000236 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
237 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000238
Fariborz Jahanian6cc59062010-04-12 18:18:10 +0000239
240 llvm::Constant *getCopyStructFn() {
241 CodeGen::CodeGenTypes &Types = CGM.getTypes();
242 ASTContext &Ctx = CGM.getContext();
243 // void objc_copyStruct (void *, const void *, size_t, bool, bool)
244 llvm::SmallVector<CanQualType,5> Params;
245 Params.push_back(Ctx.VoidPtrTy);
246 Params.push_back(Ctx.VoidPtrTy);
247 Params.push_back(Ctx.LongTy);
248 Params.push_back(Ctx.BoolTy);
249 Params.push_back(Ctx.BoolTy);
250 const llvm::FunctionType *FTy =
251 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
252 FunctionType::ExtInfo()),
253 false);
254 return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
255 }
256
Chris Lattner72db6c32009-04-22 02:44:54 +0000257 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000258 CodeGen::CodeGenTypes &Types = CGM.getTypes();
259 ASTContext &Ctx = CGM.getContext();
Chris Lattner72db6c32009-04-22 02:44:54 +0000260 // void objc_enumerationMutation (id)
John McCallead608a2010-02-26 00:48:12 +0000261 llvm::SmallVector<CanQualType,1> Params;
262 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Daniel Dunbarc1ab9002009-07-11 20:32:50 +0000263 const llvm::FunctionType *FTy =
John McCall04a67a62010-02-05 21:31:56 +0000264 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindola264ba482010-03-30 20:24:48 +0000265 FunctionType::ExtInfo()),
266 false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000267 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
268 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000269
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000270 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattner72db6c32009-04-22 02:44:54 +0000271 llvm::Constant *getGcReadWeakFn() {
272 // id objc_read_weak (id *)
273 std::vector<const llvm::Type*> Args;
274 Args.push_back(ObjectPtrTy->getPointerTo());
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000275 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000276 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner72db6c32009-04-22 02:44:54 +0000277 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000278 }
279
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000280 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner96508e12009-04-17 22:12:36 +0000281 llvm::Constant *getGcAssignWeakFn() {
282 // id objc_assign_weak (id, id *)
283 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
284 Args.push_back(ObjectPtrTy->getPointerTo());
285 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000286 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner96508e12009-04-17 22:12:36 +0000287 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
288 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000289
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000290 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000291 llvm::Constant *getGcAssignGlobalFn() {
292 // id objc_assign_global(id, id *)
293 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
294 Args.push_back(ObjectPtrTy->getPointerTo());
Owen Andersona1cf15f2009-07-14 23:10:40 +0000295 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000296 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000297 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
298 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000299
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000300 /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
301 llvm::Constant *getGcAssignThreadLocalFn() {
302 // id objc_assign_threadlocal(id src, id * dest)
303 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
304 Args.push_back(ObjectPtrTy->getPointerTo());
305 llvm::FunctionType *FTy =
306 llvm::FunctionType::get(ObjectPtrTy, Args, false);
307 return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
308 }
309
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000310 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000311 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +0000312 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattnerbbccd612009-04-22 02:38:11 +0000313 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
314 Args.push_back(ObjectPtrTy->getPointerTo());
Fariborz Jahaniane0c76652011-05-05 22:00:38 +0000315 const llvm::Type *PtrDiffTy =
316 CGM.getTypes().ConvertType(
317 CGM.getContext().getPointerDiffType()->getCanonicalTypeUnqualified());
318
319 Args.push_back(PtrDiffTy);
Owen Andersona1cf15f2009-07-14 23:10:40 +0000320 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000321 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000322 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
323 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000324
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000325 /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
326 llvm::Constant *GcMemmoveCollectableFn() {
327 // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
328 std::vector<const llvm::Type*> Args(1, Int8PtrTy);
329 Args.push_back(Int8PtrTy);
330 Args.push_back(LongTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000331 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +0000332 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
333 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000334
Fariborz Jahaniandb286862009-01-22 00:37:21 +0000335 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000336 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian021a7a62010-07-20 20:30:03 +0000337 // id objc_assign_strongCast(id, id *)
Chris Lattnerbbccd612009-04-22 02:38:11 +0000338 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
339 Args.push_back(ObjectPtrTy->getPointerTo());
Owen Andersona1cf15f2009-07-14 23:10:40 +0000340 llvm::FunctionType *FTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +0000341 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000342 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
343 }
Anders Carlssonf57c5b22009-02-16 22:59:18 +0000344
345 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000346 llvm::Constant *getExceptionThrowFn() {
347 // void objc_exception_throw(id)
348 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
349 llvm::FunctionType *FTy =
Owen Anderson0032b272009-08-13 21:57:51 +0000350 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000351 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
352 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000353
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000354 /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
355 llvm::Constant *getExceptionRethrowFn() {
356 // void objc_exception_rethrow(void)
357 std::vector<const llvm::Type*> Args;
358 llvm::FunctionType *FTy =
John McCall7ec404c2010-10-16 08:21:07 +0000359 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Fariborz Jahanian69677ea2010-05-28 17:34:43 +0000360 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
361 }
362
Daniel Dunbar1c566672009-02-24 01:43:46 +0000363 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000364 llvm::Constant *getSyncEnterFn() {
365 // void objc_sync_enter (id)
366 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
367 llvm::FunctionType *FTy =
Owen Anderson0032b272009-08-13 21:57:51 +0000368 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerb02e53b2009-04-06 16:53:45 +0000369 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
370 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000371
Daniel Dunbar1c566672009-02-24 01:43:46 +0000372 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattnerbbccd612009-04-22 02:38:11 +0000373 llvm::Constant *getSyncExitFn() {
374 // void objc_sync_exit (id)
375 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
376 llvm::FunctionType *FTy =
Owen Anderson0032b272009-08-13 21:57:51 +0000377 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerbbccd612009-04-22 02:38:11 +0000378 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
379 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000380
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000381 llvm::Constant *getSendFn(bool IsSuper) const {
382 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
383 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000384
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000385 llvm::Constant *getSendFn2(bool IsSuper) const {
386 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
387 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000388
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000389 llvm::Constant *getSendStretFn(bool IsSuper) const {
390 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
391 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000392
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000393 llvm::Constant *getSendStretFn2(bool IsSuper) const {
394 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
395 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000396
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000397 llvm::Constant *getSendFpretFn(bool IsSuper) const {
398 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
399 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000400
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +0000401 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
402 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
403 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000404
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000405 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
406 ~ObjCCommonTypesHelper(){}
407};
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000408
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000409/// ObjCTypesHelper - Helper class that encapsulates lazy
410/// construction of varies types used during ObjC generation.
411class ObjCTypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000412public:
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000413 /// SymtabTy - LLVM type for struct objc_symtab.
414 const llvm::StructType *SymtabTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000415 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
416 const llvm::Type *SymtabPtrTy;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000417 /// ModuleTy - LLVM type for struct objc_module.
418 const llvm::StructType *ModuleTy;
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000419
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000420 /// ProtocolTy - LLVM type for struct objc_protocol.
421 const llvm::StructType *ProtocolTy;
422 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
423 const llvm::Type *ProtocolPtrTy;
424 /// ProtocolExtensionTy - LLVM type for struct
425 /// objc_protocol_extension.
426 const llvm::StructType *ProtocolExtensionTy;
427 /// ProtocolExtensionTy - LLVM type for struct
428 /// objc_protocol_extension *.
429 const llvm::Type *ProtocolExtensionPtrTy;
430 /// MethodDescriptionTy - LLVM type for struct
431 /// objc_method_description.
432 const llvm::StructType *MethodDescriptionTy;
433 /// MethodDescriptionListTy - LLVM type for struct
434 /// objc_method_description_list.
435 const llvm::StructType *MethodDescriptionListTy;
436 /// MethodDescriptionListPtrTy - LLVM type for struct
437 /// objc_method_description_list *.
438 const llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000439 /// ProtocolListTy - LLVM type for struct objc_property_list.
440 const llvm::Type *ProtocolListTy;
441 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
442 const llvm::Type *ProtocolListPtrTy;
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000443 /// CategoryTy - LLVM type for struct objc_category.
444 const llvm::StructType *CategoryTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000445 /// ClassTy - LLVM type for struct objc_class.
446 const llvm::StructType *ClassTy;
447 /// ClassPtrTy - LLVM type for struct objc_class *.
448 const llvm::Type *ClassPtrTy;
449 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
450 const llvm::StructType *ClassExtensionTy;
451 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
452 const llvm::Type *ClassExtensionPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000453 // IvarTy - LLVM type for struct objc_ivar.
454 const llvm::StructType *IvarTy;
455 /// IvarListTy - LLVM type for struct objc_ivar_list.
456 const llvm::Type *IvarListTy;
457 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
458 const llvm::Type *IvarListPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000459 /// MethodListTy - LLVM type for struct objc_method_list.
460 const llvm::Type *MethodListTy;
461 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
462 const llvm::Type *MethodListPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000463
Anders Carlsson124526b2008-09-09 10:10:21 +0000464 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
465 const llvm::Type *ExceptionDataTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000466
Anders Carlsson124526b2008-09-09 10:10:21 +0000467 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000468 llvm::Constant *getExceptionTryEnterFn() {
469 std::vector<const llvm::Type*> Params;
Owen Anderson96e0fc72009-07-29 22:16:19 +0000470 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
Owen Andersona1cf15f2009-07-14 23:10:40 +0000471 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000472 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000473 Params, false),
474 "objc_exception_try_enter");
Chris Lattner34b02a12009-04-22 02:26:14 +0000475 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000476
477 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000478 llvm::Constant *getExceptionTryExitFn() {
479 std::vector<const llvm::Type*> Params;
Owen Anderson96e0fc72009-07-29 22:16:19 +0000480 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
Owen Andersona1cf15f2009-07-14 23:10:40 +0000481 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000482 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000483 Params, false),
484 "objc_exception_try_exit");
Chris Lattner34b02a12009-04-22 02:26:14 +0000485 }
Anders Carlsson124526b2008-09-09 10:10:21 +0000486
487 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000488 llvm::Constant *getExceptionExtractFn() {
489 std::vector<const llvm::Type*> Params;
Owen Anderson96e0fc72009-07-29 22:16:19 +0000490 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
491 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattner34b02a12009-04-22 02:26:14 +0000492 Params, false),
493 "objc_exception_extract");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000494
Chris Lattner34b02a12009-04-22 02:26:14 +0000495 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000496
Anders Carlsson124526b2008-09-09 10:10:21 +0000497 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000498 llvm::Constant *getExceptionMatchFn() {
499 std::vector<const llvm::Type*> Params;
500 Params.push_back(ClassPtrTy);
501 Params.push_back(ObjectPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000502 return CGM.CreateRuntimeFunction(
Owen Anderson0032b272009-08-13 21:57:51 +0000503 llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000504 Params, false),
505 "objc_exception_match");
506
Chris Lattner34b02a12009-04-22 02:26:14 +0000507 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000508
Anders Carlsson124526b2008-09-09 10:10:21 +0000509 /// SetJmpFn - LLVM _setjmp function.
Chris Lattner34b02a12009-04-22 02:26:14 +0000510 llvm::Constant *getSetJmpFn() {
511 std::vector<const llvm::Type*> Params;
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +0000512 Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
Chris Lattner34b02a12009-04-22 02:26:14 +0000513 return
Owen Anderson0032b272009-08-13 21:57:51 +0000514 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Chris Lattner34b02a12009-04-22 02:26:14 +0000515 Params, false),
516 "_setjmp");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000517
Chris Lattner34b02a12009-04-22 02:26:14 +0000518 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000519
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000520public:
521 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000522 ~ObjCTypesHelper() {}
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000523};
524
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000525/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000526/// modern abi
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000527class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000528public:
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000529
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000530 // MethodListnfABITy - LLVM for struct _method_list_t
531 const llvm::StructType *MethodListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000532
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000533 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
534 const llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000535
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000536 // ProtocolnfABITy = LLVM for struct _protocol_t
537 const llvm::StructType *ProtocolnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000538
Daniel Dunbar948e2582009-02-15 07:36:20 +0000539 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
540 const llvm::Type *ProtocolnfABIPtrTy;
541
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000542 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
543 const llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000544
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000545 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
546 const llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000547
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000548 // ClassnfABITy - LLVM for struct _class_t
549 const llvm::StructType *ClassnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000550
Fariborz Jahanianaa23b572009-01-23 23:53:38 +0000551 // ClassnfABIPtrTy - LLVM for struct _class_t*
552 const llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000553
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000554 // IvarnfABITy - LLVM for struct _ivar_t
555 const llvm::StructType *IvarnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000556
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000557 // IvarListnfABITy - LLVM for struct _ivar_list_t
558 const llvm::StructType *IvarListnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000559
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000560 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
561 const llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000562
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000563 // ClassRonfABITy - LLVM for struct _class_ro_t
564 const llvm::StructType *ClassRonfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000565
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000566 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
567 const llvm::Type *ImpnfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000568
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +0000569 // CategorynfABITy - LLVM for struct _category_t
570 const llvm::StructType *CategorynfABITy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000571
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000572 // New types for nonfragile abi messaging.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000573
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000574 // MessageRefTy - LLVM for:
575 // struct _message_ref_t {
576 // IMP messenger;
577 // SEL name;
578 // };
579 const llvm::StructType *MessageRefTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000580 // MessageRefCTy - clang type for struct _message_ref_t
581 QualType MessageRefCTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000582
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000583 // MessageRefPtrTy - LLVM for struct _message_ref_t*
584 const llvm::Type *MessageRefPtrTy;
Fariborz Jahanian83a8a752009-02-04 20:42:28 +0000585 // MessageRefCPtrTy - clang type for struct _message_ref_t*
586 QualType MessageRefCPtrTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000587
Fariborz Jahanianef163782009-02-05 01:13:09 +0000588 // MessengerTy - Type of the messenger (shown as IMP above)
589 const llvm::FunctionType *MessengerTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000590
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000591 // SuperMessageRefTy - LLVM for:
592 // struct _super_message_ref_t {
593 // SUPER_IMP messenger;
594 // SEL name;
595 // };
596 const llvm::StructType *SuperMessageRefTy;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000597
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +0000598 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
599 const llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000600
Chris Lattner1c02f862009-04-22 02:53:24 +0000601 llvm::Constant *getMessageSendFixupFn() {
602 // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
603 std::vector<const llvm::Type*> Params;
604 Params.push_back(ObjectPtrTy);
605 Params.push_back(MessageRefPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000606 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000607 Params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000608 "objc_msgSend_fixup");
609 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000610
Chris Lattner1c02f862009-04-22 02:53:24 +0000611 llvm::Constant *getMessageSendFpretFixupFn() {
612 // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
613 std::vector<const llvm::Type*> Params;
614 Params.push_back(ObjectPtrTy);
615 Params.push_back(MessageRefPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000616 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000617 Params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000618 "objc_msgSend_fpret_fixup");
619 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000620
Chris Lattner1c02f862009-04-22 02:53:24 +0000621 llvm::Constant *getMessageSendStretFixupFn() {
622 // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
623 std::vector<const llvm::Type*> Params;
624 Params.push_back(ObjectPtrTy);
625 Params.push_back(MessageRefPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000626 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000627 Params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000628 "objc_msgSend_stret_fixup");
629 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000630
Chris Lattner1c02f862009-04-22 02:53:24 +0000631 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000632 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000633 // struct _super_message_ref_t*, ...)
634 std::vector<const llvm::Type*> Params;
635 Params.push_back(SuperPtrTy);
636 Params.push_back(SuperMessageRefPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000637 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000638 Params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000639 "objc_msgSendSuper2_fixup");
640 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000641
Chris Lattner1c02f862009-04-22 02:53:24 +0000642 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000643 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner1c02f862009-04-22 02:53:24 +0000644 // struct _super_message_ref_t*, ...)
645 std::vector<const llvm::Type*> Params;
646 Params.push_back(SuperPtrTy);
647 Params.push_back(SuperMessageRefPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000648 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanianbf1f8262011-02-28 21:19:34 +0000649 Params, true),
Chris Lattner1c02f862009-04-22 02:53:24 +0000650 "objc_msgSendSuper2_stret_fixup");
651 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000652
Chris Lattner8a569112009-04-22 02:15:23 +0000653 llvm::Constant *getObjCEndCatchFn() {
Owen Anderson0032b272009-08-13 21:57:51 +0000654 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Chris Lattnerb59761b2009-07-01 04:13:52 +0000655 false),
Chris Lattner8a569112009-04-22 02:15:23 +0000656 "objc_end_catch");
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000657
Chris Lattner8a569112009-04-22 02:15:23 +0000658 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000659
Chris Lattner8a569112009-04-22 02:15:23 +0000660 llvm::Constant *getObjCBeginCatchFn() {
661 std::vector<const llvm::Type*> Params;
662 Params.push_back(Int8PtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +0000663 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
Chris Lattner8a569112009-04-22 02:15:23 +0000664 Params, false),
665 "objc_begin_catch");
666 }
Daniel Dunbare588b992009-03-01 04:46:24 +0000667
668 const llvm::StructType *EHTypeTy;
669 const llvm::Type *EHTypePtrTy;
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +0000670
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000671 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
672 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000673};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000674
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000675class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000676public:
677 // FIXME - accessibility
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000678 class GC_IVAR {
Fariborz Jahanian820e0202009-03-11 00:07:04 +0000679 public:
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000680 unsigned ivar_bytepos;
681 unsigned ivar_size;
682 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000683 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar0941b492009-04-23 01:29:05 +0000684
685 // Allow sorting based on byte pos.
686 bool operator<(const GC_IVAR &b) const {
687 return ivar_bytepos < b.ivar_bytepos;
688 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000689 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000690
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000691 class SKIP_SCAN {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000692 public:
693 unsigned skip;
694 unsigned scan;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000695 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar8b2926c2009-05-03 13:44:42 +0000696 : skip(_skip), scan(_scan) {}
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000697 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000698
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000699protected:
700 CodeGen::CodeGenModule &CGM;
Owen Anderson69243822009-07-13 04:10:07 +0000701 llvm::LLVMContext &VMContext;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000702 // FIXME! May not be needing this after all.
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000703 unsigned ObjCABI;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000704
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +0000705 // gc ivar layout bitmap calculation helper caches.
706 llvm::SmallVector<GC_IVAR, 16> SkipIvars;
707 llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000708
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000709 /// LazySymbols - Symbols to generate a lazy reference for. See
710 /// DefinedSymbols and FinishModule().
Daniel Dunbar33063492009-09-07 00:20:42 +0000711 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000712
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000713 /// DefinedSymbols - External symbols which are defined by this
714 /// module. The symbols in this list and LazySymbols are used to add
715 /// special linker symbols which ensure that Objective-C modules are
716 /// linked properly.
Daniel Dunbar33063492009-09-07 00:20:42 +0000717 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000718
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000719 /// ClassNames - uniqued class names.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000720 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000721
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000722 /// MethodVarNames - uniqued method variable names.
723 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000724
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +0000725 /// DefinedCategoryNames - list of category names in form Class_Category.
726 llvm::SetVector<std::string> DefinedCategoryNames;
727
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000728 /// MethodVarTypes - uniqued method type signatures. We have to use
729 /// a StringMap here because have no other unique reference.
730 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000731
Daniel Dunbarc45ef602008-08-26 21:51:14 +0000732 /// MethodDefinitions - map of methods which have been defined in
733 /// this translation unit.
734 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000735
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000736 /// PropertyNames - uniqued method variable names.
737 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000738
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000739 /// ClassReferences - uniqued class references.
740 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000741
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000742 /// SelectorReferences - uniqued selector references.
743 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000744
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000745 /// Protocols - Protocols for which an objc_protocol structure has
746 /// been emitted. Forward declarations are handled by creating an
747 /// empty structure whose initializer is filled in when/if defined.
748 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000749
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000750 /// DefinedProtocols - Protocols which have actually been
751 /// defined. We should not need this, see FIXME in GenerateProtocol.
752 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000753
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000754 /// DefinedClasses - List of defined classes.
755 std::vector<llvm::GlobalValue*> DefinedClasses;
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000756
757 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
758 std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000759
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000760 /// DefinedCategories - List of defined categories.
761 std::vector<llvm::GlobalValue*> DefinedCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000762
Daniel Dunbar74d4b122009-05-15 22:33:15 +0000763 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
764 std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000765
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000766 /// GetNameForMethod - Return a name for the given method.
767 /// \param[out] NameOut - The return value.
768 void GetNameForMethod(const ObjCMethodDecl *OMD,
769 const ObjCContainerDecl *CD,
Daniel Dunbarc575ce72009-10-19 01:21:19 +0000770 llvm::SmallVectorImpl<char> &NameOut);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000771
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000772 /// GetMethodVarName - Return a unique constant for the given
773 /// selector's name. The return value has type char *.
774 llvm::Constant *GetMethodVarName(Selector Sel);
775 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000776
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000777 /// GetMethodVarType - Return a unique constant for the given
778 /// selector's name. The return value has type char *.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000779
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000780 // FIXME: This is a horrible name.
781 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +0000782 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000783
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000784 /// GetPropertyName - Return a unique constant for the given
785 /// name. The return value has type char *.
786 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000787
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000788 // FIXME: This can be dropped once string functions are unified.
789 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
790 const Decl *Container);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000791
Fariborz Jahanian058a1b72009-01-24 20:21:50 +0000792 /// GetClassName - Return a unique constant for the given selector's
793 /// name. The return value has type char *.
794 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000795
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +0000796 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
797
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000798 /// BuildIvarLayout - Builds ivar layout bitmap for the class
799 /// implementation for the __strong or __weak case.
800 ///
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000801 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
802 bool ForStrongLayout);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +0000803
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +0000804 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000805
Daniel Dunbard58edcb2009-05-03 14:10:34 +0000806 void BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000807 unsigned int BytePos, bool ForStrongLayout,
808 bool &HasUnion);
Daniel Dunbar5a5a8032009-05-03 21:05:10 +0000809 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000810 const llvm::StructLayout *Layout,
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +0000811 const RecordDecl *RD,
Chris Lattnerf1690852009-03-31 08:48:01 +0000812 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +0000813 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahanian81adc052009-04-24 16:17:09 +0000814 bool &HasUnion);
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +0000815
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +0000816 /// GetIvarLayoutName - Returns a unique constant for the given
817 /// ivar layout bitmap.
818 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
819 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000820
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000821 /// EmitPropertyList - Emit the given property list. The return
822 /// value has type PropertyListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000823 llvm::Constant *EmitPropertyList(llvm::Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000824 const Decl *Container,
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +0000825 const ObjCContainerDecl *OCD,
826 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000827
Fariborz Jahanian191dcd72009-12-12 21:26:21 +0000828 /// PushProtocolProperties - Push protocol's property on the input stack.
829 void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
830 std::vector<llvm::Constant*> &Properties,
831 const Decl *Container,
832 const ObjCProtocolDecl *PROTO,
833 const ObjCCommonTypesHelper &ObjCTypes);
834
Fariborz Jahanianda320092009-01-29 19:24:30 +0000835 /// GetProtocolRef - Return a reference to the internal protocol
836 /// description, creating an empty one if it has not been
837 /// defined. The return value has type ProtocolPtrTy.
838 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahanianb21f07e2009-03-08 20:18:37 +0000839
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000840 /// CreateMetadataVar - Create a global variable with internal
841 /// linkage for use by the Objective-C runtime.
842 ///
843 /// This is a convenience wrapper which not only creates the
844 /// variable, but also sets the section and alignment and adds the
Chris Lattnerad64e022009-07-17 23:57:13 +0000845 /// global to the "llvm.used" list.
Daniel Dunbar35bd7632009-03-09 20:50:13 +0000846 ///
847 /// \param Name - The variable name.
848 /// \param Init - The variable initializer; this is also used to
849 /// define the type of the variable.
850 /// \param Section - The section the variable should go into, or 0.
851 /// \param Align - The alignment for the variable, or 0.
852 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbarc1583062009-04-14 17:42:51 +0000853 /// "llvm.used".
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000854 llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000855 llvm::Constant *Init,
856 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +0000857 unsigned Align,
858 bool AddToUsed);
Daniel Dunbarfd65d372009-03-09 20:09:19 +0000859
John McCall944c8432011-05-14 03:10:52 +0000860 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
861 ReturnValueSlot Return,
862 QualType ResultType,
863 llvm::Value *Sel,
864 llvm::Value *Arg0,
865 QualType Arg0Ty,
866 bool IsSuper,
867 const CallArgList &CallArgs,
868 const ObjCMethodDecl *OMD,
869 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +0000870
Daniel Dunbarfce176b2010-04-25 20:39:01 +0000871 /// EmitImageInfo - Emit the image info marker used to encode some module
872 /// level information.
873 void EmitImageInfo();
874
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000875public:
Owen Anderson69243822009-07-13 04:10:07 +0000876 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
Mike Stump1eb44332009-09-09 15:08:12 +0000877 CGM(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000878
David Chisnall0d13f6f2010-01-23 02:40:42 +0000879 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000880
Fariborz Jahanian493dab72009-01-26 21:38:32 +0000881 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
882 const ObjCContainerDecl *CD=0);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000883
Fariborz Jahanianda320092009-01-29 19:24:30 +0000884 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000885
Fariborz Jahanianda320092009-01-29 19:24:30 +0000886 /// GetOrEmitProtocol - Get the protocol object for the given
887 /// declaration, emitting it if necessary. The return value has type
888 /// ProtocolPtrTy.
889 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000890
Fariborz Jahanianda320092009-01-29 19:24:30 +0000891 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
892 /// object for the given declaration, emitting it if needed. These
893 /// forward references will be filled in with empty bodies if no
894 /// definition is seen. The return value has type ProtocolPtrTy.
895 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
John McCall6b5a61b2011-02-07 10:33:21 +0000896 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
897 const CGBlockInfo &blockInfo);
Fariborz Jahanian89ecd412010-08-04 16:57:49 +0000898
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000899};
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000900
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000901class CGObjCMac : public CGObjCCommonMac {
902private:
903 ObjCTypesHelper ObjCTypes;
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000904
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000905 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000906 /// information.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000907 void EmitModuleInfo();
908
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000909 /// EmitModuleSymols - Emit module symbols, the list of defined
910 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000911 llvm::Constant *EmitModuleSymbols();
912
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000913 /// FinishModule - Write out global data structures at the end of
914 /// processing a translation unit.
915 void FinishModule();
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000916
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000917 /// EmitClassExtension - Generate the class extension structure used
918 /// to store the weak ivar layout and properties. The return value
919 /// has type ClassExtensionPtrTy.
920 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
921
922 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
923 /// for the given class.
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000924 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000925 const ObjCInterfaceDecl *ID);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +0000926
927 /// EmitSuperClassRef - Emits reference to class's main metadata class.
928 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000929
930 /// EmitIvarList - Emit the ivar list for the given
931 /// implementation. If ForClass is true the list of class ivars
932 /// (i.e. metaclass ivars) is emitted, otherwise the list of
933 /// interface ivars will be emitted. The return value has type
934 /// IvarListPtrTy.
935 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +0000936 bool ForClass);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000937
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000938 /// EmitMetaClass - Emit a forward reference to the class structure
939 /// for the metaclass of the given interface. The return value has
940 /// type ClassPtrTy.
941 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
942
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000943 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000944 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000945 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
946 llvm::Constant *Protocols,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000947 const ConstantVector &Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000948
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000949 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000950
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000951 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000952
953 /// EmitMethodList - Emit the method list for the given
Daniel Dunbaraf05bb92008-08-26 08:29:31 +0000954 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000955 llvm::Constant *EmitMethodList(llvm::Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000956 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000957 const ConstantVector &Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000958
959 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar6bff2512009-08-03 17:06:42 +0000960 /// method declarations.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000961 /// - TypeName: The name for the type containing the methods.
962 /// - IsProtocol: True iff these methods are for a protocol.
963 /// - ClassMethds: True iff these are class methods.
964 /// - Required: When true, only "required" methods are
965 /// listed. Similarly, when false only "optional" methods are
966 /// listed. For classes this should always be true.
967 /// - begin, end: The method list to output.
968 ///
969 /// The return value has type MethodDescriptionListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000970 llvm::Constant *EmitMethodDescList(llvm::Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000971 const char *Section,
972 const ConstantVector &Methods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000973
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000974 /// GetOrEmitProtocol - Get the protocol object for the given
975 /// declaration, emitting it if necessary. The return value has type
976 /// ProtocolPtrTy.
Fariborz Jahanianda320092009-01-29 19:24:30 +0000977 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000978
979 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
980 /// object for the given declaration, emitting it if needed. These
981 /// forward references will be filled in with empty bodies if no
982 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanianda320092009-01-29 19:24:30 +0000983 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000984
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000985 /// EmitProtocolExtension - Generate the protocol extension
986 /// structure used to store optional instance and class methods, and
987 /// protocol properties. The return value has type
988 /// ProtocolExtensionPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000989 llvm::Constant *
990 EmitProtocolExtension(const ObjCProtocolDecl *PD,
991 const ConstantVector &OptInstanceMethods,
992 const ConstantVector &OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000993
994 /// EmitProtocolList - Generate the list of referenced
995 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +0000996 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Daniel Dunbardbc933702008-08-21 21:57:41 +0000997 ObjCProtocolDecl::protocol_iterator begin,
998 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000999
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001000 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1001 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001002 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1003 bool lval=false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001004
1005public:
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001006 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001007
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001008 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001009
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001010 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001011 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001012 QualType ResultType,
1013 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001014 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001015 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001016 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001017 const ObjCMethodDecl *Method);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001018
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001019 virtual CodeGen::RValue
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001020 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001021 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001022 QualType ResultType,
1023 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001024 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001025 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001026 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001027 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001028 const CallArgList &CallArgs,
1029 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001030
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001031 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001032 const ObjCInterfaceDecl *ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001033
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001034 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1035 bool lval = false);
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001036
1037 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1038 /// untyped one.
1039 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1040 const ObjCMethodDecl *Method);
1041
John McCall5a180392010-07-24 00:37:23 +00001042 virtual llvm::Constant *GetEHType(QualType T);
1043
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001044 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001045
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001046 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001047
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001048 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001049 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001050
Chris Lattner74391b42009-03-22 21:03:39 +00001051 virtual llvm::Constant *GetPropertyGetFunction();
1052 virtual llvm::Constant *GetPropertySetFunction();
David Chisnall8fac25d2010-12-26 22:13:16 +00001053 virtual llvm::Constant *GetGetStructFunction();
1054 virtual llvm::Constant *GetSetStructFunction();
Chris Lattner74391b42009-03-22 21:03:39 +00001055 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001056
John McCallf1549f62010-07-06 01:34:17 +00001057 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1058 const ObjCAtTryStmt &S);
1059 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1060 const ObjCAtSynchronizedStmt &S);
1061 void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00001062 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1063 const ObjCAtThrowStmt &S);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001064 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001065 llvm::Value *AddrWeakObj);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001066 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001067 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001068 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001069 llvm::Value *src, llvm::Value *dest,
1070 bool threadlocal = false);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00001071 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001072 llvm::Value *src, llvm::Value *dest,
1073 llvm::Value *ivarOffset);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001074 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1075 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001076 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1077 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001078 llvm::Value *size);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001079
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001080 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1081 QualType ObjectTy,
1082 llvm::Value *BaseValue,
1083 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001084 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001085 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001086 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001087 const ObjCIvarDecl *Ivar);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001088};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001089
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001090class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001091private:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001092 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001093 llvm::GlobalVariable* ObjCEmptyCacheVar;
1094 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001095
Daniel Dunbar11394522009-04-18 08:51:00 +00001096 /// SuperClassReferences - uniqued super class references.
1097 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001098
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001099 /// MetaClassReferences - uniqued meta class references.
1100 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbare588b992009-03-01 04:46:24 +00001101
1102 /// EHTypeReferences - uniqued class ehtype references.
1103 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001104
John McCall944c8432011-05-14 03:10:52 +00001105 /// VTableDispatchMethods - List of methods for which we generate
1106 /// vtable-based message dispatch.
1107 llvm::DenseSet<Selector> VTableDispatchMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001108
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00001109 /// DefinedMetaClasses - List of defined meta-classes.
1110 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1111
John McCall944c8432011-05-14 03:10:52 +00001112 /// isVTableDispatchedSelector - Returns true if SEL is a
1113 /// vtable-based selector.
1114 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001115
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001116 /// FinishNonFragileABIModule - Write out global data structures at the end of
1117 /// processing a translation unit.
1118 void FinishNonFragileABIModule();
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001119
Daniel Dunbar463b8762009-05-15 21:48:48 +00001120 /// AddModuleClassList - Add the given list of class pointers to the
1121 /// module with the provided symbol and section names.
1122 void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
1123 const char *SymbolName,
1124 const char *SectionName);
1125
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001126 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1127 unsigned InstanceStart,
1128 unsigned InstanceSize,
1129 const ObjCImplementationDecl *ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001130 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001131 llvm::Constant *IsAGV,
Fariborz Jahanian84394a52009-01-24 21:21:53 +00001132 llvm::Constant *SuperClassGV,
Fariborz Jahaniancf555162009-01-31 00:59:10 +00001133 llvm::Constant *ClassRoGV,
1134 bool HiddenVisibility);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001135
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001136 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001137
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00001138 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001139
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001140 /// EmitMethodList - Emit the method list for the given
1141 /// implementation. The return value has type MethodListnfABITy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001142 llvm::Constant *EmitMethodList(llvm::Twine Name,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00001143 const char *Section,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00001144 const ConstantVector &Methods);
1145 /// EmitIvarList - Emit the ivar list for the given
1146 /// implementation. If ForClass is true the list of class ivars
1147 /// (i.e. metaclass ivars) is emitted, otherwise the list of
1148 /// interface ivars will be emitted. The return value has type
1149 /// IvarListnfABIPtrTy.
1150 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001151
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001152 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00001153 const ObjCIvarDecl *Ivar,
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00001154 unsigned long int offset);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001155
Fariborz Jahanianda320092009-01-29 19:24:30 +00001156 /// GetOrEmitProtocol - Get the protocol object for the given
1157 /// declaration, emitting it if necessary. The return value has type
1158 /// ProtocolPtrTy.
1159 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001160
Fariborz Jahanianda320092009-01-29 19:24:30 +00001161 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
1162 /// object for the given declaration, emitting it if needed. These
1163 /// forward references will be filled in with empty bodies if no
1164 /// definition is seen. The return value has type ProtocolPtrTy.
1165 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001166
Fariborz Jahanianda320092009-01-29 19:24:30 +00001167 /// EmitProtocolList - Generate the list of referenced
1168 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001169 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Fariborz Jahanianda320092009-01-29 19:24:30 +00001170 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian46551122009-02-04 00:22:57 +00001171 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001172
John McCall944c8432011-05-14 03:10:52 +00001173 CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF,
1174 ReturnValueSlot Return,
1175 QualType ResultType,
1176 Selector Sel,
1177 llvm::Value *Receiver,
1178 QualType Arg0Ty,
1179 bool IsSuper,
1180 const CallArgList &CallArgs,
1181 const ObjCMethodDecl *Method);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00001182
1183 /// GetClassGlobal - Return the global variable for the Objective-C
1184 /// class of the given name.
Fariborz Jahanian0f902942009-04-14 18:41:56 +00001185 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001186
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001187 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar11394522009-04-18 08:51:00 +00001188 /// for the given class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001189 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00001190 const ObjCInterfaceDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001191
Daniel Dunbar11394522009-04-18 08:51:00 +00001192 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1193 /// for the given super class reference.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001194 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1195 const ObjCInterfaceDecl *ID);
1196
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001197 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1198 /// meta-data
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001199 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00001200 const ObjCInterfaceDecl *ID);
1201
Fariborz Jahanianed157d32009-02-10 20:21:06 +00001202 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1203 /// the given ivar.
1204 ///
Daniel Dunbar5e88bea2009-04-19 00:31:15 +00001205 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001206 const ObjCInterfaceDecl *ID,
1207 const ObjCIvarDecl *Ivar);
1208
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00001209 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1210 /// for the given selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001211 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1212 bool lval=false);
Daniel Dunbare588b992009-03-01 04:46:24 +00001213
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001214 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbare588b992009-03-01 04:46:24 +00001215 /// interface. The return value has type EHTypePtrTy.
John McCall5a180392010-07-24 00:37:23 +00001216 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001217 bool ForDefinition);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001218
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001219 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001220 return "OBJC_METACLASS_$_";
1221 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001222
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00001223 const char *getClassSymbolPrefix() const {
1224 return "OBJC_CLASS_$_";
1225 }
1226
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00001227 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001228 uint32_t &InstanceStart,
1229 uint32_t &InstanceSize);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001230
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001231 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001232 Selector GetNullarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001233 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1234 return CGM.getContext().Selectors.getSelector(0, &II);
1235 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001236
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001237 Selector GetUnarySelector(const char* name) const {
Fariborz Jahanian4523eb02009-05-12 20:06:41 +00001238 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1239 return CGM.getContext().Selectors.getSelector(1, &II);
1240 }
Daniel Dunbarb02532a2009-04-19 23:41:48 +00001241
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001242 /// ImplementationIsNonLazy - Check whether the given category or
1243 /// class implementation is "non-lazy".
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00001244 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00001245
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001246public:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00001247 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001248 // FIXME. All stubs for now!
1249 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001250
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001251 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001252 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001253 QualType ResultType,
1254 Selector Sel,
1255 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001256 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001257 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001258 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001259
1260 virtual CodeGen::RValue
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001261 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001262 ReturnValueSlot Return,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001263 QualType ResultType,
1264 Selector Sel,
1265 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001266 bool isCategoryImpl,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001267 llvm::Value *Receiver,
1268 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001269 const CallArgList &CallArgs,
1270 const ObjCMethodDecl *Method);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001271
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001272 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00001273 const ObjCInterfaceDecl *ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001274
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001275 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1276 bool lvalue = false)
1277 { return EmitSelector(Builder, Sel, lvalue); }
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001278
1279 /// The NeXT/Apple runtimes do not support typed selectors; just emit an
1280 /// untyped one.
1281 virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
1282 const ObjCMethodDecl *Method)
1283 { return EmitSelector(Builder, Method->getSelector()); }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001284
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00001285 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001286
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001287 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001288 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00001289 const ObjCProtocolDecl *PD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001290
John McCall5a180392010-07-24 00:37:23 +00001291 virtual llvm::Constant *GetEHType(QualType T);
1292
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001293 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001294 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001295 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001296 virtual llvm::Constant *GetPropertySetFunction() {
1297 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001298 }
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001299
David Chisnall8fac25d2010-12-26 22:13:16 +00001300 virtual llvm::Constant *GetSetStructFunction() {
1301 return ObjCTypes.getCopyStructFn();
1302 }
1303 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00001304 return ObjCTypes.getCopyStructFn();
1305 }
1306
Chris Lattner74391b42009-03-22 21:03:39 +00001307 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00001308 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbar28ed0842009-02-16 18:48:45 +00001309 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001310
John McCallf1549f62010-07-06 01:34:17 +00001311 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1312 const ObjCAtTryStmt &S);
1313 virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1314 const ObjCAtSynchronizedStmt &S);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001315 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlssonf57c5b22009-02-16 22:59:18 +00001316 const ObjCAtThrowStmt &S);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001317 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001318 llvm::Value *AddrWeakObj);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001319 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001320 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001321 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00001322 llvm::Value *src, llvm::Value *dest,
1323 bool threadlocal = false);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001324 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00001325 llvm::Value *src, llvm::Value *dest,
1326 llvm::Value *ivarOffset);
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001327 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00001328 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00001329 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1330 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00001331 llvm::Value *size);
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001332 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1333 QualType ObjectTy,
1334 llvm::Value *BaseValue,
1335 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00001336 unsigned CVRQualifiers);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001337 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00001338 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00001339 const ObjCIvarDecl *Ivar);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001340};
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001341
John McCallcba681a2011-05-14 21:12:11 +00001342/// A helper class for performing the null-initialization of a return
1343/// value.
1344struct NullReturnState {
1345 llvm::BasicBlock *NullBB;
1346
1347 NullReturnState() : NullBB(0) {}
1348
1349 void init(CodeGenFunction &CGF, llvm::Value *receiver) {
1350 // Make blocks for the null-init and call edges.
1351 NullBB = CGF.createBasicBlock("msgSend.nullinit");
1352 llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");
1353
1354 // Check for a null receiver and, if there is one, jump to the
1355 // null-init test.
1356 llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
1357 CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
1358
1359 // Otherwise, start performing the call.
1360 CGF.EmitBlock(callBB);
1361 }
1362
1363 RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType) {
1364 if (!NullBB) return result;
1365
1366 // Finish the call path.
1367 llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
1368 if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
1369
1370 // Emit the null-init block and perform the null-initialization there.
1371 CGF.EmitBlock(NullBB);
1372 assert(result.isAggregate() && "null init of non-aggregate result?");
1373 CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
1374
1375 // Jump to the continuation block.
1376 CGF.EmitBlock(contBB);
1377
1378 return result;
1379 }
1380};
1381
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001382} // end anonymous namespace
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001383
1384/* *** Helper Functions *** */
1385
1386/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Andersona1cf15f2009-07-14 23:10:40 +00001387static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001388 llvm::Constant *C,
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001389 unsigned idx0,
1390 unsigned idx1) {
1391 llvm::Value *Idxs[] = {
Owen Anderson0032b272009-08-13 21:57:51 +00001392 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1393 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001394 };
Owen Anderson3c4972d2009-07-29 18:54:39 +00001395 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001396}
1397
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001398/// hasObjCExceptionAttribute - Return true if this class or any super
1399/// class has the __objc_exception__ attribute.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001400static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor68584ed2009-06-18 16:11:24 +00001401 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidis40b598e2009-06-30 02:34:44 +00001402 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001403 return true;
1404 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor68584ed2009-06-18 16:11:24 +00001405 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00001406 return false;
1407}
1408
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001409/* *** CGObjCMac Public Interface *** */
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001410
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001411CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00001412 ObjCTypes(cgm) {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00001413 ObjCABI = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001414 EmitImageInfo();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001415}
1416
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +00001417/// GetClass - Return a reference to the class for the given interface
1418/// decl.
Daniel Dunbar45d196b2008-11-01 01:53:16 +00001419llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001420 const ObjCInterfaceDecl *ID) {
1421 return EmitClassRef(Builder, ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001422}
1423
1424/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian03b29602010-06-17 19:56:20 +00001425llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1426 bool lval) {
1427 return EmitSelector(Builder, Sel, lval);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001428}
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001429llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001430 *Method) {
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001431 return EmitSelector(Builder, Method->getSelector());
1432}
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001433
John McCall5a180392010-07-24 00:37:23 +00001434llvm::Constant *CGObjCMac::GetEHType(QualType T) {
1435 llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
1436 return 0;
1437}
1438
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001439/// Generate a constant CFString object.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001440/*
1441 struct __builtin_CFString {
1442 const int *isa; // point to __CFConstantStringClassReference
1443 int flags;
1444 const char *str;
1445 long length;
1446 };
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001447*/
1448
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001449/// or Generate a constant NSString object.
1450/*
1451 struct __builtin_NSString {
1452 const int *isa; // point to __NSConstantStringClassReference
1453 const char *str;
1454 unsigned int length;
1455 };
1456*/
1457
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00001458llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall0d13f6f2010-01-23 02:40:42 +00001459 const StringLiteral *SL) {
Fariborz Jahanian33e982b2010-04-22 20:26:39 +00001460 return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
1461 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian4c733072010-10-19 17:19:29 +00001462 CGM.GetAddrOfConstantString(SL));
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001463}
1464
1465/// Generates a message send where the super is the receiver. This is
1466/// a message send to self with special delivery semantics indicating
1467/// which class's method should be called.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001468CodeGen::RValue
1469CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001470 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001471 QualType ResultType,
1472 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001473 const ObjCInterfaceDecl *Class,
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001474 bool isCategoryImpl,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001475 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001476 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001477 const CodeGen::CallArgList &CallArgs,
1478 const ObjCMethodDecl *Method) {
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001479 // Create and init a super structure; this is a (receiver, class)
1480 // pair we will pass to objc_msgSendSuper.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001481 llvm::Value *ObjCSuper =
John McCall604da292011-03-04 08:00:29 +00001482 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001483 llvm::Value *ReceiverAsObject =
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001484 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001485 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001486 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbare8b470d2008-08-23 04:28:29 +00001487
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001488 // If this is a class message the metaclass is passed as the target.
1489 llvm::Value *Target;
1490 if (IsClassMessage) {
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001491 if (isCategoryImpl) {
1492 // Message sent to 'super' in a class method defined in a category
1493 // implementation requires an odd treatment.
1494 // If we are in a class method, we must retrieve the
1495 // _metaclass_ for the current class, pointed at by
1496 // the class's "isa" pointer. The following assumes that
1497 // isa" is the first ivar in a class (which it must be).
1498 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1499 Target = CGF.Builder.CreateStructGEP(Target, 0);
1500 Target = CGF.Builder.CreateLoad(Target);
Mike Stumpb3589f42009-07-30 22:28:39 +00001501 } else {
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00001502 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1503 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1504 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1505 Target = Super;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001506 }
Fariborz Jahanian182f2682009-11-14 02:18:31 +00001507 }
1508 else if (isCategoryImpl)
1509 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1510 else {
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00001511 llvm::Value *ClassPtr = EmitSuperClassRef(Class);
1512 ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
1513 Target = CGF.Builder.CreateLoad(ClassPtr);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001514 }
Mike Stumpf5408fe2009-05-16 07:57:57 +00001515 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1516 // ObjCTypes types.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001517 const llvm::Type *ClassTy =
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001518 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001519 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001520 CGF.Builder.CreateStore(Target,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001521 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall944c8432011-05-14 03:10:52 +00001522 return EmitMessageSend(CGF, Return, ResultType,
1523 EmitSelector(CGF.Builder, Sel),
1524 ObjCSuper, ObjCTypes.SuperPtrCTy,
1525 true, CallArgs, Method, ObjCTypes);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001526}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001527
1528/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +00001529CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00001530 ReturnValueSlot Return,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +00001531 QualType ResultType,
1532 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001533 llvm::Value *Receiver,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001534 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00001535 const ObjCInterfaceDecl *Class,
Fariborz Jahaniandf9ccc62009-05-05 21:36:57 +00001536 const ObjCMethodDecl *Method) {
John McCall944c8432011-05-14 03:10:52 +00001537 return EmitMessageSend(CGF, Return, ResultType,
1538 EmitSelector(CGF.Builder, Sel),
1539 Receiver, CGF.getContext().getObjCIdType(),
1540 false, CallArgs, Method, ObjCTypes);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00001541}
1542
Daniel Dunbard6c93d72009-09-17 04:01:22 +00001543CodeGen::RValue
John McCall944c8432011-05-14 03:10:52 +00001544CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
1545 ReturnValueSlot Return,
1546 QualType ResultType,
1547 llvm::Value *Sel,
1548 llvm::Value *Arg0,
1549 QualType Arg0Ty,
1550 bool IsSuper,
1551 const CallArgList &CallArgs,
1552 const ObjCMethodDecl *Method,
1553 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001554 CallArgList ActualArgs;
Fariborz Jahaniand019d962009-04-24 21:07:43 +00001555 if (!IsSuper)
1556 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Eli Friedman04c9a492011-05-02 17:57:46 +00001557 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1558 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
Daniel Dunbar19cd87e2008-08-30 03:02:31 +00001559 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001560
Daniel Dunbar541b63b2009-02-02 23:23:47 +00001561 CodeGenTypes &Types = CGM.getTypes();
John McCall04a67a62010-02-05 21:31:56 +00001562 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindola264ba482010-03-30 20:24:48 +00001563 FunctionType::ExtInfo());
Daniel Dunbar67939662009-09-17 04:01:40 +00001564 const llvm::FunctionType *FTy =
1565 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001566
Anders Carlsson7e70fb22010-06-21 20:59:55 +00001567 if (Method)
1568 assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
1569 CGM.getContext().getCanonicalType(ResultType) &&
1570 "Result type mismatch!");
1571
John McCallcba681a2011-05-14 21:12:11 +00001572 NullReturnState nullReturn;
1573
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001574 llvm::Constant *Fn = NULL;
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001575 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
John McCallcba681a2011-05-14 21:12:11 +00001576 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001577 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001578 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001579 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1580 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1581 : ObjCTypes.getSendFpretFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001582 } else {
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00001583 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001584 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar5669e572008-10-17 03:24:53 +00001585 }
Daniel Dunbardacf9dd2010-07-14 23:39:36 +00001586 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
John McCallcba681a2011-05-14 21:12:11 +00001587 RValue rvalue = CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
1588 return nullReturn.complete(CGF, rvalue, ResultType);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001589}
1590
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001591static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
1592 if (FQT.isObjCGCStrong())
1593 return Qualifiers::Strong;
1594
1595 if (FQT.isObjCGCWeak())
1596 return Qualifiers::Weak;
1597
1598 if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
1599 return Qualifiers::Strong;
1600
1601 if (const PointerType *PT = FQT->getAs<PointerType>())
1602 return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
1603
1604 return Qualifiers::GCNone;
1605}
1606
John McCall6b5a61b2011-02-07 10:33:21 +00001607llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1608 const CGBlockInfo &blockInfo) {
1609 llvm::Constant *nullPtr =
Fariborz Jahanian44034db2010-08-04 18:44:59 +00001610 llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
John McCall6b5a61b2011-02-07 10:33:21 +00001611
Fariborz Jahanianfb550312010-09-13 16:09:44 +00001612 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
John McCall6b5a61b2011-02-07 10:33:21 +00001613 return nullPtr;
1614
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001615 bool hasUnion = false;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001616 SkipIvars.clear();
1617 IvarsInfo.clear();
1618 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
1619 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
1620
Fariborz Jahanian81979822010-09-09 00:21:45 +00001621 // __isa is the first field in block descriptor and must assume by runtime's
1622 // convention that it is GC'able.
1623 IvarsInfo.push_back(GC_IVAR(0, 1));
John McCall6b5a61b2011-02-07 10:33:21 +00001624
1625 const BlockDecl *blockDecl = blockInfo.getBlockDecl();
1626
1627 // Calculate the basic layout of the block structure.
1628 const llvm::StructLayout *layout =
1629 CGM.getTargetData().getStructLayout(blockInfo.StructureType);
1630
1631 // Ignore the optional 'this' capture: C++ objects are not assumed
1632 // to be GC'ed.
1633
1634 // Walk the captured variables.
1635 for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(),
1636 ce = blockDecl->capture_end(); ci != ce; ++ci) {
1637 const VarDecl *variable = ci->getVariable();
1638 QualType type = variable->getType();
1639
1640 const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
1641
1642 // Ignore constant captures.
1643 if (capture.isConstant()) continue;
1644
1645 uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
1646
1647 // __block variables are passed by their descriptor address.
1648 if (ci->isByRef()) {
1649 IvarsInfo.push_back(GC_IVAR(fieldOffset, /*size in words*/ 1));
Fariborz Jahanianc5904b42010-09-11 01:27:29 +00001650 continue;
John McCall6b5a61b2011-02-07 10:33:21 +00001651 }
1652
1653 assert(!type->isArrayType() && "array variable should not be caught");
1654 if (const RecordType *record = type->getAs<RecordType>()) {
1655 BuildAggrIvarRecordLayout(record, fieldOffset, true, hasUnion);
Fariborz Jahaniane1a48982010-08-05 21:00:25 +00001656 continue;
1657 }
Fariborz Jahaniana1f024c2010-08-06 16:28:55 +00001658
John McCall6b5a61b2011-02-07 10:33:21 +00001659 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);
1660 unsigned fieldSize = CGM.getContext().getTypeSize(type);
1661
1662 if (GCAttr == Qualifiers::Strong)
1663 IvarsInfo.push_back(GC_IVAR(fieldOffset,
1664 fieldSize / WordSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001665 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
John McCall6b5a61b2011-02-07 10:33:21 +00001666 SkipIvars.push_back(GC_IVAR(fieldOffset,
1667 fieldSize / ByteSizeInBits));
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001668 }
1669
1670 if (IvarsInfo.empty())
John McCall6b5a61b2011-02-07 10:33:21 +00001671 return nullPtr;
1672
1673 // Sort on byte position; captures might not be allocated in order,
1674 // and unions can do funny things.
1675 llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
1676 llvm::array_pod_sort(SkipIvars.begin(), SkipIvars.end());
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001677
1678 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00001679 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00001680 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
1681 printf("\n block variable layout for block: ");
1682 const unsigned char *s = (unsigned char*)BitMap.c_str();
1683 for (unsigned i = 0; i < BitMap.size(); i++)
1684 if (!(s[i] & 0xf0))
1685 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
1686 else
1687 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
1688 printf("\n");
1689 }
1690
1691 return C;
Fariborz Jahanian89ecd412010-08-04 16:57:49 +00001692}
1693
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001694llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +00001695 const ObjCProtocolDecl *PD) {
Daniel Dunbarc67876d2008-09-04 04:33:15 +00001696 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00001697 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc67876d2008-09-04 04:33:15 +00001698 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1699
Owen Anderson3c4972d2009-07-29 18:54:39 +00001700 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001701 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001702}
1703
Fariborz Jahanianda320092009-01-29 19:24:30 +00001704void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stumpf5408fe2009-05-16 07:57:57 +00001705 // FIXME: We shouldn't need this, the protocol decl should contain enough
1706 // information to tell us whether this was a declaration or a definition.
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001707 DefinedProtocols.insert(PD->getIdentifier());
1708
1709 // If we have generated a forward reference to this protocol, emit
1710 // it now. Otherwise do nothing, the protocol objects are lazily
1711 // emitted.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001712 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001713 GetOrEmitProtocol(PD);
1714}
1715
Fariborz Jahanianda320092009-01-29 19:24:30 +00001716llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001717 if (DefinedProtocols.count(PD->getIdentifier()))
1718 return GetOrEmitProtocol(PD);
1719 return GetOrEmitProtocolRef(PD);
1720}
1721
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001722/*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001723// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1724struct _objc_protocol {
1725struct _objc_protocol_extension *isa;
1726char *protocol_name;
1727struct _objc_protocol_list *protocol_list;
1728struct _objc__method_prototype_list *instance_methods;
1729struct _objc__method_prototype_list *class_methods
1730};
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001731
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001732See EmitProtocolExtension().
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001733*/
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001734llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1735 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1736
1737 // Early exit if a defining object has already been generated.
1738 if (Entry && Entry->hasInitializer())
1739 return Entry;
1740
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00001741 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stumpf5408fe2009-05-16 07:57:57 +00001742 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00001743 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1744
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001745 // Construct method lists.
1746 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1747 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001748 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001749 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001750 ObjCMethodDecl *MD = *i;
1751 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1752 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1753 OptInstanceMethods.push_back(C);
1754 } else {
1755 InstanceMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001756 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001757 }
1758
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001759 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00001760 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001761 ObjCMethodDecl *MD = *i;
1762 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1763 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1764 OptClassMethods.push_back(C);
1765 } else {
1766 ClassMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001767 }
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001768 }
1769
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001770 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001771 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001772 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001773 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001774 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardbc933702008-08-21 21:57:41 +00001775 PD->protocol_begin(),
1776 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001777 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001778 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001779 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1780 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001781 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001782 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001783 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1784 ClassMethods);
Owen Anderson08e25242009-07-27 22:29:56 +00001785 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001786 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001787
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001788 if (Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001789 // Already created, fix the linkage and update the initializer.
1790 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001791 Entry->setInitializer(Init);
1792 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001793 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00001794 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001795 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001796 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001797 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001798 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001799 // FIXME: Is this necessary? Why only for protocol?
1800 Entry->setAlignment(4);
1801 }
Chris Lattnerad64e022009-07-17 23:57:13 +00001802 CGM.AddUsedGlobal(Entry);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001803
1804 return Entry;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001805}
1806
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001807llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001808 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1809
1810 if (!Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001811 // We use the initializer as a marker of whether this is a forward
1812 // reference or not. At module finalization we add the empty
1813 // contents for protocols which were referenced but never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001814 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00001815 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001816 llvm::GlobalValue::ExternalLinkage,
1817 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001818 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001819 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001820 // FIXME: Is this necessary? Why only for protocol?
1821 Entry->setAlignment(4);
1822 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001823
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001824 return Entry;
1825}
1826
1827/*
1828 struct _objc_protocol_extension {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001829 uint32_t size;
1830 struct objc_method_description_list *optional_instance_methods;
1831 struct objc_method_description_list *optional_class_methods;
1832 struct objc_property_list *instance_properties;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001833 };
1834*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001835llvm::Constant *
1836CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1837 const ConstantVector &OptInstanceMethods,
1838 const ConstantVector &OptClassMethods) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001839 uint64_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00001840 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001841 std::vector<llvm::Constant*> Values(4);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001842 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001843 Values[1] =
1844 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001845 + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001846 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1847 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001848 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001849 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001850 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1851 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001852 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00001853 0, PD, ObjCTypes);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001854
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001855 // Return null if no extension bits are used.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001856 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001857 Values[3]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001858 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001859
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001860 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00001861 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001862
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001863 // No special section, but goes in llvm.used
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001864 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001865 Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001866 0, 0, true);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001867}
1868
1869/*
1870 struct objc_protocol_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001871 struct objc_protocol_list *next;
1872 long count;
1873 Protocol *list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001874 };
1875*/
Daniel Dunbardbc933702008-08-21 21:57:41 +00001876llvm::Constant *
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001877CGObjCMac::EmitProtocolList(llvm::Twine Name,
Daniel Dunbardbc933702008-08-21 21:57:41 +00001878 ObjCProtocolDecl::protocol_iterator begin,
1879 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001880 std::vector<llvm::Constant*> ProtocolRefs;
1881
Daniel Dunbardbc933702008-08-21 21:57:41 +00001882 for (; begin != end; ++begin)
1883 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001884
1885 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001886 if (ProtocolRefs.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001887 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001888
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001889 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00001890 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001891
1892 std::vector<llvm::Constant*> Values(3);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001893 // This field is only used by the runtime.
Owen Andersonc9c88b42009-07-31 20:28:54 +00001894 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001895 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001896 ProtocolRefs.size() - 1);
1897 Values[2] =
1898 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1899 ProtocolRefs.size()),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001900 ProtocolRefs);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001901
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001902 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001903 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00001904 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00001905 4, false);
Owen Anderson3c4972d2009-07-29 18:54:39 +00001906 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001907}
1908
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001909void CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
1910 std::vector<llvm::Constant*> &Properties,
1911 const Decl *Container,
1912 const ObjCProtocolDecl *PROTO,
1913 const ObjCCommonTypesHelper &ObjCTypes) {
1914 std::vector<llvm::Constant*> Prop(2);
1915 for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
1916 E = PROTO->protocol_end(); P != E; ++P)
1917 PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
1918 for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
1919 E = PROTO->prop_end(); I != E; ++I) {
1920 const ObjCPropertyDecl *PD = *I;
1921 if (!PropertySet.insert(PD->getIdentifier()))
1922 continue;
1923 Prop[0] = GetPropertyName(PD->getIdentifier());
1924 Prop[1] = GetPropertyTypeString(PD, Container);
1925 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
1926 }
1927}
1928
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001929/*
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001930 struct _objc_property {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001931 const char * const name;
1932 const char * const attributes;
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001933 };
1934
1935 struct _objc_property_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001936 uint32_t entsize; // sizeof (struct _objc_property)
1937 uint32_t prop_count;
1938 struct _objc_property[prop_count];
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001939 };
1940*/
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00001941llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001942 const Decl *Container,
1943 const ObjCContainerDecl *OCD,
1944 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001945 std::vector<llvm::Constant*> Properties, Prop(2);
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001946 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001947 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1948 E = OCD->prop_end(); I != E; ++I) {
Steve Naroff93983f82009-01-11 12:47:58 +00001949 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian191dcd72009-12-12 21:26:21 +00001950 PropertySet.insert(PD->getIdentifier());
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001951 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00001952 Prop[1] = GetPropertyTypeString(PD, Container);
Owen Anderson08e25242009-07-27 22:29:56 +00001953 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001954 Prop));
1955 }
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00001956 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek53b94412010-09-01 01:21:15 +00001957 for (ObjCInterfaceDecl::all_protocol_iterator
1958 P = OID->all_referenced_protocol_begin(),
1959 E = OID->all_referenced_protocol_end(); P != E; ++P)
Fariborz Jahanian6afbdf52010-06-22 16:33:55 +00001960 PushProtocolProperties(PropertySet, Properties, Container, (*P),
1961 ObjCTypes);
1962 }
1963 else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
1964 for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
1965 E = CD->protocol_end(); P != E; ++P)
1966 PushProtocolProperties(PropertySet, Properties, Container, (*P),
1967 ObjCTypes);
1968 }
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001969
1970 // Return null for empty list.
1971 if (Properties.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00001972 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001973
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001974 unsigned PropertySize =
Duncan Sands9408c452009-05-09 07:08:47 +00001975 CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001976 std::vector<llvm::Constant*> Values(3);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00001977 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
1978 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001979 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001980 Properties.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00001981 Values[2] = llvm::ConstantArray::get(AT, Properties);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00001982 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001983
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001984 llvm::GlobalVariable *GV =
1985 CreateMetadataVar(Name, Init,
1986 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbar0bf21992009-04-15 02:56:18 +00001987 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001988 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbar0bf21992009-04-15 02:56:18 +00001989 true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00001990 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001991}
1992
1993/*
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001994 struct objc_method_description_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00001995 int count;
1996 struct objc_method_description list[];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001997 };
1998*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001999llvm::Constant *
2000CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
2001 std::vector<llvm::Constant*> Desc(2);
Owen Andersona1cf15f2009-07-14 23:10:40 +00002002 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002003 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
2004 ObjCTypes.SelectorPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002005 Desc[1] = GetMethodVarType(MD);
Owen Anderson08e25242009-07-27 22:29:56 +00002006 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002007 Desc);
2008}
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002009
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002010llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002011 const char *Section,
2012 const ConstantVector &Methods) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002013 // Return null for empty list.
2014 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002015 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002016
2017 std::vector<llvm::Constant*> Values(2);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002018 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002019 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002020 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002021 Values[1] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002022 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002023
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002024 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002025 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002026 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002027}
2028
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002029/*
2030 struct _objc_category {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002031 char *category_name;
2032 char *class_name;
2033 struct _objc_method_list *instance_methods;
2034 struct _objc_method_list *class_methods;
2035 struct _objc_protocol_list *protocols;
2036 uint32_t size; // <rdar://4585769>
2037 struct _objc_property_list *instance_properties;
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002038 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002039*/
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00002040void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Duncan Sands9408c452009-05-09 07:08:47 +00002041 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002042
Mike Stumpf5408fe2009-05-16 07:57:57 +00002043 // FIXME: This is poor design, the OCD should have a pointer to the category
2044 // decl. Additionally, note that Category can be null for the @implementation
2045 // w/o an @interface case. Sema should just create one for us as it does for
2046 // @implementation so everyone else can live life under a clear blue sky.
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002047 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002048 const ObjCCategoryDecl *Category =
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002049 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002050
2051 llvm::SmallString<256> ExtName;
2052 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2053 << OCD->getName();
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002054
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002055 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002056 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002057 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002058 // Instance methods should always be defined.
2059 InstanceMethods.push_back(GetMethodConstant(*i));
2060 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002061 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002062 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002063 // Class methods should always be defined.
2064 ClassMethods.push_back(GetMethodConstant(*i));
2065 }
2066
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002067 std::vector<llvm::Constant*> Values(7);
2068 Values[0] = GetClassName(OCD->getIdentifier());
2069 Values[1] = GetClassName(Interface->getIdentifier());
Fariborz Jahanian679cd7f2009-04-29 20:40:05 +00002070 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002071 Values[2] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002072 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002073 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002074 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002075 Values[3] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002076 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002077 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002078 ClassMethods);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002079 if (Category) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002080 Values[4] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002081 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002082 Category->protocol_begin(),
2083 Category->protocol_end());
2084 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002085 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002086 }
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002087 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002088
2089 // If there is no category @interface then there can be no properties.
2090 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002091 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002092 OCD, Category, ObjCTypes);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002093 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002094 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00002095 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002096
Owen Anderson08e25242009-07-27 22:29:56 +00002097 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002098 Values);
2099
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002100 llvm::GlobalVariable *GV =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002101 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002102 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002103 4, true);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002104 DefinedCategories.push_back(GV);
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00002105 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00002106 // method definition entries must be clear for next implementation.
2107 MethodDefinitions.clear();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002108}
2109
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002110// FIXME: Get from somewhere?
2111enum ClassFlags {
2112 eClassFlags_Factory = 0x00001,
2113 eClassFlags_Meta = 0x00002,
2114 // <rdr://5142207>
2115 eClassFlags_HasCXXStructors = 0x02000,
2116 eClassFlags_Hidden = 0x20000,
2117 eClassFlags_ABI2_Hidden = 0x00010,
2118 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
2119};
2120
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002121/*
2122 struct _objc_class {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002123 Class isa;
2124 Class super_class;
2125 const char *name;
2126 long version;
2127 long info;
2128 long instance_size;
2129 struct _objc_ivar_list *ivars;
2130 struct _objc_method_list *methods;
2131 struct _objc_cache *cache;
2132 struct _objc_protocol_list *protocols;
2133 // Objective-C 1.0 extensions (<rdr://4585769>)
2134 const char *ivar_layout;
2135 struct _objc_class_ext *ext;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002136 };
2137
2138 See EmitClassExtension();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002139*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002140void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002141 DefinedSymbols.insert(ID->getIdentifier());
2142
Chris Lattner8ec03f52008-11-24 03:54:41 +00002143 std::string ClassName = ID->getNameAsString();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002144 // FIXME: Gross
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002145 ObjCInterfaceDecl *Interface =
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002146 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002147 llvm::Constant *Protocols =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002148 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00002149 Interface->all_referenced_protocol_begin(),
2150 Interface->all_referenced_protocol_end());
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002151 unsigned Flags = eClassFlags_Factory;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00002152 if (ID->getNumIvarInitializers())
2153 Flags |= eClassFlags_HasCXXStructors;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002154 unsigned Size =
Ken Dyck5f022d82011-02-09 01:59:34 +00002155 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002156
2157 // FIXME: Set CXX-structors flag.
John McCall1fb0caa2010-10-22 21:05:15 +00002158 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002159 Flags |= eClassFlags_Hidden;
2160
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002161 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002162 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002163 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002164 // Instance methods should always be defined.
2165 InstanceMethods.push_back(GetMethodConstant(*i));
2166 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002167 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002168 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002169 // Class methods should always be defined.
2170 ClassMethods.push_back(GetMethodConstant(*i));
2171 }
2172
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002173 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00002174 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002175 ObjCPropertyImplDecl *PID = *i;
2176
2177 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
2178 ObjCPropertyDecl *PD = PID->getPropertyDecl();
2179
2180 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
2181 if (llvm::Constant *C = GetMethodConstant(MD))
2182 InstanceMethods.push_back(C);
2183 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
2184 if (llvm::Constant *C = GetMethodConstant(MD))
2185 InstanceMethods.push_back(C);
2186 }
2187 }
2188
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002189 std::vector<llvm::Constant*> Values(12);
Daniel Dunbar5384b092009-05-03 08:56:52 +00002190 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002191 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002192 // Record a reference to the super class.
2193 LazySymbols.insert(Super->getIdentifier());
2194
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002195 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002196 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002197 ObjCTypes.ClassPtrTy);
2198 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002199 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002200 }
2201 Values[ 2] = GetClassName(ID->getIdentifier());
2202 // Version is always 0.
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002203 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2204 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2205 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002206 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002207 Values[ 7] =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002208 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002209 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002210 InstanceMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002211 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002212 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002213 Values[ 9] = Protocols;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002214 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002215 Values[11] = EmitClassExtension(ID);
Owen Anderson08e25242009-07-27 22:29:56 +00002216 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002217 Values);
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00002218 std::string Name("\01L_OBJC_CLASS_");
2219 Name += ClassName;
2220 const char *Section = "__OBJC,__class,regular,no_dead_strip";
2221 // Check for a forward reference.
2222 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2223 if (GV) {
2224 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2225 "Forward metaclass reference has incorrect type.");
2226 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2227 GV->setInitializer(Init);
2228 GV->setSection(Section);
2229 GV->setAlignment(4);
2230 CGM.AddUsedGlobal(GV);
2231 }
2232 else
2233 GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002234 DefinedClasses.push_back(GV);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00002235 // method definition entries must be clear for next implementation.
2236 MethodDefinitions.clear();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002237}
2238
2239llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2240 llvm::Constant *Protocols,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002241 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002242 unsigned Flags = eClassFlags_Meta;
Duncan Sands9408c452009-05-09 07:08:47 +00002243 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002244
John McCall1fb0caa2010-10-22 21:05:15 +00002245 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002246 Flags |= eClassFlags_Hidden;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002247
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002248 std::vector<llvm::Constant*> Values(12);
2249 // The isa for the metaclass is the root of the hierarchy.
2250 const ObjCInterfaceDecl *Root = ID->getClassInterface();
2251 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
2252 Root = Super;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002253 Values[ 0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002254 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002255 ObjCTypes.ClassPtrTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002256 // The super class for the metaclass is emitted as the name of the
2257 // super class. The runtime fixes this up to point to the
2258 // *metaclass* for the super class.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002259 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002260 Values[ 1] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002261 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002262 ObjCTypes.ClassPtrTy);
2263 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00002264 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002265 }
2266 Values[ 2] = GetClassName(ID->getIdentifier());
2267 // Version is always 0.
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002268 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2269 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
2270 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002271 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002272 Values[ 7] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00002273 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002274 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002275 Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002276 // cache is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002277 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002278 Values[ 9] = Protocols;
2279 // ivar_layout for metaclass is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002280 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002281 // The class extension is always unused for metaclasses.
Owen Andersonc9c88b42009-07-31 20:28:54 +00002282 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00002283 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002284 Values);
2285
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002286 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner8ec03f52008-11-24 03:54:41 +00002287 Name += ID->getNameAsCString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002288
2289 // Check for a forward reference.
2290 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
2291 if (GV) {
2292 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2293 "Forward metaclass reference has incorrect type.");
2294 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
2295 GV->setInitializer(Init);
2296 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00002297 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002298 llvm::GlobalValue::InternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00002299 Init, Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002300 }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002301 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbar58a29122009-03-09 22:18:41 +00002302 GV->setAlignment(4);
Chris Lattnerad64e022009-07-17 23:57:13 +00002303 CGM.AddUsedGlobal(GV);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002304
2305 return GV;
2306}
2307
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002308llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00002309 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002310
Mike Stumpf5408fe2009-05-16 07:57:57 +00002311 // FIXME: Should we look these up somewhere other than the module. Its a bit
2312 // silly since we only generate these while processing an implementation, so
2313 // exactly one pointer would work if know when we entered/exitted an
2314 // implementation block.
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002315
2316 // Check for an existing forward reference.
Fariborz Jahanianb0d27942009-01-07 20:11:22 +00002317 // Previously, metaclass with internal linkage may have been defined.
2318 // pass 'true' as 2nd argument so it is returned.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002319 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2320 true)) {
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002321 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2322 "Forward metaclass reference has incorrect type.");
2323 return GV;
2324 } else {
2325 // Generate as an external reference to keep a consistent
2326 // module. This will be patched up when we emit the metaclass.
Owen Anderson1c431b32009-07-08 19:05:04 +00002327 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002328 llvm::GlobalValue::ExternalLinkage,
2329 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00002330 Name);
Daniel Dunbarf56f1912008-08-25 08:19:24 +00002331 }
2332}
2333
Fariborz Jahanianb0069ee2009-11-12 20:14:24 +00002334llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
2335 std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
2336
2337 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2338 true)) {
2339 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
2340 "Forward class metadata reference has incorrect type.");
2341 return GV;
2342 } else {
2343 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
2344 llvm::GlobalValue::ExternalLinkage,
2345 0,
2346 Name);
2347 }
2348}
2349
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002350/*
2351 struct objc_class_ext {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002352 uint32_t size;
2353 const char *weak_ivar_layout;
2354 struct _objc_property_list *properties;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002355 };
2356*/
2357llvm::Constant *
2358CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002359 uint64_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00002360 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002361
2362 std::vector<llvm::Constant*> Values(3);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002363 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanianc71303d2009-04-22 23:00:43 +00002364 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002365 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00002366 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002367
2368 // Return null if no extension bits are used.
2369 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002370 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002371
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002372 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00002373 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002374 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002375 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002376 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002377}
2378
2379/*
2380 struct objc_ivar {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002381 char *ivar_name;
2382 char *ivar_type;
2383 int ivar_offset;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002384 };
2385
2386 struct objc_ivar_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002387 int ivar_count;
2388 struct objc_ivar list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002389 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002390*/
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002391llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002392 bool ForClass) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002393 std::vector<llvm::Constant*> Ivars, Ivar(3);
2394
2395 // When emitting the root class GCC emits ivar entries for the
2396 // actual class structure. It is not clear if we need to follow this
2397 // behavior; for now lets try and get away with not doing it. If so,
2398 // the cleanest solution would be to make up an ObjCInterfaceDecl
2399 // for the class.
2400 if (ForClass)
Owen Andersonc9c88b42009-07-31 20:28:54 +00002401 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002402
2403 ObjCInterfaceDecl *OID =
Fariborz Jahanian46b86c62009-01-28 19:12:34 +00002404 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002405
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00002406 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00002407 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002408
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00002409 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2410 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00002411 // Ignore unnamed bit-fields.
2412 if (!IVD->getDeclName())
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002413 continue;
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00002414 Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2415 Ivar[1] = GetMethodVarType(IVD);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002416 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
Daniel Dunbar97776872009-04-22 07:32:20 +00002417 ComputeIvarBaseOffset(CGM, OID, IVD));
Owen Anderson08e25242009-07-27 22:29:56 +00002418 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002419 }
2420
2421 // Return null for empty list.
2422 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002423 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002424
2425 std::vector<llvm::Constant*> Values(2);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002426 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00002427 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002428 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002429 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002430 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002431
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002432 llvm::GlobalVariable *GV;
2433 if (ForClass)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002434 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002435 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00002436 4, true);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002437 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002438 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00002439 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002440 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002441 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002442}
2443
2444/*
2445 struct objc_method {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002446 SEL method_name;
2447 char *method_types;
2448 void *method;
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002449 };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002450
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002451 struct objc_method_list {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002452 struct objc_method_list *obsolete;
2453 int count;
2454 struct objc_method methods_list[count];
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002455 };
2456*/
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002457
2458/// GetMethodConstant - Return a struct objc_method constant for the
2459/// given method if it has been defined. The result is null if the
2460/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002461llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00002462 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002463 if (!Fn)
2464 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002465
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002466 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002467 Method[0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00002468 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002469 ObjCTypes.SelectorPtrTy);
2470 Method[1] = GetMethodVarType(MD);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002471 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00002472 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002473}
2474
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002475llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002476 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00002477 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002478 // Return null for empty list.
2479 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00002480 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002481
2482 std::vector<llvm::Constant*> Values(3);
Owen Andersonc9c88b42009-07-31 20:28:54 +00002483 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00002484 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00002485 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002486 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00002487 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00002488 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002489
Daniel Dunbar0bf21992009-04-15 02:56:18 +00002490 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00002491 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002492 ObjCTypes.MethodListPtrTy);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002493}
2494
Fariborz Jahanian493dab72009-01-26 21:38:32 +00002495llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002496 const ObjCContainerDecl *CD) {
Daniel Dunbarc575ce72009-10-19 01:21:19 +00002497 llvm::SmallString<256> Name;
Fariborz Jahanian679a5022009-01-10 21:06:09 +00002498 GetNameForMethod(OMD, CD, Name);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002499
Daniel Dunbar541b63b2009-02-02 23:23:47 +00002500 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00002501 const llvm::FunctionType *MethodTy =
Daniel Dunbar541b63b2009-02-02 23:23:47 +00002502 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002503 llvm::Function *Method =
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00002504 llvm::Function::Create(MethodTy,
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002505 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00002506 Name.str(),
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002507 &CGM.getModule());
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002508 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002509
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002510 return Method;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002511}
2512
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002513llvm::GlobalVariable *
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00002514CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002515 llvm::Constant *Init,
2516 const char *Section,
Daniel Dunbar35bd7632009-03-09 20:50:13 +00002517 unsigned Align,
2518 bool AddToUsed) {
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002519 const llvm::Type *Ty = Init->getType();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002520 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00002521 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerad64e022009-07-17 23:57:13 +00002522 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002523 if (Section)
2524 GV->setSection(Section);
Daniel Dunbar35bd7632009-03-09 20:50:13 +00002525 if (Align)
2526 GV->setAlignment(Align);
2527 if (AddToUsed)
Chris Lattnerad64e022009-07-17 23:57:13 +00002528 CGM.AddUsedGlobal(GV);
Daniel Dunbarfd65d372009-03-09 20:09:19 +00002529 return GV;
2530}
2531
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002532llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002533 // Abuse this interface function as a place to finalize.
2534 FinishModule();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002535 return NULL;
2536}
2537
Chris Lattner74391b42009-03-22 21:03:39 +00002538llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002539 return ObjCTypes.getGetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00002540}
2541
Chris Lattner74391b42009-03-22 21:03:39 +00002542llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002543 return ObjCTypes.getSetPropertyFn();
Daniel Dunbar49f66022008-09-24 03:38:44 +00002544}
2545
David Chisnall8fac25d2010-12-26 22:13:16 +00002546llvm::Constant *CGObjCMac::GetGetStructFunction() {
2547 return ObjCTypes.getCopyStructFn();
2548}
2549llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian6cc59062010-04-12 18:18:10 +00002550 return ObjCTypes.getCopyStructFn();
2551}
2552
Chris Lattner74391b42009-03-22 21:03:39 +00002553llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattner72db6c32009-04-22 02:44:54 +00002554 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson2abd89c2008-08-31 04:05:03 +00002555}
2556
John McCallf1549f62010-07-06 01:34:17 +00002557void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
2558 return EmitTryOrSynchronizedStmt(CGF, S);
2559}
2560
2561void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
2562 const ObjCAtSynchronizedStmt &S) {
2563 return EmitTryOrSynchronizedStmt(CGF, S);
2564}
2565
John McCallcc505292010-07-21 06:59:36 +00002566namespace {
John McCall1f0fca52010-07-21 07:22:38 +00002567 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCallcc505292010-07-21 06:59:36 +00002568 const Stmt &S;
John McCall0b251722010-08-04 05:59:32 +00002569 llvm::Value *SyncArgSlot;
John McCallcc505292010-07-21 06:59:36 +00002570 llvm::Value *CallTryExitVar;
2571 llvm::Value *ExceptionData;
2572 ObjCTypesHelper &ObjCTypes;
2573 PerformFragileFinally(const Stmt *S,
John McCall0b251722010-08-04 05:59:32 +00002574 llvm::Value *SyncArgSlot,
John McCallcc505292010-07-21 06:59:36 +00002575 llvm::Value *CallTryExitVar,
2576 llvm::Value *ExceptionData,
2577 ObjCTypesHelper *ObjCTypes)
John McCall0b251722010-08-04 05:59:32 +00002578 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCallcc505292010-07-21 06:59:36 +00002579 ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
2580
2581 void Emit(CodeGenFunction &CGF, bool IsForEH) {
2582 // Check whether we need to call objc_exception_try_exit.
2583 // In optimized code, this branch will always be folded.
2584 llvm::BasicBlock *FinallyCallExit =
2585 CGF.createBasicBlock("finally.call_exit");
2586 llvm::BasicBlock *FinallyNoCallExit =
2587 CGF.createBasicBlock("finally.no_call_exit");
2588 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
2589 FinallyCallExit, FinallyNoCallExit);
2590
2591 CGF.EmitBlock(FinallyCallExit);
2592 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
2593 ->setDoesNotThrow();
2594
2595 CGF.EmitBlock(FinallyNoCallExit);
2596
2597 if (isa<ObjCAtTryStmt>(S)) {
2598 if (const ObjCAtFinallyStmt* FinallyStmt =
John McCalld96a8e72010-08-11 00:16:14 +00002599 cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
2600 // Save the current cleanup destination in case there's
2601 // control flow inside the finally statement.
2602 llvm::Value *CurCleanupDest =
2603 CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());
2604
John McCallcc505292010-07-21 06:59:36 +00002605 CGF.EmitStmt(FinallyStmt->getFinallyBody());
2606
John McCalld96a8e72010-08-11 00:16:14 +00002607 if (CGF.HaveInsertPoint()) {
2608 CGF.Builder.CreateStore(CurCleanupDest,
2609 CGF.getNormalCleanupDestSlot());
2610 } else {
2611 // Currently, the end of the cleanup must always exist.
2612 CGF.EnsureInsertPoint();
2613 }
2614 }
John McCallcc505292010-07-21 06:59:36 +00002615 } else {
2616 // Emit objc_sync_exit(expr); as finally's sole statement for
2617 // @synchronized.
John McCall0b251722010-08-04 05:59:32 +00002618 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCallcc505292010-07-21 06:59:36 +00002619 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2620 ->setDoesNotThrow();
2621 }
2622 }
2623 };
John McCall87bb5822010-07-31 23:20:56 +00002624
2625 class FragileHazards {
2626 CodeGenFunction &CGF;
2627 llvm::SmallVector<llvm::Value*, 20> Locals;
2628 llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
2629
2630 llvm::InlineAsm *ReadHazard;
2631 llvm::InlineAsm *WriteHazard;
2632
2633 llvm::FunctionType *GetAsmFnType();
2634
2635 void collectLocals();
2636 void emitReadHazard(CGBuilderTy &Builder);
2637
2638 public:
2639 FragileHazards(CodeGenFunction &CGF);
John McCall0b251722010-08-04 05:59:32 +00002640
John McCall87bb5822010-07-31 23:20:56 +00002641 void emitWriteHazard();
John McCall0b251722010-08-04 05:59:32 +00002642 void emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00002643 };
2644}
2645
2646/// Create the fragile-ABI read and write hazards based on the current
2647/// state of the function, which is presumed to be immediately prior
2648/// to a @try block. These hazards are used to maintain correct
2649/// semantics in the face of optimization and the fragile ABI's
2650/// cavalier use of setjmp/longjmp.
2651FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
2652 collectLocals();
2653
2654 if (Locals.empty()) return;
2655
2656 // Collect all the blocks in the function.
2657 for (llvm::Function::iterator
2658 I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
2659 BlocksBeforeTry.insert(&*I);
2660
2661 llvm::FunctionType *AsmFnTy = GetAsmFnType();
2662
2663 // Create a read hazard for the allocas. This inhibits dead-store
2664 // optimizations and forces the values to memory. This hazard is
2665 // inserted before any 'throwing' calls in the protected scope to
2666 // reflect the possibility that the variables might be read from the
2667 // catch block if the call throws.
2668 {
2669 std::string Constraint;
2670 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2671 if (I) Constraint += ',';
2672 Constraint += "*m";
2673 }
2674
2675 ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2676 }
2677
2678 // Create a write hazard for the allocas. This inhibits folding
2679 // loads across the hazard. This hazard is inserted at the
2680 // beginning of the catch path to reflect the possibility that the
2681 // variables might have been written within the protected scope.
2682 {
2683 std::string Constraint;
2684 for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
2685 if (I) Constraint += ',';
2686 Constraint += "=*m";
2687 }
2688
2689 WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
2690 }
2691}
2692
2693/// Emit a write hazard at the current location.
2694void FragileHazards::emitWriteHazard() {
2695 if (Locals.empty()) return;
2696
2697 CGF.Builder.CreateCall(WriteHazard, Locals.begin(), Locals.end())
2698 ->setDoesNotThrow();
2699}
2700
John McCall87bb5822010-07-31 23:20:56 +00002701void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
2702 assert(!Locals.empty());
2703 Builder.CreateCall(ReadHazard, Locals.begin(), Locals.end())
2704 ->setDoesNotThrow();
2705}
2706
2707/// Emit read hazards in all the protected blocks, i.e. all the blocks
2708/// which have been inserted since the beginning of the try.
John McCall0b251722010-08-04 05:59:32 +00002709void FragileHazards::emitHazardsInNewBlocks() {
John McCall87bb5822010-07-31 23:20:56 +00002710 if (Locals.empty()) return;
2711
2712 CGBuilderTy Builder(CGF.getLLVMContext());
2713
2714 // Iterate through all blocks, skipping those prior to the try.
2715 for (llvm::Function::iterator
2716 FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
2717 llvm::BasicBlock &BB = *FI;
2718 if (BlocksBeforeTry.count(&BB)) continue;
2719
2720 // Walk through all the calls in the block.
2721 for (llvm::BasicBlock::iterator
2722 BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
2723 llvm::Instruction &I = *BI;
2724
2725 // Ignore instructions that aren't non-intrinsic calls.
2726 // These are the only calls that can possibly call longjmp.
2727 if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
2728 if (isa<llvm::IntrinsicInst>(I))
2729 continue;
2730
2731 // Ignore call sites marked nounwind. This may be questionable,
2732 // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
2733 llvm::CallSite CS(&I);
2734 if (CS.doesNotThrow()) continue;
2735
John McCall0b251722010-08-04 05:59:32 +00002736 // Insert a read hazard before the call. This will ensure that
2737 // any writes to the locals are performed before making the
2738 // call. If the call throws, then this is sufficient to
2739 // guarantee correctness as long as it doesn't also write to any
2740 // locals.
John McCall87bb5822010-07-31 23:20:56 +00002741 Builder.SetInsertPoint(&BB, BI);
2742 emitReadHazard(Builder);
2743 }
2744 }
2745}
2746
2747static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
2748 if (V) S.insert(V);
2749}
2750
2751void FragileHazards::collectLocals() {
2752 // Compute a set of allocas to ignore.
2753 llvm::DenseSet<llvm::Value*> AllocasToIgnore;
2754 addIfPresent(AllocasToIgnore, CGF.ReturnValue);
2755 addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
2756 addIfPresent(AllocasToIgnore, CGF.EHCleanupDest);
2757
2758 // Collect all the allocas currently in the function. This is
2759 // probably way too aggressive.
2760 llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
2761 for (llvm::BasicBlock::iterator
2762 I = Entry.begin(), E = Entry.end(); I != E; ++I)
2763 if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
2764 Locals.push_back(&*I);
2765}
2766
2767llvm::FunctionType *FragileHazards::GetAsmFnType() {
2768 std::vector<const llvm::Type *> Tys(Locals.size());
2769 for (unsigned I = 0, E = Locals.size(); I != E; ++I)
2770 Tys[I] = Locals[I]->getType();
2771 return llvm::FunctionType::get(CGF.Builder.getVoidTy(), Tys, false);
John McCallcc505292010-07-21 06:59:36 +00002772}
2773
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002774/*
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002775
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002776 Objective-C setjmp-longjmp (sjlj) Exception Handling
2777 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002778
John McCallf1549f62010-07-06 01:34:17 +00002779 A catch buffer is a setjmp buffer plus:
2780 - a pointer to the exception that was caught
2781 - a pointer to the previous exception data buffer
2782 - two pointers of reserved storage
2783 Therefore catch buffers form a stack, with a pointer to the top
2784 of the stack kept in thread-local storage.
2785
2786 objc_exception_try_enter pushes a catch buffer onto the EH stack.
2787 objc_exception_try_exit pops the given catch buffer, which is
2788 required to be the top of the EH stack.
2789 objc_exception_throw pops the top of the EH stack, writes the
2790 thrown exception into the appropriate field, and longjmps
2791 to the setjmp buffer. It crashes the process (with a printf
2792 and an abort()) if there are no catch buffers on the stack.
2793 objc_exception_extract just reads the exception pointer out of the
2794 catch buffer.
2795
2796 There's no reason an implementation couldn't use a light-weight
2797 setjmp here --- something like __builtin_setjmp, but API-compatible
2798 with the heavyweight setjmp. This will be more important if we ever
2799 want to implement correct ObjC/C++ exception interactions for the
2800 fragile ABI.
2801
2802 Note that for this use of setjmp/longjmp to be correct, we may need
2803 to mark some local variables volatile: if a non-volatile local
2804 variable is modified between the setjmp and the longjmp, it has
2805 indeterminate value. For the purposes of LLVM IR, it may be
2806 sufficient to make loads and stores within the @try (to variables
2807 declared outside the @try) volatile. This is necessary for
2808 optimized correctness, but is not currently being done; this is
2809 being tracked as rdar://problem/8160285
2810
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002811 The basic framework for a @try-catch-finally is as follows:
2812 {
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002813 objc_exception_data d;
2814 id _rethrow = null;
Anders Carlsson190d00e2009-02-07 21:26:04 +00002815 bool _call_try_exit = true;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002816
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002817 objc_exception_try_enter(&d);
2818 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002819 ... try body ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002820 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002821 // exception path
2822 id _caught = objc_exception_extract(&d);
2823
2824 // enter new try scope for handlers
2825 if (!setjmp(d.jmp_buf)) {
2826 ... match exception and execute catch blocks ...
2827
2828 // fell off end, rethrow.
2829 _rethrow = _caught;
2830 ... jump-through-finally to finally_rethrow ...
2831 } else {
2832 // exception in catch block
2833 _rethrow = objc_exception_extract(&d);
2834 _call_try_exit = false;
2835 ... jump-through-finally to finally_rethrow ...
2836 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002837 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00002838 ... jump-through-finally to finally_end ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002839
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002840 finally:
Anders Carlsson190d00e2009-02-07 21:26:04 +00002841 if (_call_try_exit)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002842 objc_exception_try_exit(&d);
Anders Carlsson190d00e2009-02-07 21:26:04 +00002843
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002844 ... finally block ....
Daniel Dunbar898d5082008-09-30 01:06:03 +00002845 ... dispatch to finally destination ...
2846
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002847 finally_rethrow:
Daniel Dunbar898d5082008-09-30 01:06:03 +00002848 objc_exception_throw(_rethrow);
2849
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002850 finally_end:
2851 }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002852
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002853 This framework differs slightly from the one gcc uses, in that gcc
2854 uses _rethrow to determine if objc_exception_try_exit should be called
2855 and if the object should be rethrown. This breaks in the face of
2856 throwing nil and introduces unnecessary branches.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002857
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002858 We specialize this framework for a few particular circumstances:
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002859
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002860 - If there are no catch blocks, then we avoid emitting the second
2861 exception handling context.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002862
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002863 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2864 e)) we avoid emitting the code to rethrow an uncaught exception.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002865
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002866 - FIXME: If there is no @finally block we can do a few more
2867 simplifications.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002868
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002869 Rethrows and Jumps-Through-Finally
2870 --
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002871
John McCallf1549f62010-07-06 01:34:17 +00002872 '@throw;' is supported by pushing the currently-caught exception
2873 onto ObjCEHStack while the @catch blocks are emitted.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002874
John McCallf1549f62010-07-06 01:34:17 +00002875 Branches through the @finally block are handled with an ordinary
2876 normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
2877 exceptions are not compatible with C++ exceptions, and this is
2878 hardly the only place where this will go wrong.
Daniel Dunbar898d5082008-09-30 01:06:03 +00002879
John McCallf1549f62010-07-06 01:34:17 +00002880 @synchronized(expr) { stmt; } is emitted as if it were:
2881 id synch_value = expr;
2882 objc_sync_enter(synch_value);
2883 @try { stmt; } @finally { objc_sync_exit(synch_value); }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00002884*/
2885
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00002886void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2887 const Stmt &S) {
2888 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallf1549f62010-07-06 01:34:17 +00002889
2890 // A destination for the fall-through edges of the catch handlers to
2891 // jump to.
2892 CodeGenFunction::JumpDest FinallyEnd =
2893 CGF.getJumpDestInCurrentScope("finally.end");
2894
2895 // A destination for the rethrow edge of the catch handlers to jump
2896 // to.
2897 CodeGenFunction::JumpDest FinallyRethrow =
2898 CGF.getJumpDestInCurrentScope("finally.rethrow");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002899
Daniel Dunbar1c566672009-02-24 01:43:46 +00002900 // For @synchronized, call objc_sync_enter(sync.expr). The
2901 // evaluation of the expression must occur before we enter the
John McCall0b251722010-08-04 05:59:32 +00002902 // @synchronized. We can't avoid a temp here because we need the
2903 // value to be preserved. If the backend ever does liveness
2904 // correctly after setjmp, this will be unnecessary.
2905 llvm::Value *SyncArgSlot = 0;
Daniel Dunbar1c566672009-02-24 01:43:46 +00002906 if (!isTry) {
John McCall0b251722010-08-04 05:59:32 +00002907 llvm::Value *SyncArg =
Daniel Dunbar1c566672009-02-24 01:43:46 +00002908 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2909 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallf1549f62010-07-06 01:34:17 +00002910 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
2911 ->setDoesNotThrow();
John McCall0b251722010-08-04 05:59:32 +00002912
2913 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
2914 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar1c566672009-02-24 01:43:46 +00002915 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00002916
John McCall0b251722010-08-04 05:59:32 +00002917 // Allocate memory for the setjmp buffer. This needs to be kept
2918 // live throughout the try and catch blocks.
2919 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2920 "exceptiondata.ptr");
2921
John McCall87bb5822010-07-31 23:20:56 +00002922 // Create the fragile hazards. Note that this will not capture any
2923 // of the allocas required for exception processing, but will
2924 // capture the current basic block (which extends all the way to the
2925 // setjmp call) as "before the @try".
2926 FragileHazards Hazards(CGF);
2927
John McCallf1549f62010-07-06 01:34:17 +00002928 // Create a flag indicating whether the cleanup needs to call
2929 // objc_exception_try_exit. This is true except when
2930 // - no catches match and we're branching through the cleanup
2931 // just to rethrow the exception, or
2932 // - a catch matched and we're falling out of the catch handler.
John McCall0b251722010-08-04 05:59:32 +00002933 // The setjmp-safety rule here is that we should always store to this
2934 // variable in a place that dominates the branch through the cleanup
2935 // without passing through any setjmps.
John McCallf1549f62010-07-06 01:34:17 +00002936 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlsson190d00e2009-02-07 21:26:04 +00002937 "_call_try_exit");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002938
John McCall9e2213d2010-10-04 23:42:51 +00002939 // A slot containing the exception to rethrow. Only needed when we
2940 // have both a @catch and a @finally.
2941 llvm::Value *PropagatingExnVar = 0;
2942
John McCallf1549f62010-07-06 01:34:17 +00002943 // Push a normal cleanup to leave the try scope.
John McCall1f0fca52010-07-21 07:22:38 +00002944 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall0b251722010-08-04 05:59:32 +00002945 SyncArgSlot,
John McCall1f0fca52010-07-21 07:22:38 +00002946 CallTryExitVar,
2947 ExceptionData,
2948 &ObjCTypes);
John McCallf1549f62010-07-06 01:34:17 +00002949
2950 // Enter a try block:
2951 // - Call objc_exception_try_enter to push ExceptionData on top of
2952 // the EH stack.
2953 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
2954 ->setDoesNotThrow();
2955
2956 // - Call setjmp on the exception data buffer.
2957 llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
2958 llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
2959 llvm::Value *SetJmpBuffer =
2960 CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, GEPIndexes+3, "setjmp_buffer");
2961 llvm::CallInst *SetJmpResult =
2962 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
2963 SetJmpResult->setDoesNotThrow();
2964
2965 // If setjmp returned 0, enter the protected block; otherwise,
2966 // branch to the handler.
Daniel Dunbar55e87422008-11-11 02:29:29 +00002967 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2968 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallf1549f62010-07-06 01:34:17 +00002969 llvm::Value *DidCatch =
John McCalld96a8e72010-08-11 00:16:14 +00002970 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
2971 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson80f25672008-09-09 17:59:25 +00002972
John McCallf1549f62010-07-06 01:34:17 +00002973 // Emit the protected block.
Anders Carlsson80f25672008-09-09 17:59:25 +00002974 CGF.EmitBlock(TryBlock);
John McCall0b251722010-08-04 05:59:32 +00002975 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002976 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallf1549f62010-07-06 01:34:17 +00002977 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall0b251722010-08-04 05:59:32 +00002978
2979 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00002980
John McCallf1549f62010-07-06 01:34:17 +00002981 // Emit the exception handler block.
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00002982 CGF.EmitBlock(TryHandler);
Daniel Dunbar55e40722008-09-27 07:03:52 +00002983
John McCall87bb5822010-07-31 23:20:56 +00002984 // Don't optimize loads of the in-scope locals across this point.
2985 Hazards.emitWriteHazard();
2986
John McCallf1549f62010-07-06 01:34:17 +00002987 // For a @synchronized (or a @try with no catches), just branch
2988 // through the cleanup to the rethrow block.
2989 if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
2990 // Tell the cleanup not to re-pop the exit.
John McCall0b251722010-08-04 05:59:32 +00002991 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00002992 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallf1549f62010-07-06 01:34:17 +00002993
2994 // Otherwise, we have to match against the caught exceptions.
2995 } else {
John McCall0b251722010-08-04 05:59:32 +00002996 // Retrieve the exception object. We may emit multiple blocks but
2997 // nothing can cross this so the value is already in SSA form.
2998 llvm::CallInst *Caught =
2999 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3000 ExceptionData, "caught");
3001 Caught->setDoesNotThrow();
3002
John McCallf1549f62010-07-06 01:34:17 +00003003 // Push the exception to rethrow onto the EH value stack for the
3004 // benefit of any @throws in the handlers.
3005 CGF.ObjCEHValueStack.push_back(Caught);
3006
Douglas Gregor8f5e3dd2010-04-23 22:50:49 +00003007 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003008
John McCall0b251722010-08-04 05:59:32 +00003009 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallf1549f62010-07-06 01:34:17 +00003010
John McCall0b251722010-08-04 05:59:32 +00003011 llvm::BasicBlock *CatchBlock = 0;
3012 llvm::BasicBlock *CatchHandler = 0;
3013 if (HasFinally) {
John McCall9e2213d2010-10-04 23:42:51 +00003014 // Save the currently-propagating exception before
3015 // objc_exception_try_enter clears the exception slot.
3016 PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(),
3017 "propagating_exception");
3018 CGF.Builder.CreateStore(Caught, PropagatingExnVar);
3019
John McCall0b251722010-08-04 05:59:32 +00003020 // Enter a new exception try block (in case a @catch block
3021 // throws an exception).
3022 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
3023 ->setDoesNotThrow();
Anders Carlsson80f25672008-09-09 17:59:25 +00003024
John McCall0b251722010-08-04 05:59:32 +00003025 llvm::CallInst *SetJmpResult =
3026 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3027 "setjmp.result");
3028 SetJmpResult->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003029
John McCall0b251722010-08-04 05:59:32 +00003030 llvm::Value *Threw =
3031 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
3032
3033 CatchBlock = CGF.createBasicBlock("catch");
3034 CatchHandler = CGF.createBasicBlock("catch_for_catch");
3035 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
3036
3037 CGF.EmitBlock(CatchBlock);
3038 }
3039
3040 CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003041
Daniel Dunbar55e40722008-09-27 07:03:52 +00003042 // Handle catch list. As a special case we check if everything is
3043 // matched and avoid generating code for falling off the end if
3044 // so.
3045 bool AllMatched = false;
Douglas Gregor8f5e3dd2010-04-23 22:50:49 +00003046 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3047 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson80f25672008-09-09 17:59:25 +00003048
Douglas Gregorc00d8e12010-04-26 16:46:50 +00003049 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff14108da2009-07-10 23:34:53 +00003050 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar129271a2008-09-27 07:36:24 +00003051
Anders Carlsson80f25672008-09-09 17:59:25 +00003052 // catch(...) always matches.
Daniel Dunbar55e40722008-09-27 07:03:52 +00003053 if (!CatchParam) {
3054 AllMatched = true;
3055 } else {
John McCall183700f2009-09-21 23:43:11 +00003056 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003057
John McCallf1549f62010-07-06 01:34:17 +00003058 // catch(id e) always matches under this ABI, since only
3059 // ObjC exceptions end up here in the first place.
Daniel Dunbar97f61d12008-09-27 22:21:14 +00003060 // FIXME: For the time being we also match id<X>; this should
3061 // be rejected by Sema instead.
Eli Friedman818e96f2009-07-11 00:57:02 +00003062 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbar55e40722008-09-27 07:03:52 +00003063 AllMatched = true;
Anders Carlsson80f25672008-09-09 17:59:25 +00003064 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003065
John McCallf1549f62010-07-06 01:34:17 +00003066 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003067 if (AllMatched) {
John McCallf1549f62010-07-06 01:34:17 +00003068 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3069
Anders Carlssondde0a942008-09-11 09:15:33 +00003070 if (CatchParam) {
John McCallb6bbcc92010-10-15 04:57:14 +00003071 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003072 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallf1549f62010-07-06 01:34:17 +00003073
3074 // These types work out because ConvertType(id) == i8*.
Steve Naroff7ba138a2009-03-03 19:52:17 +00003075 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlssondde0a942008-09-11 09:15:33 +00003076 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003077
Anders Carlssondde0a942008-09-11 09:15:33 +00003078 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003079
3080 // The scope of the catch variable ends right here.
3081 CatchVarCleanups.ForceCleanup();
3082
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003083 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson80f25672008-09-09 17:59:25 +00003084 break;
3085 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003086
Steve Naroff14108da2009-07-10 23:34:53 +00003087 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall506b57e2010-05-17 21:00:27 +00003088 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallf1549f62010-07-06 01:34:17 +00003089
3090 // FIXME: @catch (Class c) ?
John McCall506b57e2010-05-17 21:00:27 +00003091 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3092 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson80f25672008-09-09 17:59:25 +00003093
3094 // Check if the @catch block matches the exception object.
John McCall506b57e2010-05-17 21:00:27 +00003095 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003096
John McCallf1549f62010-07-06 01:34:17 +00003097 llvm::CallInst *Match =
Chris Lattner34b02a12009-04-22 02:26:14 +00003098 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3099 Class, Caught, "match");
John McCallf1549f62010-07-06 01:34:17 +00003100 Match->setDoesNotThrow();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003101
John McCallf1549f62010-07-06 01:34:17 +00003102 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3103 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003104
3105 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00003106 MatchedBlock, NextCatchBlock);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003107
Anders Carlsson80f25672008-09-09 17:59:25 +00003108 // Emit the @catch block.
3109 CGF.EmitBlock(MatchedBlock);
John McCallf1549f62010-07-06 01:34:17 +00003110
3111 // Collect any cleanups for the catch variable. The scope lasts until
3112 // the end of the catch body.
John McCall0b251722010-08-04 05:59:32 +00003113 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallf1549f62010-07-06 01:34:17 +00003114
John McCallb6bbcc92010-10-15 04:57:14 +00003115 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00003116 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003117
John McCallf1549f62010-07-06 01:34:17 +00003118 // Initialize the catch variable.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003119 llvm::Value *Tmp =
3120 CGF.Builder.CreateBitCast(Caught,
3121 CGF.ConvertType(CatchParam->getType()),
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003122 "tmp");
Steve Naroff7ba138a2009-03-03 19:52:17 +00003123 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003124
Anders Carlssondde0a942008-09-11 09:15:33 +00003125 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallf1549f62010-07-06 01:34:17 +00003126
3127 // We're done with the catch variable.
3128 CatchVarCleanups.ForceCleanup();
3129
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003130 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003131
Anders Carlsson80f25672008-09-09 17:59:25 +00003132 CGF.EmitBlock(NextCatchBlock);
3133 }
3134
John McCallf1549f62010-07-06 01:34:17 +00003135 CGF.ObjCEHValueStack.pop_back();
3136
John McCall0b251722010-08-04 05:59:32 +00003137 // If nothing wanted anything to do with the caught exception,
3138 // kill the extract call.
3139 if (Caught->use_empty())
3140 Caught->eraseFromParent();
3141
3142 if (!AllMatched)
3143 CGF.EmitBranchThroughCleanup(FinallyRethrow);
3144
3145 if (HasFinally) {
3146 // Emit the exception handler for the @catch blocks.
3147 CGF.EmitBlock(CatchHandler);
3148
3149 // In theory we might now need a write hazard, but actually it's
3150 // unnecessary because there's no local-accessing code between
3151 // the try's write hazard and here.
3152 //Hazards.emitWriteHazard();
3153
John McCall9e2213d2010-10-04 23:42:51 +00003154 // Extract the new exception and save it to the
3155 // propagating-exception slot.
3156 assert(PropagatingExnVar);
3157 llvm::CallInst *NewCaught =
3158 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3159 ExceptionData, "caught");
3160 NewCaught->setDoesNotThrow();
3161 CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);
3162
John McCall0b251722010-08-04 05:59:32 +00003163 // Don't pop the catch handler; the throw already did.
3164 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003165 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar55e40722008-09-27 07:03:52 +00003166 }
Anders Carlsson80f25672008-09-09 17:59:25 +00003167 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003168
John McCall87bb5822010-07-31 23:20:56 +00003169 // Insert read hazards as required in the new blocks.
John McCall0b251722010-08-04 05:59:32 +00003170 Hazards.emitHazardsInNewBlocks();
John McCall87bb5822010-07-31 23:20:56 +00003171
John McCallf1549f62010-07-06 01:34:17 +00003172 // Pop the cleanup.
John McCall0b251722010-08-04 05:59:32 +00003173 CGF.Builder.restoreIP(TryFallthroughIP);
3174 if (CGF.HaveInsertPoint())
3175 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallf1549f62010-07-06 01:34:17 +00003176 CGF.PopCleanupBlock();
John McCall0b251722010-08-04 05:59:32 +00003177 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonf3a79a92009-02-09 20:38:58 +00003178
John McCallf1549f62010-07-06 01:34:17 +00003179 // Emit the rethrow block.
John McCall87bb5822010-07-31 23:20:56 +00003180 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallff8e1152010-07-23 21:56:41 +00003181 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallf1549f62010-07-06 01:34:17 +00003182 if (CGF.HaveInsertPoint()) {
John McCall9e2213d2010-10-04 23:42:51 +00003183 // If we have a propagating-exception variable, check it.
3184 llvm::Value *PropagatingExn;
3185 if (PropagatingExnVar) {
3186 PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);
John McCall0b251722010-08-04 05:59:32 +00003187
John McCall9e2213d2010-10-04 23:42:51 +00003188 // Otherwise, just look in the buffer for the exception to throw.
3189 } else {
3190 llvm::CallInst *Caught =
3191 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
3192 ExceptionData);
3193 Caught->setDoesNotThrow();
3194 PropagatingExn = Caught;
3195 }
3196
3197 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), PropagatingExn)
John McCallf1549f62010-07-06 01:34:17 +00003198 ->setDoesNotThrow();
3199 CGF.Builder.CreateUnreachable();
Fariborz Jahanianf2878e52008-11-21 19:21:53 +00003200 }
Anders Carlsson80f25672008-09-09 17:59:25 +00003201
John McCall87bb5822010-07-31 23:20:56 +00003202 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00003203}
3204
3205void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar898d5082008-09-30 01:06:03 +00003206 const ObjCAtThrowStmt &S) {
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003207 llvm::Value *ExceptionAsObject;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003208
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003209 if (const Expr *ThrowExpr = S.getThrowExpr()) {
3210 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003211 ExceptionAsObject =
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003212 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
3213 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003214 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar18ccc772008-09-28 01:03:14 +00003215 "Unexpected rethrow outside @catch block.");
Anders Carlsson273558f2009-02-07 21:37:21 +00003216 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlsson2b1e3112008-09-09 16:16:55 +00003217 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003218
John McCallf1549f62010-07-06 01:34:17 +00003219 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3220 ->setDoesNotReturn();
Anders Carlsson80f25672008-09-09 17:59:25 +00003221 CGF.Builder.CreateUnreachable();
Daniel Dunbara448fb22008-11-11 23:11:34 +00003222
3223 // Clear the insertion point to indicate we are in unreachable code.
3224 CGF.Builder.ClearInsertionPoint();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00003225}
3226
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003227/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00003228/// object: objc_read_weak (id *src)
3229///
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003230llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003231 llvm::Value *AddrWeakObj) {
Eli Friedman8339b352009-03-07 03:57:15 +00003232 const llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003233 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3234 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3235 ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00003236 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003237 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00003238 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00003239 return read_weak;
3240}
3241
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003242/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
3243/// objc_assign_weak (id src, id *dst)
3244///
3245void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003246 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003247 const llvm::Type * SrcTy = src->getType();
3248 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003249 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003250 assert(Size <= 8 && "does not support size > 8");
3251 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003252 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003253 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3254 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003255 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3256 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00003257 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00003258 src, dst, "weakassign");
3259 return;
3260}
3261
Fariborz Jahanian58626502008-11-19 00:59:10 +00003262/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
3263/// objc_assign_global (id src, id *dst)
3264///
3265void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00003266 llvm::Value *src, llvm::Value *dst,
3267 bool threadlocal) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003268 const llvm::Type * SrcTy = src->getType();
3269 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003270 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003271 assert(Size <= 8 && "does not support size > 8");
3272 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003273 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003274 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3275 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003276 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3277 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00003278 if (!threadlocal)
3279 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
3280 src, dst, "globalassign");
3281 else
3282 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
3283 src, dst, "threadlocalassign");
Fariborz Jahanian58626502008-11-19 00:59:10 +00003284 return;
3285}
3286
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003287/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003288/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003289///
3290void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003291 llvm::Value *src, llvm::Value *dst,
3292 llvm::Value *ivarOffset) {
3293 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003294 const llvm::Type * SrcTy = src->getType();
3295 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003296 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003297 assert(Size <= 8 && "does not support size > 8");
3298 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003299 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003300 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3301 }
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003302 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3303 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00003304 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3305 src, dst, ivarOffset);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00003306 return;
3307}
3308
Fariborz Jahanian58626502008-11-19 00:59:10 +00003309/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
3310/// objc_assign_strongCast (id src, id *dst)
3311///
3312void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00003313 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003314 const llvm::Type * SrcTy = src->getType();
3315 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00003316 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00003317 assert(Size <= 8 && "does not support size > 8");
3318 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003319 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00003320 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3321 }
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00003322 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3323 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00003324 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian58626502008-11-19 00:59:10 +00003325 src, dst, "weakassign");
3326 return;
3327}
3328
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003329void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003330 llvm::Value *DestPtr,
3331 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00003332 llvm::Value *size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003333 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3334 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003335 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00003336 DestPtr, SrcPtr, size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00003337 return;
3338}
3339
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00003340/// EmitObjCValueForIvar - Code Gen for ivar reference.
3341///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00003342LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3343 QualType ObjectTy,
3344 llvm::Value *BaseValue,
3345 const ObjCIvarDecl *Ivar,
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00003346 unsigned CVRQualifiers) {
John McCallc12c5bb2010-05-15 11:32:37 +00003347 const ObjCInterfaceDecl *ID =
3348 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00003349 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3350 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian0bb20362009-02-02 20:02:29 +00003351}
3352
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003353llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2a031922009-04-22 05:08:15 +00003354 const ObjCInterfaceDecl *Interface,
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003355 const ObjCIvarDecl *Ivar) {
Daniel Dunbar97776872009-04-22 07:32:20 +00003356 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003357 return llvm::ConstantInt::get(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003358 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3359 Offset);
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00003360}
3361
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003362/* *** Private Interface *** */
3363
3364/// EmitImageInfo - Emit the image info marker used to encode some module
3365/// level information.
3366///
3367/// See: <rdr://4810609&4810587&4810587>
3368/// struct IMAGE_INFO {
3369/// unsigned version;
3370/// unsigned flags;
3371/// };
3372enum ImageInfoFlags {
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003373 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003374 eImageInfo_GarbageCollected = (1 << 1),
3375 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003376 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3377
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003378 // A flag indicating that the module has no instances of a @synthesize of a
3379 // superclass variable. <rdar://problem/6803242>
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003380 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003381};
3382
Daniel Dunbarfce176b2010-04-25 20:39:01 +00003383void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003384 unsigned version = 0; // Version is unused?
3385 unsigned flags = 0;
3386
3387 // FIXME: Fix and continue?
3388 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
3389 flags |= eImageInfo_GarbageCollected;
3390 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
3391 flags |= eImageInfo_GCOnly;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003392
Daniel Dunbarc7c6dc02009-04-20 07:11:47 +00003393 // We never allow @synthesize of a superclass property.
3394 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003395
Chris Lattner77b89b82010-06-27 07:15:29 +00003396 const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
3397
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003398 // Emitted as int[2];
3399 llvm::Constant *values[2] = {
Chris Lattner77b89b82010-06-27 07:15:29 +00003400 llvm::ConstantInt::get(Int32Ty, version),
3401 llvm::ConstantInt::get(Int32Ty, flags)
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003402 };
Chris Lattner77b89b82010-06-27 07:15:29 +00003403 llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003404
3405 const char *Section;
3406 if (ObjCABI == 1)
3407 Section = "__OBJC, __image_info,regular";
3408 else
3409 Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003410 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003411 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
Owen Anderson7db6d832009-07-28 18:33:04 +00003412 llvm::ConstantArray::get(AT, values, 2),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003413 Section,
3414 0,
3415 true);
3416 GV->setConstant(true);
Daniel Dunbarf77ac862008-08-11 21:35:06 +00003417}
3418
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003419
3420// struct objc_module {
3421// unsigned long version;
3422// unsigned long size;
3423// const char *name;
3424// Symtab symtab;
3425// };
3426
3427// FIXME: Get from somewhere
3428static const int ModuleVersion = 7;
3429
3430void CGObjCMac::EmitModuleInfo() {
Duncan Sands9408c452009-05-09 07:08:47 +00003431 uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003432
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003433 std::vector<llvm::Constant*> Values(4);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003434 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
3435 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00003436 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003437 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003438 Values[3] = EmitModuleSymbols();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003439 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson08e25242009-07-27 22:29:56 +00003440 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003441 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbar58a29122009-03-09 22:18:41 +00003442 4, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003443}
3444
3445llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003446 unsigned NumClasses = DefinedClasses.size();
3447 unsigned NumCategories = DefinedCategories.size();
3448
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003449 // Return null if no symbols were defined.
3450 if (!NumClasses && !NumCategories)
Owen Andersonc9c88b42009-07-31 20:28:54 +00003451 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003452
3453 std::vector<llvm::Constant*> Values(5);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003454 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Andersonc9c88b42009-07-31 20:28:54 +00003455 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00003456 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3457 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003458
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003459 // The runtime expects exactly the list of defined classes followed
3460 // by the list of defined categories, in a single array.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003461 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003462 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00003463 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003464 ObjCTypes.Int8PtrTy);
3465 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003466 Symbols[NumClasses + i] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003467 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar86e253a2008-08-22 20:34:54 +00003468 ObjCTypes.Int8PtrTy);
3469
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003470 Values[4] =
Owen Anderson96e0fc72009-07-29 22:16:19 +00003471 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003472 NumClasses + NumCategories),
3473 Symbols);
3474
Nick Lewycky0d36dd22009-09-19 20:00:52 +00003475 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003476
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003477 llvm::GlobalVariable *GV =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003478 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3479 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003480 4, true);
Owen Anderson3c4972d2009-07-29 18:54:39 +00003481 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003482}
3483
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003484llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003485 const ObjCInterfaceDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00003486 LazySymbols.insert(ID->getIdentifier());
3487
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003488 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003489
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003490 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003491 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003492 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003493 ObjCTypes.ClassPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003494 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003495 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3496 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003497 4, true);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003498 }
3499
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00003500 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003501}
3502
Fariborz Jahanian03b29602010-06-17 19:56:20 +00003503llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3504 bool lvalue) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003505 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003506
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003507 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003508 llvm::Constant *Casted =
Owen Anderson3c4972d2009-07-29 18:54:39 +00003509 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003510 ObjCTypes.SelectorPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003511 Entry =
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003512 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3513 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbar0bf21992009-04-15 02:56:18 +00003514 4, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003515 }
3516
Fariborz Jahanian03b29602010-06-17 19:56:20 +00003517 if (lvalue)
3518 return Entry;
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00003519 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003520}
3521
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00003522llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003523 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003524
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003525 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003526 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003527 llvm::ConstantArray::get(VMContext,
3528 Ident->getNameStart()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003529 ((ObjCABI == 2) ?
3530 "__TEXT,__objc_classname,cstring_literals" :
3531 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003532 1, true);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003533
Owen Andersona1cf15f2009-07-14 23:10:40 +00003534 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00003535}
3536
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00003537llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
3538 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*>::iterator
3539 I = MethodDefinitions.find(MD);
3540 if (I != MethodDefinitions.end())
3541 return I->second;
3542
3543 if (MD->hasBody() && MD->getPCHLevel() > 0) {
3544 // MD isn't emitted yet because it comes from PCH.
3545 CGM.EmitTopLevelDecl(const_cast<ObjCMethodDecl*>(MD));
3546 assert(MethodDefinitions[MD] && "EmitTopLevelDecl didn't emit the method!");
3547 return MethodDefinitions[MD];
3548 }
3549
3550 return NULL;
3551}
3552
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00003553/// GetIvarLayoutName - Returns a unique constant for the given
3554/// ivar layout bitmap.
3555llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003556 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Andersonc9c88b42009-07-31 20:28:54 +00003557 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahaniand80d81b2009-03-05 19:17:31 +00003558}
3559
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003560void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003561 unsigned int BytePos,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003562 bool ForStrongLayout,
3563 bool &HasUnion) {
3564 const RecordDecl *RD = RT->getDecl();
3565 // FIXME - Use iterator.
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00003566 llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003567 const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003568 const llvm::StructLayout *RecLayout =
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003569 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003570
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003571 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3572 ForStrongLayout, HasUnion);
3573}
3574
Daniel Dunbar5a5a8032009-05-03 21:05:10 +00003575void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003576 const llvm::StructLayout *Layout,
3577 const RecordDecl *RD,
Chris Lattnerf1690852009-03-31 08:48:01 +00003578 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003579 unsigned int BytePos, bool ForStrongLayout,
3580 bool &HasUnion) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003581 bool IsUnion = (RD && RD->isUnion());
3582 uint64_t MaxUnionIvarSize = 0;
3583 uint64_t MaxSkippedUnionIvarSize = 0;
3584 FieldDecl *MaxField = 0;
3585 FieldDecl *MaxSkippedField = 0;
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003586 FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003587 uint64_t MaxFieldOffset = 0;
3588 uint64_t MaxSkippedFieldOffset = 0;
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003589 uint64_t LastBitfieldOrUnnamedOffset = 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003590
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003591 if (RecFields.empty())
3592 return;
Chris Lattnerf1690852009-03-31 08:48:01 +00003593 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3594 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3595
Chris Lattnerf1690852009-03-31 08:48:01 +00003596 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003597 FieldDecl *Field = RecFields[i];
Daniel Dunbare05cc982009-05-03 23:35:23 +00003598 uint64_t FieldOffset;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00003599 if (RD) {
Daniel Dunbarf8f8eba2010-04-14 17:02:21 +00003600 // Note that 'i' here is actually the field index inside RD of Field,
3601 // although this dependency is hidden.
3602 const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
Ken Dyckfb67ccd2011-04-14 00:43:09 +00003603 FieldOffset = RL.getFieldOffset(i) / ByteSizeInBits;
Anders Carlssonfc514ab2009-07-24 17:23:54 +00003604 } else
Daniel Dunbare05cc982009-05-03 23:35:23 +00003605 FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003606
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003607 // Skip over unnamed or bitfields
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003608 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003609 LastFieldBitfieldOrUnnamed = Field;
3610 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003611 continue;
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003612 }
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003613
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003614 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003615 QualType FQT = Field->getType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003616 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003617 if (FQT->isUnionType())
3618 HasUnion = true;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003619
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003620 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003621 BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003622 ForStrongLayout, HasUnion);
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003623 continue;
3624 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003625
Chris Lattnerf1690852009-03-31 08:48:01 +00003626 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003627 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003628 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003629 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003630 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003631 FQT = CArray->getElementType();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003632 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3633 const ConstantArrayType *CArray =
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003634 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003635 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003636 FQT = CArray->getElementType();
3637 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003638
3639 assert(!FQT->isUnionType() &&
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003640 "layout for array of unions not supported");
Fariborz Jahanianf96bdf42011-01-03 19:23:18 +00003641 if (FQT->isRecordType() && ElCount) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003642 int OldIndex = IvarsInfo.size() - 1;
3643 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003644
Ted Kremenek6217b802009-07-29 21:53:49 +00003645 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003646 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003647 ForStrongLayout, HasUnion);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003648
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003649 // Replicate layout information for each array element. Note that
3650 // one element is already done.
3651 uint64_t ElIx = 1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003652 for (int FirstIndex = IvarsInfo.size() - 1,
3653 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003654 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003655 for (int i = OldIndex+1; i <= FirstIndex; ++i)
3656 IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
3657 IvarsInfo[i].ivar_size));
3658 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
3659 SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
3660 SkipIvars[i].ivar_size));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003661 }
3662 continue;
3663 }
Fariborz Jahaniana5a10c32009-03-10 16:22:08 +00003664 }
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003665 // At this point, we are done with Record/Union and array there of.
3666 // For other arrays we are down to its element type.
John McCall0953e762009-09-24 19:53:00 +00003667 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar5e563dd2009-05-03 13:55:09 +00003668
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003669 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall0953e762009-09-24 19:53:00 +00003670 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3671 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00003672 if (IsUnion) {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003673 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar487993b2009-05-03 13:32:01 +00003674 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003675 MaxUnionIvarSize = UnionIvarSize;
3676 MaxField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003677 MaxFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003678 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00003679 } else {
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003680 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003681 FieldSize / WordSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003682 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003683 } else if ((ForStrongLayout &&
John McCall0953e762009-09-24 19:53:00 +00003684 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3685 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar487993b2009-05-03 13:32:01 +00003686 if (IsUnion) {
Mike Stumpf5408fe2009-05-16 07:57:57 +00003687 // FIXME: Why the asymmetry? We divide by word size in bits on other
3688 // side.
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003689 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar487993b2009-05-03 13:32:01 +00003690 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003691 MaxSkippedUnionIvarSize = UnionIvarSize;
3692 MaxSkippedField = Field;
Daniel Dunbar900c1982009-05-03 23:31:46 +00003693 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003694 }
Daniel Dunbar487993b2009-05-03 13:32:01 +00003695 } else {
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003696 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar25d583e2009-05-03 14:17:18 +00003697 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003698 FieldSize / ByteSizeInBits));
Fariborz Jahanian820e0202009-03-11 00:07:04 +00003699 }
3700 }
3701 }
Daniel Dunbard58edcb2009-05-03 14:10:34 +00003702
Argyrios Kyrtzidis0dc75092010-09-06 12:00:10 +00003703 if (LastFieldBitfieldOrUnnamed) {
3704 if (LastFieldBitfieldOrUnnamed->isBitField()) {
3705 // Last field was a bitfield. Must update skip info.
3706 Expr *BitWidth = LastFieldBitfieldOrUnnamed->getBitWidth();
3707 uint64_t BitFieldSize =
3708 BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
3709 GC_IVAR skivar;
3710 skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset;
3711 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
3712 + ((BitFieldSize % ByteSizeInBits) != 0);
3713 SkipIvars.push_back(skivar);
3714 } else {
3715 assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
3716 // Last field was unnamed. Must update skip info.
3717 unsigned FieldSize
3718 = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
3719 SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset,
3720 FieldSize / ByteSizeInBits));
3721 }
Fariborz Jahanian7fb16272009-04-21 18:33:06 +00003722 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003723
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003724 if (MaxField)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003725 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003726 MaxUnionIvarSize));
3727 if (MaxSkippedField)
Daniel Dunbar900c1982009-05-03 23:31:46 +00003728 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar8b2926c2009-05-03 13:44:42 +00003729 MaxSkippedUnionIvarSize));
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00003730}
3731
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003732/// BuildIvarLayoutBitmap - This routine is the horsework for doing all
3733/// the computations and returning the layout bitmap (for ivar or blocks) in
3734/// the given argument BitMap string container. Routine reads
3735/// two containers, IvarsInfo and SkipIvars which are assumed to be
3736/// filled already by the caller.
3737llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string& BitMap) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003738 unsigned int WordsToScan, WordsToSkip;
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00003739 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003740
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003741 // Build the string of skip/scan nibbles
Fariborz Jahanian8c2f2d12009-04-24 17:15:27 +00003742 llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003743 unsigned int WordSize =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003744 CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003745 if (IvarsInfo[0].ivar_bytepos == 0) {
3746 WordsToSkip = 0;
3747 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003748 } else {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003749 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3750 WordsToScan = IvarsInfo[0].ivar_size;
3751 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003752 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003753 unsigned int TailPrevGCObjC =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003754 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003755 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003756 // consecutive 'scanned' object pointers.
3757 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003758 } else {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003759 // Skip over 'gc'able object pointer which lay over each other.
3760 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
3761 continue;
3762 // Must skip over 1 or more words. We save current skip/scan values
3763 // and start a new pair.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003764 SKIP_SCAN SkScan;
3765 SkScan.skip = WordsToSkip;
3766 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003767 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003768
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003769 // Skip the hole.
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003770 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3771 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003772 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003773 WordsToSkip = 0;
3774 WordsToScan = IvarsInfo[i].ivar_size;
3775 }
3776 }
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003777 if (WordsToScan > 0) {
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003778 SKIP_SCAN SkScan;
3779 SkScan.skip = WordsToSkip;
3780 SkScan.scan = WordsToScan;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003781 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003782 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003783
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003784 if (!SkipIvars.empty()) {
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003785 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003786 int LastByteSkipped =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003787 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003788 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003789 int LastByteScanned =
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003790 IvarsInfo[LastIndex].ivar_bytepos +
3791 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003792 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramer54d76db2009-12-25 15:43:36 +00003793 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003794 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanianc8ce9c82009-03-12 22:50:49 +00003795 SKIP_SCAN SkScan;
3796 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3797 SkScan.scan = 0;
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003798 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003799 }
3800 }
3801 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3802 // as 0xMN.
Fariborz Jahanian81adc052009-04-24 16:17:09 +00003803 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003804 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003805 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3806 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3807 // 0xM0 followed by 0x0N detected.
3808 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3809 for (int j = i+1; j < SkipScan; j++)
3810 SkipScanIvars[j] = SkipScanIvars[j+1];
3811 --SkipScan;
3812 }
3813 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003814
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003815 // Generate the string.
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003816 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003817 unsigned char byte;
3818 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3819 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3820 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
3821 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003822
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003823 // first skip big.
3824 for (unsigned int ix = 0; ix < skip_big; ix++)
3825 BitMap += (unsigned char)(0xf0);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003826
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003827 // next (skip small, scan)
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003828 if (skip_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003829 byte = skip_small << 4;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003830 if (scan_big > 0) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003831 byte |= 0xf;
3832 --scan_big;
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003833 } else if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003834 byte |= scan_small;
3835 scan_small = 0;
3836 }
3837 BitMap += byte;
3838 }
3839 // next scan big
3840 for (unsigned int ix = 0; ix < scan_big; ix++)
3841 BitMap += (unsigned char)(0x0f);
3842 // last scan small
Daniel Dunbar31682fd2009-05-03 23:21:22 +00003843 if (scan_small) {
Fariborz Jahanian9397e1d2009-03-11 20:59:05 +00003844 byte = scan_small;
3845 BitMap += byte;
3846 }
3847 }
3848 // null terminate string.
Fariborz Jahanian667423a2009-03-25 22:36:49 +00003849 unsigned char zero = 0;
3850 BitMap += zero;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003851
3852 llvm::GlobalVariable * Entry =
3853 CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3854 llvm::ConstantArray::get(VMContext, BitMap.c_str()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003855 ((ObjCABI == 2) ?
3856 "__TEXT,__objc_classname,cstring_literals" :
3857 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003858 1, true);
3859 return getConstantGEP(VMContext, Entry, 0, 0);
3860}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003861
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003862/// BuildIvarLayout - Builds ivar layout bitmap for the class
3863/// implementation for the __strong or __weak case.
3864/// The layout map displays which words in ivar list must be skipped
3865/// and which must be scanned by GC (see below). String is built of bytes.
3866/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
3867/// of words to skip and right nibble is count of words to scan. So, each
3868/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
3869/// represented by a 0x00 byte which also ends the string.
3870/// 1. when ForStrongLayout is true, following ivars are scanned:
3871/// - id, Class
3872/// - object *
3873/// - __strong anything
3874///
3875/// 2. When ForStrongLayout is false, following ivars are scanned:
3876/// - __weak anything
3877///
3878llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
3879 const ObjCImplementationDecl *OMD,
3880 bool ForStrongLayout) {
3881 bool hasUnion = false;
3882
3883 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
3884 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
3885 return llvm::Constant::getNullValue(PtrTy);
3886
Fariborz Jahanian2c18bb72010-08-20 21:21:08 +00003887 llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003888 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
Fariborz Jahanian2c18bb72010-08-20 21:21:08 +00003889 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003890
Fariborz Jahanian2c18bb72010-08-20 21:21:08 +00003891 llvm::SmallVector<FieldDecl*, 32> RecFields;
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003892 for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
3893 RecFields.push_back(cast<FieldDecl>(Ivars[k]));
3894
3895 if (RecFields.empty())
3896 return llvm::Constant::getNullValue(PtrTy);
3897
3898 SkipIvars.clear();
3899 IvarsInfo.clear();
3900
3901 BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
3902 if (IvarsInfo.empty())
3903 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003904 // Sort on byte position in case we encounterred a union nested in
3905 // the ivar list.
3906 if (hasUnion && !IvarsInfo.empty())
3907 std::sort(IvarsInfo.begin(), IvarsInfo.end());
3908 if (hasUnion && !SkipIvars.empty())
3909 std::sort(SkipIvars.begin(), SkipIvars.end());
3910
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003911 std::string BitMap;
Fariborz Jahanianb8fd2eb2010-08-05 00:19:48 +00003912 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003913
3914 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003915 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian3d2ad662009-04-20 22:03:45 +00003916 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar4087f272010-08-17 22:39:59 +00003917 OMD->getClassInterface()->getName().data());
Fariborz Jahanian3d2ad662009-04-20 22:03:45 +00003918 const unsigned char *s = (unsigned char*)BitMap.c_str();
3919 for (unsigned i = 0; i < BitMap.size(); i++)
3920 if (!(s[i] & 0xf0))
3921 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3922 else
3923 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
3924 printf("\n");
3925 }
Fariborz Jahanian93ce50d2010-08-04 23:55:24 +00003926 return C;
Fariborz Jahaniand61a50a2009-03-05 22:39:55 +00003927}
3928
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003929llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003930 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3931
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003932 // FIXME: Avoid std::string copying.
3933 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003934 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Owen Anderson0032b272009-08-13 21:57:51 +00003935 llvm::ConstantArray::get(VMContext, Sel.getAsString()),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003936 ((ObjCABI == 2) ?
3937 "__TEXT,__objc_methname,cstring_literals" :
3938 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003939 1, true);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003940
Owen Andersona1cf15f2009-07-14 23:10:40 +00003941 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003942}
3943
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003944// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003945llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003946 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3947}
3948
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00003949llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel7794bb82009-03-04 18:21:39 +00003950 std::string TypeStr;
3951 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
3952
3953 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00003954
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003955 if (!Entry)
3956 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson0032b272009-08-13 21:57:51 +00003957 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003958 ((ObjCABI == 2) ?
3959 "__TEXT,__objc_methtype,cstring_literals" :
3960 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003961 1, true);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003962
Owen Andersona1cf15f2009-07-14 23:10:40 +00003963 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00003964}
3965
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003966llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003967 std::string TypeStr;
Daniel Dunbarc45ef602008-08-26 21:51:14 +00003968 CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
3969 TypeStr);
Devang Patel7794bb82009-03-04 18:21:39 +00003970
3971 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3972
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003973 if (!Entry)
3974 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson0032b272009-08-13 21:57:51 +00003975 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbaraf19ac42011-03-25 20:09:09 +00003976 ((ObjCABI == 2) ?
3977 "__TEXT,__objc_methtype,cstring_literals" :
3978 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003979 1, true);
Devang Patel7794bb82009-03-04 18:21:39 +00003980
Owen Andersona1cf15f2009-07-14 23:10:40 +00003981 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00003982}
3983
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003984// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00003985llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003986 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003987
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003988 if (!Entry)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00003989 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00003990 llvm::ConstantArray::get(VMContext,
3991 Ident->getNameStart()),
Daniel Dunbar63c5b502009-03-09 21:49:58 +00003992 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarb90bb002009-04-14 23:14:47 +00003993 1, true);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003994
Owen Andersona1cf15f2009-07-14 23:10:40 +00003995 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00003996}
3997
3998// FIXME: Merge into a single cstring creation function.
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00003999// FIXME: This Decl should be more precise.
Daniel Dunbar63c5b502009-03-09 21:49:58 +00004000llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004001CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4002 const Decl *Container) {
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00004003 std::string TypeStr;
4004 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00004005 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4006}
4007
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004008void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian56210f72009-01-21 23:34:32 +00004009 const ObjCContainerDecl *CD,
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004010 llvm::SmallVectorImpl<char> &Name) {
4011 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian679a5022009-01-10 21:06:09 +00004012 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004013 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4014 << '[' << CD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004015 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004016 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramer900fc632010-04-17 09:33:03 +00004017 OS << '(' << CID << ')';
Daniel Dunbarc575ce72009-10-19 01:21:19 +00004018 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00004019}
4020
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004021void CGObjCMac::FinishModule() {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004022 EmitModuleInfo();
4023
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004024 // Emit the dummy bodies for any protocols which were referenced but
4025 // never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004026 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerad64e022009-07-17 23:57:13 +00004027 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4028 if (I->second->hasInitializer())
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004029 continue;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004030
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004031 std::vector<llvm::Constant*> Values(5);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004032 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004033 Values[1] = GetClassName(I->first);
Owen Andersonc9c88b42009-07-31 20:28:54 +00004034 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004035 Values[3] = Values[4] =
Owen Andersonc9c88b42009-07-31 20:28:54 +00004036 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerad64e022009-07-17 23:57:13 +00004037 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson08e25242009-07-27 22:29:56 +00004038 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004039 Values));
Chris Lattnerad64e022009-07-17 23:57:13 +00004040 CGM.AddUsedGlobal(I->second);
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004041 }
4042
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004043 // Add assembler directives to add lazy undefined symbol references
4044 // for classes which are referenced but not defined. This is
4045 // important for correct linker interaction.
Daniel Dunbar33063492009-09-07 00:20:42 +00004046 //
4047 // FIXME: It would be nice if we had an LLVM construct for this.
4048 if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
4049 llvm::SmallString<256> Asm;
4050 Asm += CGM.getModule().getModuleInlineAsm();
4051 if (!Asm.empty() && Asm.back() != '\n')
4052 Asm += '\n';
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004053
Daniel Dunbar33063492009-09-07 00:20:42 +00004054 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbar33063492009-09-07 00:20:42 +00004055 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4056 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00004057 OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
4058 << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004059 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004060 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004061 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanianb9c5b3d2010-06-21 22:05:18 +00004062 }
4063
4064 for (size_t i = 0; i < DefinedCategoryNames.size(); ++i) {
4065 OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
4066 << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
4067 }
Chris Lattnerafd5eda2010-04-17 18:26:20 +00004068
Daniel Dunbar33063492009-09-07 00:20:42 +00004069 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00004070 }
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004071}
4072
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004073CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004074 : CGObjCCommonMac(cgm),
Mike Stump1eb44332009-09-09 15:08:12 +00004075 ObjCTypes(cgm) {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004076 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004077 ObjCABI = 2;
4078}
4079
Daniel Dunbarf77ac862008-08-11 21:35:06 +00004080/* *** */
4081
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004082ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004083 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004084 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4085 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004086
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004087 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004088 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004089 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00004090 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00004091 Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004092
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004093 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004094 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004095 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004096
Mike Stumpf5408fe2009-05-16 07:57:57 +00004097 // FIXME: It would be nice to unify this with the opaque type, so that the IR
4098 // comes out a bit cleaner.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004099 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
Owen Anderson96e0fc72009-07-29 22:16:19 +00004100 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004101
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004102 // I'm not sure I like this. The implicit coordination is a bit
4103 // gross. We should solve this in a reasonable fashion because this
4104 // is a pretty common task (match some runtime data structure with
4105 // an LLVM data structure).
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004106
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004107 // FIXME: This is leaked.
4108 // FIXME: Merge with rewriter code?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004109
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004110 // struct _objc_super {
4111 // id self;
4112 // Class cls;
4113 // }
Abramo Bagnara465d41b2010-05-11 21:36:43 +00004114 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00004115 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00004116 SourceLocation(), SourceLocation(),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004117 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004118 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004119 Ctx.getObjCIdType(), 0, 0, false));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004120 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004121 Ctx.getObjCClassType(), 0, 0, false));
Douglas Gregor838db382010-02-11 01:19:42 +00004122 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004123
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004124 SuperCTy = Ctx.getTagDeclType(RD);
4125 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004126
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004127 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004128 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4129
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004130 // struct _prop_t {
4131 // char *name;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004132 // char *attributes;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004133 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004134 PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004135 CGM.getModule().addTypeName("struct._prop_t",
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004136 PropertyTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004137
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004138 // struct _prop_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004139 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004140 // uint32_t count_of_properties;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004141 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004142 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004143 PropertyListTy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004144 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004145 llvm::ArrayType::get(PropertyTy, 0),
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004146 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004147 CGM.getModule().addTypeName("struct._prop_list_t",
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004148 PropertyListTy);
4149 // struct _prop_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004150 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004151
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004152 // struct _objc_method {
4153 // SEL _cmd;
4154 // char *method_type;
4155 // char *_imp;
4156 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004157 MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004158 Int8PtrTy,
4159 Int8PtrTy,
4160 NULL);
4161 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004162
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004163 // struct _objc_cache *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004164 CacheTy = llvm::OpaqueType::get(VMContext);
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004165 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004166 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004167}
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00004168
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004169ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004170 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004171 // struct _objc_method_description {
4172 // SEL name;
4173 // char *types;
4174 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004175 MethodDescriptionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004176 llvm::StructType::get(VMContext, SelectorPtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004177 Int8PtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004178 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004179 CGM.getModule().addTypeName("struct._objc_method_description",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004180 MethodDescriptionTy);
4181
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004182 // struct _objc_method_description_list {
4183 // int count;
4184 // struct _objc_method_description[1];
4185 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004186 MethodDescriptionListTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004187 llvm::StructType::get(VMContext, IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004188 llvm::ArrayType::get(MethodDescriptionTy, 0),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004189 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004190 CGM.getModule().addTypeName("struct._objc_method_description_list",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004191 MethodDescriptionListTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004192
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004193 // struct _objc_method_description_list *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004194 MethodDescriptionListPtrTy =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004195 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004196
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004197 // Protocol description structures
4198
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004199 // struct _objc_protocol_extension {
4200 // uint32_t size; // sizeof(struct _objc_protocol_extension)
4201 // struct _objc_method_description_list *optional_instance_methods;
4202 // struct _objc_method_description_list *optional_class_methods;
4203 // struct _objc_property_list *instance_properties;
4204 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004205 ProtocolExtensionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004206 llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004207 MethodDescriptionListPtrTy,
4208 MethodDescriptionListPtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004209 PropertyListPtrTy,
4210 NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004211 CGM.getModule().addTypeName("struct._objc_protocol_extension",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004212 ProtocolExtensionTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004213
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004214 // struct _objc_protocol_extension *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004215 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004216
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00004217 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004218
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004219 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
4220 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004221
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004222 const llvm::Type *T =
Mike Stump1eb44332009-09-09 15:08:12 +00004223 llvm::StructType::get(VMContext,
Owen Anderson47a434f2009-08-05 23:18:46 +00004224 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004225 LongTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004226 llvm::ArrayType::get(ProtocolTyHolder, 0),
Fariborz Jahanianee0af742009-01-21 22:04:16 +00004227 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004228 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
4229
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004230 // struct _objc_protocol {
4231 // struct _objc_protocol_extension *isa;
4232 // char *protocol_name;
4233 // struct _objc_protocol **_objc_protocol_list;
4234 // struct _objc_method_description_list *instance_methods;
4235 // struct _objc_method_description_list *class_methods;
4236 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004237 T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004238 Int8PtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004239 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004240 MethodDescriptionListPtrTy,
4241 MethodDescriptionListPtrTy,
4242 NULL);
4243 cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
4244
4245 ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004246 CGM.getModule().addTypeName("struct._objc_protocol_list",
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004247 ProtocolListTy);
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004248 // struct _objc_protocol_list *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004249 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00004250
4251 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004252 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004253 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004254
4255 // Class description structures
4256
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004257 // struct _objc_ivar {
4258 // char *ivar_name;
4259 // char *ivar_type;
4260 // int ivar_offset;
4261 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004262 IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004263 Int8PtrTy,
4264 IntTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004265 NULL);
4266 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
4267
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004268 // struct _objc_ivar_list *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004269 IvarListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004270 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004271 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004272
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004273 // struct _objc_method_list *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004274 MethodListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004275 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004276 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004277
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004278 // struct _objc_class_extension *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004279 ClassExtensionTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004280 llvm::StructType::get(VMContext, IntTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004281 Int8PtrTy,
4282 PropertyListPtrTy,
4283 NULL);
4284 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004285 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004286
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004287 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004288
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004289 // struct _objc_class {
4290 // Class isa;
4291 // Class super_class;
4292 // char *name;
4293 // long version;
4294 // long info;
4295 // long instance_size;
4296 // struct _objc_ivar_list *ivars;
4297 // struct _objc_method_list *methods;
4298 // struct _objc_cache *cache;
4299 // struct _objc_protocol_list *protocols;
4300 // char *ivar_layout;
4301 // struct _objc_class_ext *ext;
4302 // };
Owen Anderson47a434f2009-08-05 23:18:46 +00004303 T = llvm::StructType::get(VMContext,
4304 llvm::PointerType::getUnqual(ClassTyHolder),
Owen Anderson96e0fc72009-07-29 22:16:19 +00004305 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004306 Int8PtrTy,
4307 LongTy,
4308 LongTy,
4309 LongTy,
4310 IvarListPtrTy,
4311 MethodListPtrTy,
4312 CachePtrTy,
4313 ProtocolListPtrTy,
4314 Int8PtrTy,
4315 ClassExtensionPtrTy,
4316 NULL);
4317 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004318
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004319 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
4320 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004321 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004322
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004323 // struct _objc_category {
4324 // char *category_name;
4325 // char *class_name;
4326 // struct _objc_method_list *instance_method;
4327 // struct _objc_method_list *class_method;
4328 // uint32_t size; // sizeof(struct _objc_category)
4329 // struct _objc_property_list *instance_properties;// category's @property
4330 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004331 CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00004332 Int8PtrTy,
4333 MethodListPtrTy,
4334 MethodListPtrTy,
4335 ProtocolListPtrTy,
4336 IntTy,
4337 PropertyListPtrTy,
4338 NULL);
4339 CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
4340
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004341 // Global metadata structures
4342
Fariborz Jahanian10a42312009-01-21 00:39:53 +00004343 // struct _objc_symtab {
4344 // long sel_ref_cnt;
4345 // SEL *refs;
4346 // short cls_def_cnt;
4347 // short cat_def_cnt;
4348 // char *defs[cls_def_cnt + cat_def_cnt];
4349 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004350 SymtabTy = llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004351 SelectorPtrTy,
4352 ShortTy,
4353 ShortTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004354 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004355 NULL);
4356 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004357 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004358
Fariborz Jahaniandb286862009-01-22 00:37:21 +00004359 // struct _objc_module {
4360 // long version;
4361 // long size; // sizeof(struct _objc_module)
4362 // char *name;
4363 // struct _objc_symtab* symtab;
4364 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004365 ModuleTy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004366 llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00004367 LongTy,
4368 Int8PtrTy,
4369 SymtabPtrTy,
4370 NULL);
4371 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00004372
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004373
Mike Stumpf5408fe2009-05-16 07:57:57 +00004374 // FIXME: This is the size of the setjmp buffer and should be target
4375 // specific. 18 is what's used on 32-bit X86.
Anders Carlsson124526b2008-09-09 10:10:21 +00004376 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004377
Anders Carlsson124526b2008-09-09 10:10:21 +00004378 // Exceptions
Owen Anderson96e0fc72009-07-29 22:16:19 +00004379 const llvm::Type *StackPtrTy = llvm::ArrayType::get(
Benjamin Kramer3c0ef8c2009-10-13 10:07:13 +00004380 llvm::Type::getInt8PtrTy(VMContext), 4);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004381
4382 ExceptionDataTy =
Chris Lattner77b89b82010-06-27 07:15:29 +00004383 llvm::StructType::get(VMContext,
4384 llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
4385 SetJmpBufferSize),
Anders Carlsson124526b2008-09-09 10:10:21 +00004386 StackPtrTy, NULL);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004387 CGM.getModule().addTypeName("struct._objc_exception_data",
Anders Carlsson124526b2008-09-09 10:10:21 +00004388 ExceptionDataTy);
4389
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00004390}
4391
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004392ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump1eb44332009-09-09 15:08:12 +00004393 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004394 // struct _method_list_t {
4395 // uint32_t entsize; // sizeof(struct _objc_method)
4396 // uint32_t method_count;
4397 // struct _objc_method method_list[method_count];
4398 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004399 MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004400 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004401 llvm::ArrayType::get(MethodTy, 0),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004402 NULL);
4403 CGM.getModule().addTypeName("struct.__method_list_t",
4404 MethodListnfABITy);
4405 // struct method_list_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004406 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004407
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004408 // struct _protocol_t {
4409 // id isa; // NULL
4410 // const char * const protocol_name;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004411 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004412 // const struct method_list_t * const instance_methods;
4413 // const struct method_list_t * const class_methods;
4414 // const struct method_list_t *optionalInstanceMethods;
4415 // const struct method_list_t *optionalClassMethods;
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004416 // const struct _prop_list_t * properties;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004417 // const uint32_t size; // sizeof(struct _protocol_t)
4418 // const uint32_t flags; // = 0
4419 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004420
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004421 // Holder for struct _protocol_list_t *
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004422 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004423
Owen Anderson47a434f2009-08-05 23:18:46 +00004424 ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004425 Int8PtrTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004426 llvm::PointerType::getUnqual(
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004427 ProtocolListTyHolder),
4428 MethodListnfABIPtrTy,
4429 MethodListnfABIPtrTy,
4430 MethodListnfABIPtrTy,
4431 MethodListnfABIPtrTy,
4432 PropertyListPtrTy,
4433 IntTy,
4434 IntTy,
4435 NULL);
4436 CGM.getModule().addTypeName("struct._protocol_t",
4437 ProtocolnfABITy);
Daniel Dunbar948e2582009-02-15 07:36:20 +00004438
4439 // struct _protocol_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004440 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004441
Fariborz Jahanianda320092009-01-29 19:24:30 +00004442 // struct _protocol_list_t {
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004443 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar948e2582009-02-15 07:36:20 +00004444 // struct _protocol_t *[protocol_count];
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004445 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004446 ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004447 llvm::ArrayType::get(
Daniel Dunbar948e2582009-02-15 07:36:20 +00004448 ProtocolnfABIPtrTy, 0),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004449 NULL);
4450 CGM.getModule().addTypeName("struct._objc_protocol_list",
4451 ProtocolListnfABITy);
Daniel Dunbar948e2582009-02-15 07:36:20 +00004452 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004453 ProtocolListnfABITy);
4454
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004455 // struct _objc_protocol_list*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004456 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004457
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004458 // struct _ivar_t {
4459 // unsigned long int *offset; // pointer to ivar offset location
4460 // char *name;
4461 // char *type;
4462 // uint32_t alignment;
4463 // uint32_t size;
4464 // }
Mike Stump1eb44332009-09-09 15:08:12 +00004465 IvarnfABITy = llvm::StructType::get(VMContext,
Owen Anderson47a434f2009-08-05 23:18:46 +00004466 llvm::PointerType::getUnqual(LongTy),
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004467 Int8PtrTy,
4468 Int8PtrTy,
4469 IntTy,
4470 IntTy,
4471 NULL);
4472 CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004473
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004474 // struct _ivar_list_t {
4475 // uint32 entsize; // sizeof(struct _ivar_t)
4476 // uint32 count;
4477 // struct _iver_t list[count];
4478 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004479 IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004480 IntTy,
Owen Anderson96e0fc72009-07-29 22:16:19 +00004481 llvm::ArrayType::get(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004482 IvarnfABITy, 0),
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004483 NULL);
4484 CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004485
Owen Anderson96e0fc72009-07-29 22:16:19 +00004486 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004487
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004488 // struct _class_ro_t {
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00004489 // uint32_t const flags;
4490 // uint32_t const instanceStart;
4491 // uint32_t const instanceSize;
4492 // uint32_t const reserved; // only when building for 64bit targets
4493 // const uint8_t * const ivarLayout;
4494 // const char *const name;
4495 // const struct _method_list_t * const baseMethods;
4496 // const struct _objc_protocol_list *const baseProtocols;
4497 // const struct _ivar_list_t *const ivars;
4498 // const uint8_t * const weakIvarLayout;
4499 // const struct _prop_list_t * const properties;
4500 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004501
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004502 // FIXME. Add 'reserved' field in 64bit abi mode!
Owen Anderson47a434f2009-08-05 23:18:46 +00004503 ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004504 IntTy,
4505 IntTy,
4506 Int8PtrTy,
4507 Int8PtrTy,
4508 MethodListnfABIPtrTy,
4509 ProtocolListnfABIPtrTy,
4510 IvarListnfABIPtrTy,
4511 Int8PtrTy,
4512 PropertyListPtrTy,
4513 NULL);
4514 CGM.getModule().addTypeName("struct._class_ro_t",
4515 ClassRonfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004516
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004517 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
4518 std::vector<const llvm::Type*> Params;
4519 Params.push_back(ObjectPtrTy);
4520 Params.push_back(SelectorPtrTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004521 ImpnfABITy = llvm::PointerType::getUnqual(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004522 llvm::FunctionType::get(ObjectPtrTy, Params, false));
4523
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004524 // struct _class_t {
4525 // struct _class_t *isa;
4526 // struct _class_t * const superclass;
4527 // void *cache;
4528 // IMP *vtable;
4529 // struct class_ro_t *ro;
4530 // }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004531
Owen Anderson8c8f69e2009-08-13 23:27:53 +00004532 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Owen Andersona1cf15f2009-07-14 23:10:40 +00004533 ClassnfABITy =
Owen Anderson47a434f2009-08-05 23:18:46 +00004534 llvm::StructType::get(VMContext,
4535 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004536 llvm::PointerType::getUnqual(ClassTyHolder),
4537 CachePtrTy,
4538 llvm::PointerType::getUnqual(ImpnfABITy),
4539 llvm::PointerType::getUnqual(ClassRonfABITy),
4540 NULL);
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004541 CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4542
4543 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004544 ClassnfABITy);
4545
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004546 // LLVM for struct _class_t *
Owen Anderson96e0fc72009-07-29 22:16:19 +00004547 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004548
Fariborz Jahaniand55b6fc2009-01-23 01:46:23 +00004549 // struct _category_t {
4550 // const char * const name;
4551 // struct _class_t *const cls;
4552 // const struct _method_list_t * const instance_methods;
4553 // const struct _method_list_t * const class_methods;
4554 // const struct _protocol_list_t * const protocols;
4555 // const struct _prop_list_t * const properties;
Fariborz Jahanian45c2ba02009-01-23 17:41:22 +00004556 // }
Owen Anderson47a434f2009-08-05 23:18:46 +00004557 CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004558 ClassnfABIPtrTy,
Fariborz Jahanian45c2ba02009-01-23 17:41:22 +00004559 MethodListnfABIPtrTy,
4560 MethodListnfABIPtrTy,
4561 ProtocolListnfABIPtrTy,
4562 PropertyListPtrTy,
4563 NULL);
4564 CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004565
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004566 // New types for nonfragile abi messaging.
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004567 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4568 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004569
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004570 // MessageRefTy - LLVM for:
4571 // struct _message_ref_t {
4572 // IMP messenger;
4573 // SEL name;
4574 // };
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004575
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004576 // First the clang type for struct _message_ref_t
Abramo Bagnara465d41b2010-05-11 21:36:43 +00004577 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbardaa3ac52010-04-29 16:29:11 +00004578 Ctx.getTranslationUnitDecl(),
Abramo Bagnaraba877ad2011-03-09 14:09:51 +00004579 SourceLocation(), SourceLocation(),
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004580 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004581 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004582 Ctx.VoidPtrTy, 0, 0, false));
Abramo Bagnaraff676cb2011-03-08 08:55:46 +00004583 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidisa1d56622009-08-19 01:27:57 +00004584 Ctx.getObjCSelType(), 0, 0, false));
Douglas Gregor838db382010-02-11 01:19:42 +00004585 RD->completeDefinition();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004586
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00004587 MessageRefCTy = Ctx.getTagDeclType(RD);
4588 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4589 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004590
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004591 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson96e0fc72009-07-29 22:16:19 +00004592 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004593
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004594 // SuperMessageRefTy - LLVM for:
4595 // struct _super_message_ref_t {
4596 // SUPER_IMP messenger;
4597 // SEL name;
4598 // };
Owen Anderson47a434f2009-08-05 23:18:46 +00004599 SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004600 SelectorPtrTy,
4601 NULL);
4602 CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004603
Fariborz Jahanian2e4672b2009-02-03 23:49:23 +00004604 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004605 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4606
Daniel Dunbare588b992009-03-01 04:46:24 +00004607
4608 // struct objc_typeinfo {
4609 // const void** vtable; // objc_ehtype_vtable + 2
4610 // const char* name; // c++ typeinfo string
4611 // Class cls;
4612 // };
Owen Anderson47a434f2009-08-05 23:18:46 +00004613 EHTypeTy = llvm::StructType::get(VMContext,
4614 llvm::PointerType::getUnqual(Int8PtrTy),
Daniel Dunbare588b992009-03-01 04:46:24 +00004615 Int8PtrTy,
4616 ClassnfABIPtrTy,
4617 NULL);
Daniel Dunbar4ff36842009-03-02 06:08:11 +00004618 CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
Owen Anderson96e0fc72009-07-29 22:16:19 +00004619 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00004620}
4621
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004622llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004623 FinishNonFragileABIModule();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004624
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004625 return NULL;
4626}
4627
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004628void CGObjCNonFragileABIMac::AddModuleClassList(const
4629 std::vector<llvm::GlobalValue*>
4630 &Container,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004631 const char *SymbolName,
4632 const char *SectionName) {
4633 unsigned NumClasses = Container.size();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004634
Daniel Dunbar463b8762009-05-15 21:48:48 +00004635 if (!NumClasses)
4636 return;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004637
Daniel Dunbar463b8762009-05-15 21:48:48 +00004638 std::vector<llvm::Constant*> Symbols(NumClasses);
4639 for (unsigned i=0; i<NumClasses; i++)
Owen Anderson3c4972d2009-07-29 18:54:39 +00004640 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar463b8762009-05-15 21:48:48 +00004641 ObjCTypes.Int8PtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004642 llvm::Constant* Init =
Owen Anderson96e0fc72009-07-29 22:16:19 +00004643 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004644 NumClasses),
4645 Symbols);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004646
Daniel Dunbar463b8762009-05-15 21:48:48 +00004647 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00004648 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004649 llvm::GlobalValue::InternalLinkage,
4650 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00004651 SymbolName);
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004652 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Daniel Dunbar463b8762009-05-15 21:48:48 +00004653 GV->setSection(SectionName);
Chris Lattnerad64e022009-07-17 23:57:13 +00004654 CGM.AddUsedGlobal(GV);
Daniel Dunbar463b8762009-05-15 21:48:48 +00004655}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004656
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004657void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4658 // nonfragile abi has no module definition.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004659
Daniel Dunbar463b8762009-05-15 21:48:48 +00004660 // Build list of all implemented class addresses in array
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004661 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004662 AddModuleClassList(DefinedClasses,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004663 "\01L_OBJC_LABEL_CLASS_$",
4664 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004665
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004666 for (unsigned i = 0; i < DefinedClasses.size(); i++) {
4667 llvm::GlobalValue *IMPLGV = DefinedClasses[i];
4668 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4669 continue;
4670 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004671 }
4672
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004673 for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
4674 llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
4675 if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
4676 continue;
4677 IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
4678 }
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004679
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004680 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004681 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4682 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004683
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00004684 // Build list of all implemented category addresses in array
4685 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004686 AddModuleClassList(DefinedCategories,
Daniel Dunbar463b8762009-05-15 21:48:48 +00004687 "\01L_OBJC_LABEL_CATEGORY_$",
4688 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004689 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004690 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4691 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004692
Daniel Dunbarfce176b2010-04-25 20:39:01 +00004693 EmitImageInfo();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004694}
4695
John McCall944c8432011-05-14 03:10:52 +00004696/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
4697/// VTableDispatchMethods; false otherwise. What this means is that
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004698/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004699/// message dispatch call for all the rest.
John McCall944c8432011-05-14 03:10:52 +00004700bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
4701 // At various points we've experimented with using vtable-based
4702 // dispatch for all methods.
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004703 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
4704 default:
John McCall944c8432011-05-14 03:10:52 +00004705 llvm_unreachable("Invalid dispatch method!");
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004706 case CodeGenOptions::Legacy:
Fariborz Jahanian776dbf92010-04-19 17:53:30 +00004707 return false;
John McCall944c8432011-05-14 03:10:52 +00004708 case CodeGenOptions::NonLegacy:
4709 return true;
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004710 case CodeGenOptions::Mixed:
4711 break;
4712 }
4713
4714 // If so, see whether this selector is in the white-list of things which must
4715 // use the new dispatch convention. We lazily build a dense set for this.
John McCall944c8432011-05-14 03:10:52 +00004716 if (VTableDispatchMethods.empty()) {
4717 VTableDispatchMethods.insert(GetNullarySelector("alloc"));
4718 VTableDispatchMethods.insert(GetNullarySelector("class"));
4719 VTableDispatchMethods.insert(GetNullarySelector("self"));
4720 VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
4721 VTableDispatchMethods.insert(GetNullarySelector("length"));
4722 VTableDispatchMethods.insert(GetNullarySelector("count"));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004723
John McCall944c8432011-05-14 03:10:52 +00004724 // These are vtable-based if GC is disabled.
4725 // Optimistically use vtable dispatch for hybrid compiles.
4726 if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly) {
4727 VTableDispatchMethods.insert(GetNullarySelector("retain"));
4728 VTableDispatchMethods.insert(GetNullarySelector("release"));
4729 VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
4730 }
4731
4732 VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
4733 VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
4734 VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
4735 VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
4736 VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
4737 VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
4738 VTableDispatchMethods.insert(GetUnarySelector("isEqual"));
4739
4740 // These are vtable-based if GC is enabled.
4741 // Optimistically use vtable dispatch for hybrid compiles.
4742 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC) {
4743 VTableDispatchMethods.insert(GetNullarySelector("hash"));
4744 VTableDispatchMethods.insert(GetUnarySelector("addObject"));
4745
4746 // "countByEnumeratingWithState:objects:count"
4747 IdentifierInfo *KeyIdents[] = {
4748 &CGM.getContext().Idents.get("countByEnumeratingWithState"),
4749 &CGM.getContext().Idents.get("objects"),
4750 &CGM.getContext().Idents.get("count")
4751 };
4752 VTableDispatchMethods.insert(
4753 CGM.getContext().Selectors.getSelector(3, KeyIdents));
4754 }
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004755 }
Daniel Dunbarf643b9b2010-04-24 17:56:46 +00004756
John McCall944c8432011-05-14 03:10:52 +00004757 return VTableDispatchMethods.count(Sel);
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00004758}
4759
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004760// Metadata flags
4761enum MetaDataDlags {
4762 CLS = 0x0,
4763 CLS_META = 0x1,
4764 CLS_ROOT = 0x2,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004765 OBJC2_CLS_HIDDEN = 0x10,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004766 CLS_EXCEPTION = 0x20
4767};
4768/// BuildClassRoTInitializer - generate meta-data for:
4769/// struct _class_ro_t {
4770/// uint32_t const flags;
4771/// uint32_t const instanceStart;
4772/// uint32_t const instanceSize;
4773/// uint32_t const reserved; // only when building for 64bit targets
4774/// const uint8_t * const ivarLayout;
4775/// const char *const name;
4776/// const struct _method_list_t * const baseMethods;
Fariborz Jahanianda320092009-01-29 19:24:30 +00004777/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004778/// const struct _ivar_list_t *const ivars;
4779/// const uint8_t * const weakIvarLayout;
4780/// const struct _prop_list_t * const properties;
4781/// }
4782///
4783llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004784 unsigned flags,
4785 unsigned InstanceStart,
4786 unsigned InstanceSize,
4787 const ObjCImplementationDecl *ID) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004788 std::string ClassName = ID->getNameAsString();
4789 std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
Owen Anderson4a28d5d2009-07-24 23:12:58 +00004790 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4791 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4792 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004793 // FIXME. For 64bit targets add 0 here.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004794 Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4795 : BuildIvarLayout(ID, true);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004796 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004797 // const struct _method_list_t * const baseMethods;
4798 std::vector<llvm::Constant*> Methods;
4799 std::string MethodListName("\01l_OBJC_$_");
4800 if (flags & CLS_META) {
4801 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004802 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004803 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004804 // Class methods should always be defined.
4805 Methods.push_back(GetMethodConstant(*i));
4806 }
4807 } else {
4808 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004809 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004810 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004811 // Instance methods should always be defined.
4812 Methods.push_back(GetMethodConstant(*i));
4813 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004814 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004815 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004816 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004817
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004818 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4819 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004820
Fariborz Jahanian939abce2009-01-28 22:46:49 +00004821 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4822 if (llvm::Constant *C = GetMethodConstant(MD))
4823 Methods.push_back(C);
4824 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4825 if (llvm::Constant *C = GetMethodConstant(MD))
4826 Methods.push_back(C);
4827 }
4828 }
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004829 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004830 Values[ 5] = EmitMethodList(MethodListName,
4831 "__DATA, __objc_const", Methods);
4832
Fariborz Jahanianda320092009-01-29 19:24:30 +00004833 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4834 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004835 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004836 + OID->getName(),
Ted Kremenek53b94412010-09-01 01:21:15 +00004837 OID->all_referenced_protocol_begin(),
4838 OID->all_referenced_protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004839
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00004840 if (flags & CLS_META)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004841 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00004842 else
4843 Values[ 7] = EmitIvarList(ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004844 Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4845 : BuildIvarLayout(ID, false);
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00004846 if (flags & CLS_META)
Owen Andersonc9c88b42009-07-31 20:28:54 +00004847 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00004848 else
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00004849 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4850 ID, ID->getClassInterface(), ObjCTypes);
Owen Anderson08e25242009-07-27 22:29:56 +00004851 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004852 Values);
4853 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004854 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
4855 llvm::GlobalValue::InternalLinkage,
4856 Init,
4857 (flags & CLS_META) ?
4858 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4859 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00004860 CLASS_RO_GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004861 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00004862 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004863 return CLASS_RO_GV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00004864
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004865}
4866
4867/// BuildClassMetaData - This routine defines that to-level meta-data
4868/// for the given ClassName for:
4869/// struct _class_t {
4870/// struct _class_t *isa;
4871/// struct _class_t * const superclass;
4872/// void *cache;
4873/// IMP *vtable;
4874/// struct class_ro_t *ro;
4875/// }
4876///
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004877llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004878 std::string &ClassName,
4879 llvm::Constant *IsAGV,
4880 llvm::Constant *SuperClassGV,
4881 llvm::Constant *ClassRoGV,
4882 bool HiddenVisibility) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004883 std::vector<llvm::Constant*> Values(5);
4884 Values[0] = IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004885 Values[1] = SuperClassGV;
4886 if (!Values[1])
4887 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004888 Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
4889 Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4890 Values[4] = ClassRoGV; // &CLASS_RO_GV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004891 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004892 Values);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004893 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4894 GV->setInitializer(Init);
Fariborz Jahaniandd0db2a2009-01-31 01:07:39 +00004895 GV->setSection("__DATA, __objc_data");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00004896 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00004897 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004898 if (HiddenVisibility)
4899 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004900 return GV;
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004901}
4902
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004903bool
Fariborz Jahanianecfbdcb2009-05-21 01:03:45 +00004904CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00004905 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar74d4b122009-05-15 22:33:15 +00004906}
4907
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00004908void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbarb02532a2009-04-19 23:41:48 +00004909 uint32_t &InstanceStart,
4910 uint32_t &InstanceSize) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004911 const ASTRecordLayout &RL =
Daniel Dunbarb4c79e02009-05-04 21:26:30 +00004912 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004913
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00004914 // InstanceSize is really instance end.
Ken Dyckec299032011-02-11 02:20:09 +00004915 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar6e8575b2009-05-04 23:23:09 +00004916
4917 // If there are no fields, the start is the same as the end.
4918 if (!RL.getFieldCount())
4919 InstanceStart = InstanceSize;
4920 else
Ken Dyckfb67ccd2011-04-14 00:43:09 +00004921 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbarb02532a2009-04-19 23:41:48 +00004922}
4923
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004924void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
4925 std::string ClassName = ID->getNameAsString();
4926 if (!ObjCEmptyCacheVar) {
4927 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004928 CGM.getModule(),
4929 ObjCTypes.CacheTy,
4930 false,
4931 llvm::GlobalValue::ExternalLinkage,
4932 0,
4933 "_objc_empty_cache");
4934
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004935 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004936 CGM.getModule(),
4937 ObjCTypes.ImpnfABITy,
4938 false,
4939 llvm::GlobalValue::ExternalLinkage,
4940 0,
4941 "_objc_empty_vtable");
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00004942 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004943 assert(ID->getClassInterface() &&
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004944 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbar6c1aac82009-04-20 20:18:54 +00004945 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004946 uint32_t InstanceStart =
Duncan Sands9408c452009-05-09 07:08:47 +00004947 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004948 uint32_t InstanceSize = InstanceStart;
4949 uint32_t flags = CLS_META;
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00004950 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4951 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004952
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004953 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004954
4955 bool classIsHidden =
John McCall1fb0caa2010-10-22 21:05:15 +00004956 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004957 if (classIsHidden)
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004958 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00004959 if (ID->getNumIvarInitializers())
4960 flags |= eClassFlags_ABI2_HasCXXStructors;
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004961 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004962 // class is root
4963 flags |= CLS_ROOT;
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00004964 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004965 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004966 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004967 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004968 const ObjCInterfaceDecl *Root = ID->getClassInterface();
4969 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4970 Root = Super;
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004971 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004972 if (Root->isWeakImported())
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004973 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00004974 // work on super class metadata symbol.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004975 std::string SuperClassName =
Fariborz Jahanian0e93d252009-12-01 18:25:24 +00004976 ObjCMetaClassName +
4977 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian0f902942009-04-14 18:41:56 +00004978 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00004979 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004980 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian058a1b72009-01-24 20:21:50 +00004981 }
4982 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4983 InstanceStart,
4984 InstanceSize,ID);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004985 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00004986 llvm::GlobalVariable *MetaTClass =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004987 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4988 classIsHidden);
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00004989 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00004990
Fariborz Jahanian84394a52009-01-24 21:21:53 +00004991 // Metadata for the class
4992 flags = CLS;
Fariborz Jahaniancf555162009-01-31 00:59:10 +00004993 if (classIsHidden)
Fariborz Jahanian493dab72009-01-26 21:38:32 +00004994 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian109dfc62010-04-28 21:28:56 +00004995 if (ID->getNumIvarInitializers())
4996 flags |= eClassFlags_ABI2_HasCXXStructors;
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004997
Douglas Gregor68584ed2009-06-18 16:11:24 +00004998 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00004999 flags |= CLS_EXCEPTION;
5000
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005001 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005002 flags |= CLS_ROOT;
5003 SuperClassGV = 0;
Chris Lattnerb7b58b12009-04-19 06:02:28 +00005004 } else {
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005005 // Has a root. Current class is not a root.
Fariborz Jahanianfab98c42009-02-26 18:23:47 +00005006 std::string RootClassName =
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005007 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005008 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005009 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahaniana03d0dd2009-11-17 21:37:35 +00005010 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005011 }
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005012 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005013 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00005014 InstanceStart,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005015 InstanceSize,
Fariborz Jahanianf6a077e2009-01-24 23:43:01 +00005016 ID);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005017
Fariborz Jahanian84394a52009-01-24 21:21:53 +00005018 TClassName = ObjCClassName + ClassName;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005019 llvm::GlobalVariable *ClassMD =
Fariborz Jahaniancf555162009-01-31 00:59:10 +00005020 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5021 classIsHidden);
Fariborz Jahanianf87a0cc2009-01-30 20:55:31 +00005022 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005023
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005024 // Determine if this class is also "non-lazy".
5025 if (ImplementationIsNonLazy(ID))
5026 DefinedNonLazyClasses.push_back(ClassMD);
5027
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00005028 // Force the definition of the EHType if necessary.
5029 if (flags & CLS_EXCEPTION)
5030 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00005031 // Make sure method definition entries are all clear for next implementation.
5032 MethodDefinitions.clear();
Fariborz Jahanianaa23b572009-01-23 23:53:38 +00005033}
5034
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005035/// GenerateProtocolRef - This routine is called to generate code for
5036/// a protocol reference expression; as in:
5037/// @code
5038/// @protocol(Proto1);
5039/// @endcode
5040/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
5041/// which will hold address of the protocol meta-data.
5042///
5043llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005044 const ObjCProtocolDecl *PD) {
5045
Fariborz Jahanian960cd062009-04-10 18:47:34 +00005046 // This routine is called for @protocol only. So, we must build definition
5047 // of protocol's meta-data (not a reference to it!)
5048 //
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005049 llvm::Constant *Init =
5050 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5051 ObjCTypes.ExternalProtocolPtrTy);
5052
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005053 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar4087f272010-08-17 22:39:59 +00005054 ProtocolName += PD->getName();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005055
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005056 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5057 if (PTGV)
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005058 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005059 PTGV = new llvm::GlobalVariable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005060 CGM.getModule(),
5061 Init->getType(), false,
5062 llvm::GlobalValue::WeakAnyLinkage,
5063 Init,
5064 ProtocolName);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005065 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5066 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005067 CGM.AddUsedGlobal(PTGV);
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005068 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005069}
5070
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005071/// GenerateCategory - Build metadata for a category implementation.
5072/// struct _category_t {
5073/// const char * const name;
5074/// struct _class_t *const cls;
5075/// const struct _method_list_t * const instance_methods;
5076/// const struct _method_list_t * const class_methods;
5077/// const struct _protocol_list_t * const protocols;
5078/// const struct _prop_list_t * const properties;
5079/// }
5080///
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005081void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005082 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005083 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005084 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5085 "_$_" + OCD->getNameAsString());
5086 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005087 Interface->getNameAsString());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005088
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005089 std::vector<llvm::Constant*> Values(6);
5090 Values[0] = GetClassName(OCD->getIdentifier());
5091 // meta-class entry symbol
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005092 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005093 if (Interface->isWeakImported())
Fariborz Jahanian2cdcc4c2009-11-17 22:02:21 +00005094 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5095
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005096 Values[1] = ClassGV;
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005097 std::vector<llvm::Constant*> Methods;
5098 std::string MethodListName(Prefix);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005099 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005100 "_$_" + OCD->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005101
5102 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005103 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005104 // Instance methods should always be defined.
5105 Methods.push_back(GetMethodConstant(*i));
5106 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005107
5108 Values[2] = EmitMethodList(MethodListName,
5109 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005110 Methods);
5111
5112 MethodListName = Prefix;
5113 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5114 OCD->getNameAsString();
5115 Methods.clear();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005116 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005117 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005118 // Class methods should always be defined.
5119 Methods.push_back(GetMethodConstant(*i));
5120 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005121
5122 Values[3] = EmitMethodList(MethodListName,
5123 "__DATA, __objc_const",
Fariborz Jahanianf6317dd2009-01-26 22:58:07 +00005124 Methods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005125 const ObjCCategoryDecl *Category =
Fariborz Jahanian5de14dc2009-01-28 22:18:42 +00005126 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005127 if (Category) {
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005128 llvm::SmallString<256> ExtName;
5129 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5130 << OCD->getName();
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005131 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005132 + Interface->getName() + "_$_"
5133 + Category->getName(),
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005134 Category->protocol_begin(),
5135 Category->protocol_end());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005136 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5137 OCD, Category, ObjCTypes);
Mike Stumpb3589f42009-07-30 22:28:39 +00005138 } else {
Owen Andersonc9c88b42009-07-31 20:28:54 +00005139 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5140 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian943ed6f2009-02-13 17:52:22 +00005141 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005142
5143 llvm::Constant *Init =
5144 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005145 Values);
5146 llvm::GlobalVariable *GCATV
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005147 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005148 false,
5149 llvm::GlobalValue::InternalLinkage,
5150 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005151 ExtCatName);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005152 GCATV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005153 CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005154 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerad64e022009-07-17 23:57:13 +00005155 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005156 DefinedCategories.push_back(GCATV);
Daniel Dunbar74d4b122009-05-15 22:33:15 +00005157
5158 // Determine if this category is also "non-lazy".
5159 if (ImplementationIsNonLazy(OCD))
5160 DefinedNonLazyCategories.push_back(GCATV);
Fariborz Jahanian64089ce2011-04-22 22:02:28 +00005161 // method definition entries must be clear for next implementation.
5162 MethodDefinitions.clear();
Fariborz Jahanianeb062d92009-01-26 18:32:24 +00005163}
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005164
5165/// GetMethodConstant - Return a struct objc_method constant for the
5166/// given method if it has been defined. The result is null if the
5167/// method has not been defined. The return value has type MethodPtrTy.
5168llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005169 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis9d50c062010-08-09 10:54:20 +00005170 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005171 if (!Fn)
5172 return 0;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005173
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005174 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005175 Method[0] =
Owen Anderson3c4972d2009-07-29 18:54:39 +00005176 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005177 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005178 Method[1] = GetMethodVarType(MD);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005179 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005180 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005181}
5182
5183/// EmitMethodList - Build meta-data for method declarations
5184/// struct _method_list_t {
5185/// uint32_t entsize; // sizeof(struct _objc_method)
5186/// uint32_t method_count;
5187/// struct _objc_method method_list[method_count];
5188/// }
5189///
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005190llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
5191 const char *Section,
5192 const ConstantVector &Methods) {
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005193 // Return null for empty list.
5194 if (Methods.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00005195 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005196
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005197 std::vector<llvm::Constant*> Values(3);
5198 // sizeof(struct _objc_method)
Duncan Sands9408c452009-05-09 07:08:47 +00005199 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005200 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005201 // method_count
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005202 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00005203 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005204 Methods.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00005205 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005206 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005207
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005208 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005209 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005210 llvm::GlobalValue::InternalLinkage,
5211 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005212 Name);
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005213 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005214 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005215 GV->setSection(Section);
Chris Lattnerad64e022009-07-17 23:57:13 +00005216 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005217 return llvm::ConstantExpr::getBitCast(GV,
Fariborz Jahanian493dab72009-01-26 21:38:32 +00005218 ObjCTypes.MethodListnfABIPtrTy);
5219}
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005220
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005221/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5222/// the given ivar.
Daniel Dunbare83be122010-04-02 21:14:02 +00005223llvm::GlobalVariable *
5224CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5225 const ObjCIvarDecl *Ivar) {
5226 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbara81419d2009-05-05 00:36:57 +00005227 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregor6ab35242009-04-09 21:40:53 +00005228 '.' + Ivar->getNameAsString();
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005229 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005230 CGM.getModule().getGlobalVariable(Name);
5231 if (!IvarOffsetGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005232 IvarOffsetGV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005233 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005234 false,
5235 llvm::GlobalValue::ExternalLinkage,
5236 0,
Owen Anderson1c431b32009-07-08 19:05:04 +00005237 Name);
Fariborz Jahanianed157d32009-02-10 20:21:06 +00005238 return IvarOffsetGV;
5239}
5240
Daniel Dunbare83be122010-04-02 21:14:02 +00005241llvm::Constant *
5242CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5243 const ObjCIvarDecl *Ivar,
5244 unsigned long int Offset) {
Daniel Dunbar737c5022009-04-19 00:44:02 +00005245 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005246 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar737c5022009-04-19 00:44:02 +00005247 Offset));
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005248 IvarOffsetGV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005249 CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbar737c5022009-04-19 00:44:02 +00005250
Mike Stumpf5408fe2009-05-16 07:57:57 +00005251 // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
5252 // well (i.e., in ObjCIvarOffsetVariable).
Daniel Dunbar737c5022009-04-19 00:44:02 +00005253 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5254 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall1fb0caa2010-10-22 21:05:15 +00005255 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian2fa5a272009-01-28 01:36:42 +00005256 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar04d40782009-04-14 06:00:08 +00005257 else
Fariborz Jahanian77c9fd22009-04-06 18:30:00 +00005258 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendling1f382512011-05-04 21:37:25 +00005259 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005260 return IvarOffsetGV;
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005261}
5262
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005263/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar11394522009-04-18 08:51:00 +00005264/// implementation. The return value has type
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005265/// IvarListnfABIPtrTy.
5266/// struct _ivar_t {
5267/// unsigned long int *offset; // pointer to ivar offset location
5268/// char *name;
5269/// char *type;
5270/// uint32_t alignment;
5271/// uint32_t size;
5272/// }
5273/// struct _ivar_list_t {
5274/// uint32 entsize; // sizeof(struct _ivar_t)
5275/// uint32 count;
5276/// struct _iver_t list[count];
5277/// }
5278///
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00005279
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005280llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005281 const ObjCImplementationDecl *ID) {
5282
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005283 std::vector<llvm::Constant*> Ivars, Ivar(5);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005284
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005285 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5286 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005287
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005288 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005289
Daniel Dunbar91636d62009-04-20 00:33:43 +00005290 // Collect declared and synthesized ivars in a small vector.
Fariborz Jahanian18191882009-03-31 18:11:23 +00005291 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00005292 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005293
Daniel Dunbar3e5f0d82009-04-20 06:54:31 +00005294 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
5295 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian8e6ac1d2009-06-04 01:19:09 +00005296 // Ignore unnamed bit-fields.
5297 if (!IVD->getDeclName())
5298 continue;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005299 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar9f89f2b2009-05-03 12:57:56 +00005300 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00005301 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5302 Ivar[2] = GetMethodVarType(IVD);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005303 const llvm::Type *FieldTy =
Daniel Dunbar3fea0c02009-04-22 08:22:17 +00005304 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Duncan Sands9408c452009-05-09 07:08:47 +00005305 unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005306 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005307 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005308 Align = llvm::Log2_32(Align);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005309 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbar91636d62009-04-20 00:33:43 +00005310 // NOTE. Size of a bitfield does not match gcc's, because of the
5311 // way bitfields are treated special in each. But I am told that
5312 // 'size' for bitfield ivars is ignored by the runtime so it does
5313 // not matter. If it matters, there is enough info to get the
5314 // bitfield right!
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005315 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson08e25242009-07-27 22:29:56 +00005316 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005317 }
5318 // Return null for empty list.
5319 if (Ivars.empty())
Owen Andersonc9c88b42009-07-31 20:28:54 +00005320 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005321 std::vector<llvm::Constant*> Values(3);
Duncan Sands9408c452009-05-09 07:08:47 +00005322 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005323 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
5324 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson96e0fc72009-07-29 22:16:19 +00005325 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005326 Ivars.size());
Owen Anderson7db6d832009-07-28 18:33:04 +00005327 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005328 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005329 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5330 llvm::GlobalVariable *GV =
Owen Anderson1c431b32009-07-08 19:05:04 +00005331 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian98abf4b2009-01-27 19:38:51 +00005332 llvm::GlobalValue::InternalLinkage,
5333 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005334 Prefix + OID->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005335 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005336 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian1bf0afb2009-01-28 01:05:23 +00005337 GV->setSection("__DATA, __objc_const");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005338
Chris Lattnerad64e022009-07-17 23:57:13 +00005339 CGM.AddUsedGlobal(GV);
Owen Anderson3c4972d2009-07-29 18:54:39 +00005340 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005341}
5342
5343llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005344 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005345 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005346
Fariborz Jahanianda320092009-01-29 19:24:30 +00005347 if (!Entry) {
5348 // We use the initializer as a marker of whether this is a forward
5349 // reference or not. At module finalization we add the empty
5350 // contents for protocols which were referenced but never defined.
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005351 Entry =
5352 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5353 llvm::GlobalValue::ExternalLinkage,
5354 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005355 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanianda320092009-01-29 19:24:30 +00005356 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00005357 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005358
Fariborz Jahanianda320092009-01-29 19:24:30 +00005359 return Entry;
5360}
5361
5362/// GetOrEmitProtocol - Generate the protocol meta-data:
5363/// @code
5364/// struct _protocol_t {
5365/// id isa; // NULL
5366/// const char * const protocol_name;
5367/// const struct _protocol_list_t * protocol_list; // super protocols
5368/// const struct method_list_t * const instance_methods;
5369/// const struct method_list_t * const class_methods;
5370/// const struct method_list_t *optionalInstanceMethods;
5371/// const struct method_list_t *optionalClassMethods;
5372/// const struct _prop_list_t * properties;
5373/// const uint32_t size; // sizeof(struct _protocol_t)
5374/// const uint32_t flags; // = 0
5375/// }
5376/// @endcode
5377///
5378
5379llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005380 const ObjCProtocolDecl *PD) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005381 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005382
Fariborz Jahanianda320092009-01-29 19:24:30 +00005383 // Early exit if a defining object has already been generated.
5384 if (Entry && Entry->hasInitializer())
5385 return Entry;
5386
Fariborz Jahanianda320092009-01-29 19:24:30 +00005387 // Construct method lists.
5388 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5389 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005390 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005391 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005392 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005393 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005394 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5395 OptInstanceMethods.push_back(C);
5396 } else {
5397 InstanceMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005398 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00005399 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005400
5401 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +00005402 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005403 ObjCMethodDecl *MD = *i;
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005404 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005405 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5406 OptClassMethods.push_back(C);
5407 } else {
5408 ClassMethods.push_back(C);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005409 }
Fariborz Jahanianda320092009-01-29 19:24:30 +00005410 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005411
Fariborz Jahanianda320092009-01-29 19:24:30 +00005412 std::vector<llvm::Constant*> Values(10);
5413 // isa is NULL
Owen Andersonc9c88b42009-07-31 20:28:54 +00005414 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005415 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005416 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5417 PD->protocol_begin(),
5418 PD->protocol_end());
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005419
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005420 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005421 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005422 "__DATA, __objc_const",
5423 InstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005424 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005425 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005426 "__DATA, __objc_const",
5427 ClassMethods);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005428 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005429 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005430 "__DATA, __objc_const",
5431 OptInstanceMethods);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005432 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005433 + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005434 "__DATA, __objc_const",
5435 OptClassMethods);
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005436 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanianda320092009-01-29 19:24:30 +00005437 0, PD, ObjCTypes);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005438 uint32_t Size =
Duncan Sands9408c452009-05-09 07:08:47 +00005439 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005440 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Andersonc9c88b42009-07-31 20:28:54 +00005441 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005442 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanianda320092009-01-29 19:24:30 +00005443 Values);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005444
Fariborz Jahanianda320092009-01-29 19:24:30 +00005445 if (Entry) {
5446 // Already created, fix the linkage and update the initializer.
Mike Stump286acbd2009-03-07 16:33:28 +00005447 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005448 Entry->setInitializer(Init);
5449 } else {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005450 Entry =
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005451 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
5452 false, llvm::GlobalValue::WeakAnyLinkage, Init,
5453 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005454 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005455 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanianda320092009-01-29 19:24:30 +00005456 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanianda320092009-01-29 19:24:30 +00005457 }
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005458 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005459 CGM.AddUsedGlobal(Entry);
5460
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005461 // Use this protocol meta-data to build protocol list table in section
5462 // __DATA, __objc_protolist
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005463 llvm::GlobalVariable *PTGV =
5464 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
5465 false, llvm::GlobalValue::WeakAnyLinkage, Entry,
5466 "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005467 PTGV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005468 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbar0bf21992009-04-15 02:56:18 +00005469 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian8448c2c2009-01-29 20:10:59 +00005470 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerad64e022009-07-17 23:57:13 +00005471 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005472 return Entry;
5473}
5474
5475/// EmitProtocolList - Generate protocol list meta-data:
5476/// @code
5477/// struct _protocol_list_t {
5478/// long protocol_count; // Note, this is 32/64 bit
5479/// struct _protocol_t[protocol_count];
5480/// }
5481/// @endcode
5482///
5483llvm::Constant *
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005484CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
5485 ObjCProtocolDecl::protocol_iterator begin,
5486 ObjCProtocolDecl::protocol_iterator end) {
Fariborz Jahanianda320092009-01-29 19:24:30 +00005487 std::vector<llvm::Constant*> ProtocolRefs;
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005488
Fariborz Jahanianda320092009-01-29 19:24:30 +00005489 // Just return null for empty protocol lists
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005490 if (begin == end)
Owen Andersonc9c88b42009-07-31 20:28:54 +00005491 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005492
Daniel Dunbar948e2582009-02-15 07:36:20 +00005493 // FIXME: We shouldn't need to do this lookup here, should we?
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005494 llvm::SmallString<256> TmpName;
5495 Name.toVector(TmpName);
5496 llvm::GlobalVariable *GV =
5497 CGM.getModule().getGlobalVariable(TmpName.str(), true);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005498 if (GV)
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00005499 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005500
Daniel Dunbar948e2582009-02-15 07:36:20 +00005501 for (; begin != end; ++begin)
5502 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5503
Fariborz Jahanianda320092009-01-29 19:24:30 +00005504 // This list is null terminated.
Owen Andersonc9c88b42009-07-31 20:28:54 +00005505 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005506 ObjCTypes.ProtocolnfABIPtrTy));
5507
Fariborz Jahanianda320092009-01-29 19:24:30 +00005508 std::vector<llvm::Constant*> Values(2);
Owen Andersona1cf15f2009-07-14 23:10:40 +00005509 Values[0] =
Owen Anderson4a28d5d2009-07-24 23:12:58 +00005510 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005511 Values[1] =
Owen Anderson7db6d832009-07-28 18:33:04 +00005512 llvm::ConstantArray::get(
Owen Anderson96e0fc72009-07-29 22:16:19 +00005513 llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005514 ProtocolRefs.size()),
5515 ProtocolRefs);
5516
Nick Lewycky0d36dd22009-09-19 20:00:52 +00005517 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Owen Anderson1c431b32009-07-08 19:05:04 +00005518 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanianda320092009-01-29 19:24:30 +00005519 llvm::GlobalValue::InternalLinkage,
5520 Init,
Owen Anderson1c431b32009-07-08 19:05:04 +00005521 Name);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005522 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian09796d62009-01-31 02:43:27 +00005523 GV->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005524 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Chris Lattnerad64e022009-07-17 23:57:13 +00005525 CGM.AddUsedGlobal(GV);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005526 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar948e2582009-02-15 07:36:20 +00005527 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanianda320092009-01-29 19:24:30 +00005528}
5529
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005530/// GetMethodDescriptionConstant - This routine build following meta-data:
5531/// struct _objc_method {
5532/// SEL _cmd;
5533/// char *method_type;
5534/// char *_imp;
5535/// }
5536
5537llvm::Constant *
5538CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
5539 std::vector<llvm::Constant*> Desc(3);
Owen Andersona1cf15f2009-07-14 23:10:40 +00005540 Desc[0] =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005541 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5542 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005543 Desc[1] = GetMethodVarType(MD);
Fariborz Jahanian8cfd3972009-01-30 18:58:59 +00005544 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Andersonc9c88b42009-07-31 20:28:54 +00005545 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson08e25242009-07-27 22:29:56 +00005546 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahanian3819a0b2009-01-30 00:46:37 +00005547}
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005548
5549/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
5550/// This code gen. amounts to generating code for:
5551/// @code
5552/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
5553/// @encode
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005554///
Fariborz Jahanian598d3f62009-02-03 19:03:09 +00005555LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall506b57e2010-05-17 21:00:27 +00005556 CodeGen::CodeGenFunction &CGF,
5557 QualType ObjectTy,
5558 llvm::Value *BaseValue,
5559 const ObjCIvarDecl *Ivar,
5560 unsigned CVRQualifiers) {
5561 ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar97776872009-04-22 07:32:20 +00005562 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5563 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian45012a72009-02-03 00:09:52 +00005564}
5565
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00005566llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005567 CodeGen::CodeGenFunction &CGF,
5568 const ObjCInterfaceDecl *Interface,
5569 const ObjCIvarDecl *Ivar) {
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005570 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanianf63aa3f2009-02-10 19:02:04 +00005571}
5572
John McCallb1e81442011-05-13 23:16:18 +00005573static void appendSelectorForMessageRefTable(std::string &buffer,
5574 Selector selector) {
5575 if (selector.isUnarySelector()) {
5576 buffer += selector.getNameForSlot(0);
5577 return;
5578 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005579
John McCallb1e81442011-05-13 23:16:18 +00005580 for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
5581 buffer += selector.getNameForSlot(i);
5582 buffer += '_';
5583 }
5584}
5585
John McCall944c8432011-05-14 03:10:52 +00005586/// Emit a "v-table" message send. We emit a weak hidden-visibility
5587/// struct, initially containing the selector pointer and a pointer to
5588/// a "fixup" variant of the appropriate objc_msgSend. To call, we
5589/// load and call the function pointer, passing the address of the
5590/// struct as the second parameter. The runtime determines whether
5591/// the selector is currently emitted using vtable dispatch; if so, it
5592/// substitutes a stub function which simply tail-calls through the
5593/// appropriate vtable slot, and if not, it substitues a stub function
5594/// which tail-calls objc_msgSend. Both stubs adjust the selector
5595/// argument to correctly point to the selector.
5596RValue
5597CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF,
5598 ReturnValueSlot returnSlot,
5599 QualType resultType,
5600 Selector selector,
5601 llvm::Value *arg0,
5602 QualType arg0Type,
5603 bool isSuper,
5604 const CallArgList &formalArgs,
5605 const ObjCMethodDecl *method) {
John McCallb1e81442011-05-13 23:16:18 +00005606 // Compute the actual arguments.
5607 CallArgList args;
5608
John McCall944c8432011-05-14 03:10:52 +00005609 // First argument: the receiver / super-call structure.
John McCallb1e81442011-05-13 23:16:18 +00005610 if (!isSuper)
John McCall944c8432011-05-14 03:10:52 +00005611 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
5612 args.add(RValue::get(arg0), arg0Type);
John McCallb1e81442011-05-13 23:16:18 +00005613
John McCall944c8432011-05-14 03:10:52 +00005614 // Second argument: a pointer to the message ref structure. Leave
5615 // the actual argument value blank for now.
John McCallb1e81442011-05-13 23:16:18 +00005616 args.add(RValue::get(0), ObjCTypes.MessageRefCPtrTy);
5617
5618 args.insert(args.end(), formalArgs.begin(), formalArgs.end());
5619
5620 const CGFunctionInfo &fnInfo =
5621 CGM.getTypes().getFunctionInfo(resultType, args,
5622 FunctionType::ExtInfo());
5623
John McCallcba681a2011-05-14 21:12:11 +00005624 NullReturnState nullReturn;
5625
John McCall944c8432011-05-14 03:10:52 +00005626 // Find the function to call and the mangled name for the message
5627 // ref structure. Using a different mangled name wouldn't actually
5628 // be a problem; it would just be a waste.
5629 //
5630 // The runtime currently never uses vtable dispatch for anything
5631 // except normal, non-super message-sends.
5632 // FIXME: don't use this for that.
John McCallb1e81442011-05-13 23:16:18 +00005633 llvm::Constant *fn = 0;
5634 std::string messageRefName("\01l_");
5635 if (CGM.ReturnTypeUsesSRet(fnInfo)) {
John McCallb1e81442011-05-13 23:16:18 +00005636 if (isSuper) {
5637 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5638 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005639 } else {
John McCallcba681a2011-05-14 21:12:11 +00005640 nullReturn.init(CGF, arg0);
John McCallb1e81442011-05-13 23:16:18 +00005641 fn = ObjCTypes.getMessageSendStretFixupFn();
5642 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005643 }
John McCallb1e81442011-05-13 23:16:18 +00005644 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
5645 fn = ObjCTypes.getMessageSendFpretFixupFn();
5646 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stumpb3589f42009-07-30 22:28:39 +00005647 } else {
John McCallb1e81442011-05-13 23:16:18 +00005648 if (isSuper) {
5649 fn = ObjCTypes.getMessageSendSuper2FixupFn();
5650 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005651 } else {
John McCallb1e81442011-05-13 23:16:18 +00005652 fn = ObjCTypes.getMessageSendFixupFn();
5653 messageRefName += "objc_msgSend_fixup";
Chris Lattner9b7d6702010-08-18 16:09:06 +00005654 }
Fariborz Jahanian83a8a752009-02-04 20:42:28 +00005655 }
John McCallb1e81442011-05-13 23:16:18 +00005656 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5657 messageRefName += '_';
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005658
John McCallb1e81442011-05-13 23:16:18 +00005659 // Append the selector name, except use underscores anywhere we
5660 // would have used colons.
5661 appendSelectorForMessageRefTable(messageRefName, selector);
5662
5663 llvm::GlobalVariable *messageRef
5664 = CGM.getModule().getGlobalVariable(messageRefName);
5665 if (!messageRef) {
John McCall944c8432011-05-14 03:10:52 +00005666 // Build the message ref structure.
John McCallb1e81442011-05-13 23:16:18 +00005667 llvm::Constant *values[] = { fn, GetMethodVarName(selector) };
5668 llvm::Constant *init =
5669 llvm::ConstantStruct::get(VMContext, values, 2, false);
5670 messageRef = new llvm::GlobalVariable(CGM.getModule(),
5671 init->getType(),
5672 /*constant*/ false,
5673 llvm::GlobalValue::WeakAnyLinkage,
5674 init,
5675 messageRefName);
5676 messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
5677 messageRef->setAlignment(16);
5678 messageRef->setSection("__DATA, __objc_msgrefs, coalesced");
5679 }
5680 llvm::Value *mref =
5681 CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy);
5682
John McCall944c8432011-05-14 03:10:52 +00005683 // Update the message ref argument.
John McCallb1e81442011-05-13 23:16:18 +00005684 args[1].RV = RValue::get(mref);
5685
5686 // Load the function to call from the message ref table.
5687 llvm::Value *callee = CGF.Builder.CreateStructGEP(mref, 0);
5688 callee = CGF.Builder.CreateLoad(callee, "msgSend_fn");
5689
5690 bool variadic = method ? method->isVariadic() : false;
5691 const llvm::FunctionType *fnType =
5692 CGF.getTypes().GetFunctionType(fnInfo, variadic);
5693 callee = CGF.Builder.CreateBitCast(callee,
5694 llvm::PointerType::getUnqual(fnType));
5695
John McCallcba681a2011-05-14 21:12:11 +00005696 RValue result = CGF.EmitCall(fnInfo, callee, returnSlot, args);
5697 return nullReturn.complete(CGF, result, resultType);
Fariborz Jahanian46551122009-02-04 00:22:57 +00005698}
5699
5700/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005701CodeGen::RValue
5702CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00005703 ReturnValueSlot Return,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005704 QualType ResultType,
5705 Selector Sel,
5706 llvm::Value *Receiver,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005707 const CallArgList &CallArgs,
David Chisnallc6cd5fd2010-04-28 19:33:36 +00005708 const ObjCInterfaceDecl *Class,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005709 const ObjCMethodDecl *Method) {
John McCall944c8432011-05-14 03:10:52 +00005710 return isVTableDispatchedSelector(Sel)
5711 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005712 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00005713 false, CallArgs, Method)
5714 : EmitMessageSend(CGF, Return, ResultType,
5715 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005716 Receiver, CGF.getContext().getObjCIdType(),
John McCall944c8432011-05-14 03:10:52 +00005717 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian46551122009-02-04 00:22:57 +00005718}
5719
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005720llvm::GlobalVariable *
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005721CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005722 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5723
Daniel Dunbardfff2302009-03-02 05:18:14 +00005724 if (!GV) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005725 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005726 false, llvm::GlobalValue::ExternalLinkage,
5727 0, Name);
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005728 }
5729
5730 return GV;
5731}
5732
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005733llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5734 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005735 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005736
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005737 if (!Entry) {
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005738 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbar5a7379a2009-03-01 04:40:10 +00005739 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005740 Entry =
5741 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005742 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005743 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005744 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005745 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005746 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005747 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00005748 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005749 CGM.AddUsedGlobal(Entry);
Daniel Dunbar11394522009-04-18 08:51:00 +00005750 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005751
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005752 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar11394522009-04-18 08:51:00 +00005753}
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005754
Daniel Dunbar11394522009-04-18 08:51:00 +00005755llvm::Value *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005756CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar11394522009-04-18 08:51:00 +00005757 const ObjCInterfaceDecl *ID) {
5758 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005759
Daniel Dunbar11394522009-04-18 08:51:00 +00005760 if (!Entry) {
5761 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5762 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005763 Entry =
5764 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Anderson1c431b32009-07-08 19:05:04 +00005765 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005766 ClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005767 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar11394522009-04-18 08:51:00 +00005768 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005769 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005770 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar11394522009-04-18 08:51:00 +00005771 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005772 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005773 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005774
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005775 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005776}
5777
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005778/// EmitMetaClassRef - Return a Value * of the address of _class_t
5779/// meta-data
5780///
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005781llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5782 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005783 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5784 if (Entry)
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005785 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005786
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00005787 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00005788 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005789 Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00005790 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005791 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005792 MetaClassGV,
Owen Anderson1c431b32009-07-08 19:05:04 +00005793 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005794 Entry->setAlignment(
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00005795 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005796 ObjCTypes.ClassnfABIPtrTy));
5797
Daniel Dunbar33af70f2009-04-15 19:03:14 +00005798 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005799 CGM.AddUsedGlobal(Entry);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005800
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005801 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005802}
5803
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005804/// GetClass - Return a reference to the class for the given interface
5805/// decl.
5806llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5807 const ObjCInterfaceDecl *ID) {
Douglas Gregor0a0d2b12011-03-23 00:50:03 +00005808 if (ID->isWeakImported()) {
Fariborz Jahanian269f8bc2009-11-17 22:42:00 +00005809 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5810 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5811 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5812 }
5813
Fariborz Jahanian0e81f4b2009-02-05 20:41:40 +00005814 return EmitClassRef(Builder, ID);
5815}
5816
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005817/// Generates a message send where the super is the receiver. This is
5818/// a message send to self with special delivery semantics indicating
5819/// which class's method should be called.
5820CodeGen::RValue
5821CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCallef072fd2010-05-22 01:48:05 +00005822 ReturnValueSlot Return,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005823 QualType ResultType,
5824 Selector Sel,
5825 const ObjCInterfaceDecl *Class,
5826 bool isCategoryImpl,
5827 llvm::Value *Receiver,
5828 bool IsClassMessage,
Daniel Dunbard6c93d72009-09-17 04:01:22 +00005829 const CodeGen::CallArgList &CallArgs,
5830 const ObjCMethodDecl *Method) {
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005831 // ...
5832 // Create and init a super structure; this is a (receiver, class)
5833 // pair we will pass to objc_msgSendSuper.
5834 llvm::Value *ObjCSuper =
John McCall604da292011-03-04 08:00:29 +00005835 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005836
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005837 llvm::Value *ReceiverAsObject =
5838 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5839 CGF.Builder.CreateStore(ReceiverAsObject,
5840 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005841
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005842 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005843 llvm::Value *Target;
5844 if (IsClassMessage) {
5845 if (isCategoryImpl) {
5846 // Message sent to "super' in a class method defined in
5847 // a category implementation.
Daniel Dunbar11394522009-04-18 08:51:00 +00005848 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005849 Target = CGF.Builder.CreateStructGEP(Target, 0);
5850 Target = CGF.Builder.CreateLoad(Target);
Mike Stumpb3589f42009-07-30 22:28:39 +00005851 } else
Fariborz Jahanian7ce77922009-02-28 20:07:56 +00005852 Target = EmitMetaClassRef(CGF.Builder, Class);
Mike Stumpb3589f42009-07-30 22:28:39 +00005853 } else
Daniel Dunbar11394522009-04-18 08:51:00 +00005854 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005855
Mike Stumpf5408fe2009-05-16 07:57:57 +00005856 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5857 // ObjCTypes types.
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005858 const llvm::Type *ClassTy =
5859 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
5860 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
5861 CGF.Builder.CreateStore(Target,
5862 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005863
John McCall944c8432011-05-14 03:10:52 +00005864 return (isVTableDispatchedSelector(Sel))
5865 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005866 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00005867 true, CallArgs, Method)
5868 : EmitMessageSend(CGF, Return, ResultType,
5869 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005870 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall944c8432011-05-14 03:10:52 +00005871 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian7a06aae2009-02-06 20:09:23 +00005872}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005873
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005874llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian03b29602010-06-17 19:56:20 +00005875 Selector Sel, bool lval) {
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005876 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005877
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005878 if (!Entry) {
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005879 llvm::Constant *Casted =
5880 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5881 ObjCTypes.SelectorPtrTy);
5882 Entry =
5883 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
5884 llvm::GlobalValue::InternalLinkage,
5885 Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
Fariborz Jahaniand0f8a8d2009-05-11 19:25:47 +00005886 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerad64e022009-07-17 23:57:13 +00005887 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005888 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005889
Fariborz Jahanian03b29602010-06-17 19:56:20 +00005890 if (lval)
5891 return Entry;
Daniel Dunbar2da84ff2009-11-29 21:23:36 +00005892 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00005893}
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005894/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005895/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005896///
5897void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005898 llvm::Value *src,
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005899 llvm::Value *dst,
5900 llvm::Value *ivarOffset) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005901 const llvm::Type * SrcTy = src->getType();
5902 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005903 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005904 assert(Size <= 8 && "does not support size > 8");
5905 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5906 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005907 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5908 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005909 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5910 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6c7a1f32009-09-24 22:25:38 +00005911 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5912 src, dst, ivarOffset);
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005913 return;
5914}
5915
5916/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5917/// objc_assign_strongCast (id src, id *dst)
5918///
5919void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005920 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005921 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005922 const llvm::Type * SrcTy = src->getType();
5923 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005924 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005925 assert(Size <= 8 && "does not support size > 8");
5926 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005927 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005928 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5929 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005930 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5931 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerbbccd612009-04-22 02:38:11 +00005932 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005933 src, dst, "weakassign");
5934 return;
5935}
5936
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005937void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005938 CodeGen::CodeGenFunction &CGF,
5939 llvm::Value *DestPtr,
5940 llvm::Value *SrcPtr,
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00005941 llvm::Value *Size) {
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005942 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5943 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005944 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian55bcace2010-06-15 22:44:06 +00005945 DestPtr, SrcPtr, Size);
Fariborz Jahanian082b02e2009-07-08 01:18:33 +00005946 return;
5947}
5948
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005949/// EmitObjCWeakRead - Code gen for loading value of a __weak
5950/// object: objc_read_weak (id *src)
5951///
5952llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005953 CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005954 llvm::Value *AddrWeakObj) {
Eli Friedman8339b352009-03-07 03:57:15 +00005955 const llvm::Type* DestTy =
Daniel Dunbar6bff2512009-08-03 17:06:42 +00005956 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5957 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattner72db6c32009-04-22 02:44:54 +00005958 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005959 AddrWeakObj, "weakread");
Eli Friedman8339b352009-03-07 03:57:15 +00005960 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005961 return read_weak;
5962}
5963
5964/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
5965/// objc_assign_weak (id src, id *dst)
5966///
5967void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump1eb44332009-09-09 15:08:12 +00005968 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005969 const llvm::Type * SrcTy = src->getType();
5970 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005971 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005972 assert(Size <= 8 && "does not support size > 8");
5973 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5974 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005975 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5976 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005977 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5978 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner96508e12009-04-17 22:12:36 +00005979 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005980 src, dst, "weakassign");
5981 return;
5982}
5983
5984/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
5985/// objc_assign_global (id src, id *dst)
5986///
5987void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00005988 llvm::Value *src, llvm::Value *dst,
5989 bool threadlocal) {
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005990 const llvm::Type * SrcTy = src->getType();
5991 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sands9408c452009-05-09 07:08:47 +00005992 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanian0a855d02009-03-23 19:10:40 +00005993 assert(Size <= 8 && "does not support size > 8");
5994 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5995 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian3b8a6522009-03-13 00:42:52 +00005996 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5997 }
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00005998 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5999 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian021a7a62010-07-20 20:30:03 +00006000 if (!threadlocal)
6001 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
6002 src, dst, "globalassign");
6003 else
6004 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
6005 src, dst, "threadlocalassign");
Fariborz Jahanian6948aea2009-02-16 22:52:32 +00006006 return;
6007}
Fariborz Jahanian26cc89f2009-02-11 20:51:17 +00006008
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006009void
John McCallf1549f62010-07-06 01:34:17 +00006010CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6011 const ObjCAtSynchronizedStmt &S) {
David Chisnall05dc91b2011-03-25 17:46:35 +00006012 EmitAtSynchronizedStmt(CGF, S,
6013 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6014 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallf1549f62010-07-06 01:34:17 +00006015}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006016
John McCall5a180392010-07-24 00:37:23 +00006017llvm::Constant *
6018CGObjCNonFragileABIMac::GetEHType(QualType T) {
6019 // There's a particular fixed type info for 'id'.
6020 if (T->isObjCIdType() ||
6021 T->isObjCQualifiedIdType()) {
6022 llvm::Constant *IDEHType =
6023 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
6024 if (!IDEHType)
6025 IDEHType =
6026 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
6027 false,
6028 llvm::GlobalValue::ExternalLinkage,
6029 0, "OBJC_EHTYPE_id");
6030 return IDEHType;
6031 }
6032
6033 // All other types should be Objective-C interface pointer types.
6034 const ObjCObjectPointerType *PT =
6035 T->getAs<ObjCObjectPointerType>();
6036 assert(PT && "Invalid @catch type.");
6037 const ObjCInterfaceType *IT = PT->getInterfaceType();
6038 assert(IT && "Invalid @catch type.");
6039 return GetInterfaceEHType(IT->getDecl(), false);
6040}
6041
John McCallf1549f62010-07-06 01:34:17 +00006042void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6043 const ObjCAtTryStmt &S) {
David Chisnall05dc91b2011-03-25 17:46:35 +00006044 EmitTryCatchStmt(CGF, S,
6045 cast<llvm::Function>(ObjCTypes.getObjCBeginCatchFn()),
6046 cast<llvm::Function>(ObjCTypes.getObjCEndCatchFn()),
6047 cast<llvm::Function>(ObjCTypes.getExceptionRethrowFn()));
Daniel Dunbar8ecbaf22009-02-24 07:47:38 +00006048}
6049
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006050/// EmitThrowStmt - Generate code for a throw statement.
6051void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6052 const ObjCAtThrowStmt &S) {
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006053 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall7ec404c2010-10-16 08:21:07 +00006054 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
John McCallfd186ac2010-10-16 16:34:08 +00006055 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy,
6056 "tmp");
John McCall7ec404c2010-10-16 08:21:07 +00006057 llvm::Value *Args[] = { Exception };
6058 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(),
6059 Args, Args+1)
6060 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006061 } else {
John McCall7ec404c2010-10-16 08:21:07 +00006062 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn(), 0, 0)
6063 .setDoesNotReturn();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006064 }
6065
John McCall7ec404c2010-10-16 08:21:07 +00006066 CGF.Builder.CreateUnreachable();
Anders Carlssonf57c5b22009-02-16 22:59:18 +00006067 CGF.Builder.ClearInsertionPoint();
6068}
Daniel Dunbare588b992009-03-01 04:46:24 +00006069
John McCall5a180392010-07-24 00:37:23 +00006070llvm::Constant *
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006071CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006072 bool ForDefinition) {
Daniel Dunbare588b992009-03-01 04:46:24 +00006073 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbare588b992009-03-01 04:46:24 +00006074
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006075 // If we don't need a definition, return the entry if found or check
6076 // if we use an external reference.
6077 if (!ForDefinition) {
6078 if (Entry)
6079 return Entry;
Daniel Dunbar7e075cb2009-04-07 06:43:45 +00006080
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006081 // If this type (or a super class) has the __objc_exception__
6082 // attribute, emit an external reference.
Douglas Gregor68584ed2009-06-18 16:11:24 +00006083 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006084 return Entry =
Owen Anderson1c431b32009-07-08 19:05:04 +00006085 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006086 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006087 0,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006088 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006089 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006090 }
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006091
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006092 // Otherwise we need to either make a new entry or fill in the
6093 // initializer.
6094 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006095 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbare588b992009-03-01 04:46:24 +00006096 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006097 llvm::GlobalVariable *VTableGV =
Daniel Dunbare588b992009-03-01 04:46:24 +00006098 CGM.getModule().getGlobalVariable(VTableName);
6099 if (!VTableGV)
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006100 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6101 false,
Daniel Dunbare588b992009-03-01 04:46:24 +00006102 llvm::GlobalValue::ExternalLinkage,
Owen Anderson1c431b32009-07-08 19:05:04 +00006103 0, VTableName);
Daniel Dunbare588b992009-03-01 04:46:24 +00006104
Chris Lattner77b89b82010-06-27 07:15:29 +00006105 llvm::Value *VTableIdx =
6106 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
Daniel Dunbare588b992009-03-01 04:46:24 +00006107
6108 std::vector<llvm::Constant*> Values(3);
Owen Anderson3c4972d2009-07-29 18:54:39 +00006109 Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
Daniel Dunbare588b992009-03-01 04:46:24 +00006110 Values[1] = GetClassName(ID->getIdentifier());
Fariborz Jahanian0f902942009-04-14 18:41:56 +00006111 Values[2] = GetClassGlobal(ClassName);
Owen Andersona1cf15f2009-07-14 23:10:40 +00006112 llvm::Constant *Init =
Owen Anderson08e25242009-07-27 22:29:56 +00006113 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbare588b992009-03-01 04:46:24 +00006114
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006115 if (Entry) {
6116 Entry->setInitializer(Init);
6117 } else {
Owen Anderson1c431b32009-07-08 19:05:04 +00006118 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006119 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006120 Init,
Daniel Dunbar9c29bf52009-10-18 20:48:59 +00006121 ("OBJC_EHTYPE_$_" +
Daniel Dunbar01eb9b92009-10-18 21:17:35 +00006122 ID->getIdentifier()->getName()));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006123 }
6124
John McCall1fb0caa2010-10-22 21:05:15 +00006125 if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar6ab187a2009-04-07 05:48:37 +00006126 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar4b429ae2010-04-25 20:39:32 +00006127 Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6128 ObjCTypes.EHTypeTy));
Daniel Dunbar8158a2f2009-04-08 04:21:03 +00006129
6130 if (ForDefinition) {
6131 Entry->setSection("__DATA,__objc_const");
6132 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
6133 } else {
6134 Entry->setSection("__DATA,__datacoal_nt,coalesced");
6135 }
Daniel Dunbare588b992009-03-01 04:46:24 +00006136
6137 return Entry;
6138}
Daniel Dunbar6bff2512009-08-03 17:06:42 +00006139
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00006140/* *** */
6141
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00006142CodeGen::CGObjCRuntime *
6143CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
David Chisnall60be6072011-03-22 21:21:24 +00006144 if (CGM.getLangOptions().ObjCNonFragileABI)
6145 return new CGObjCNonFragileABIMac(CGM);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00006146 return new CGObjCMac(CGM);
6147}