blob: 7cb51e2611a72e5da387a56b47c5073fb17d7ce8 [file] [log] [blame]
Daniel Dunbar303e2c22008-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 Lattner57540c52011-04-15 05:22:18 +000010// This provides Objective-C code generation targeting the Apple runtime.
Daniel Dunbar303e2c22008-08-11 02:45:11 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000015
Daniel Dunbar034299e2010-03-31 01:09:11 +000016#include "CGRecordLayout.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000017#include "CodeGenModule.h"
Daniel Dunbara94ecd22008-08-16 03:19:19 +000018#include "CodeGenFunction.h"
John McCallad7c5c12011-02-08 08:22:06 +000019#include "CGBlocks.h"
John McCalled1ae862011-01-28 11:13:47 +000020#include "CGCleanup.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000021#include "clang/AST/ASTContext.h"
Daniel Dunbar221fa942008-08-11 04:54:23 +000022#include "clang/AST/Decl.h"
Daniel Dunbarb036db82008-08-13 03:21:16 +000023#include "clang/AST/DeclObjC.h"
Anders Carlsson15b73de2009-07-18 19:43:29 +000024#include "clang/AST/RecordLayout.h"
Chris Lattnerf0b64d72009-04-26 01:32:48 +000025#include "clang/AST/StmtObjC.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000026#include "clang/Basic/LangOptions.h"
Chandler Carruth85098242010-06-15 23:19:56 +000027#include "clang/Frontend/CodeGenOptions.h"
Daniel Dunbar3ad53482008-08-11 21:35:06 +000028
John McCall42227ed2010-07-31 23:20:56 +000029#include "llvm/InlineAsm.h"
30#include "llvm/IntrinsicInst.h"
Owen Andersonae86c192009-07-13 04:10:07 +000031#include "llvm/LLVMContext.h"
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000032#include "llvm/Module.h"
Daniel Dunbarc475d422008-10-29 22:36:39 +000033#include "llvm/ADT/DenseSet.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000034#include "llvm/ADT/SetVector.h"
35#include "llvm/ADT/SmallString.h"
Fariborz Jahanian751c1e72009-12-12 21:26:21 +000036#include "llvm/ADT/SmallPtrSet.h"
John McCall5c08ab92010-07-13 22:12:14 +000037#include "llvm/Support/CallSite.h"
Daniel Dunbard027a922009-09-07 00:20:42 +000038#include "llvm/Support/raw_ostream.h"
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +000039#include "llvm/Target/TargetData.h"
Torok Edwindb714922009-08-24 13:25:12 +000040#include <cstdio>
Daniel Dunbar303e2c22008-08-11 02:45:11 +000041
42using namespace clang;
Daniel Dunbar41cf9de2008-09-09 01:06:48 +000043using namespace CodeGen;
Daniel Dunbar303e2c22008-08-11 02:45:11 +000044
Daniel Dunbar9fd114d2009-04-22 07:32:20 +000045
Daniel Dunbar303e2c22008-08-11 02:45:11 +000046namespace {
Daniel Dunbar8b8683f2008-08-12 00:12:39 +000047
Daniel Dunbar59e476b2009-08-03 17:06:42 +000048typedef std::vector<llvm::Constant*> ConstantVector;
Daniel Dunbareb1f9a22008-08-27 02:31:56 +000049
Daniel Dunbar59e476b2009-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 Dunbarb036db82008-08-13 03:21:16 +000052
Fariborz Jahanian279eda62009-01-21 22:04:16 +000053class ObjCCommonTypesHelper {
Owen Anderson170229f2009-07-14 23:10:40 +000054protected:
55 llvm::LLVMContext &VMContext;
Daniel Dunbar59e476b2009-08-03 17:06:42 +000056
Fariborz Jahanian5d5ed2d2009-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 Dunbar59e476b2009-08-03 17:06:42 +000064 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +000065 Params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +000066 "objc_msgSend");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000067 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000068
Fariborz Jahanian5d5ed2d2009-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 Anderson41a75022009-08-13 21:57:51 +000075 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +000076 Params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +000077 "objc_msgSend_stret");
78
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000079 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000080
Fariborz Jahanian5d5ed2d2009-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 Anderson41a75022009-08-13 21:57:51 +000088 CGM.CreateRuntimeFunction(llvm::FunctionType::get(
89 llvm::Type::getDoubleTy(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +000090 Params,
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +000091 true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +000092 "objc_msgSend_fpret");
93
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +000094 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +000095
Fariborz Jahanian5d5ed2d2009-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 Anderson9793f0e2009-07-29 22:16:19 +0000102 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +0000103 Params, true),
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000104 SuperName);
105 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000106
Fariborz Jahanian5d5ed2d2009-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 Anderson9793f0e2009-07-29 22:16:19 +0000113 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +0000114 Params, true),
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000115 SuperName);
116 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000117
Fariborz Jahanian5d5ed2d2009-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 Anderson170229f2009-07-14 23:10:40 +0000125 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000126 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +0000127 Params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000128 "objc_msgSendSuper_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000129 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000130
Fariborz Jahanian5d5ed2d2009-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 Anderson170229f2009-07-14 23:10:40 +0000138 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000139 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +0000140 Params, true),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000141 "objc_msgSendSuper2_stret");
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000142 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000143
Fariborz Jahanian5d5ed2d2009-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 Dunbar59e476b2009-08-03 17:06:42 +0000148
Fariborz Jahanian5d5ed2d2009-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 Dunbar59e476b2009-08-03 17:06:42 +0000153
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000154protected:
155 CodeGen::CodeGenModule &CGM;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000156
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000157public:
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +0000158 const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000159 const llvm::Type *Int8PtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000160
Daniel Dunbar5d715592008-08-12 05:28:47 +0000161 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
162 const llvm::Type *ObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000163
Fariborz Jahanian406b1172008-11-18 20:18:11 +0000164 /// PtrObjectPtrTy - LLVM type for id *
165 const llvm::Type *PtrObjectPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000166
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000167 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Daniel Dunbar5d715592008-08-12 05:28:47 +0000168 const llvm::Type *SelectorPtrTy;
Daniel Dunbarb036db82008-08-13 03:21:16 +0000169 /// ProtocolPtrTy - LLVM type for external protocol handles
170 /// (typeof(Protocol))
171 const llvm::Type *ExternalProtocolPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000172
Daniel Dunbarc722b852008-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 Dunbar59e476b2009-08-03 17:06:42 +0000177
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000178 /// SuperTy - LLVM type for struct objc_super.
179 const llvm::StructType *SuperTy;
Daniel Dunbar97ff50d2008-08-23 09:25:55 +0000180 /// SuperPtrTy - LLVM type for struct objc_super *.
181 const llvm::Type *SuperPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000182
Fariborz Jahanianb15a3d52009-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 Dunbar59e476b2009-08-03 17:06:42 +0000186
Fariborz Jahanianb15a3d52009-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 Dunbar59e476b2009-08-03 17:06:42 +0000192
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000193 // MethodTy - LLVM type for struct objc_method.
194 const llvm::StructType *MethodTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000195
Fariborz Jahanian0232c052009-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 Dunbar59e476b2009-08-03 17:06:42 +0000200
Chris Lattnerce8754e2009-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 McCall2da83a32010-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 Lattnerce8754e2009-04-22 02:44:54 +0000208 Params.push_back(IdType);
209 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000210 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-04-22 02:44:54 +0000211 Params.push_back(Ctx.BoolTy);
212 const llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000213 Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000214 FunctionType::ExtInfo()),
215 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000216 return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
217 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000218
Chris Lattnerce8754e2009-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 McCall2da83a32010-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 Lattnerce8754e2009-04-22 02:44:54 +0000226 Params.push_back(IdType);
227 Params.push_back(SelType);
David Chisnall08a45252011-03-22 20:03:13 +0000228 Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
Chris Lattnerce8754e2009-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 McCallab26cfa2010-02-05 21:31:56 +0000233 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000234 FunctionType::ExtInfo()),
235 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000236 return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
237 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000238
Fariborz Jahanian5a8c2032010-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 Lattnerce8754e2009-04-22 02:44:54 +0000257 llvm::Constant *getEnumerationMutationFn() {
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000258 CodeGen::CodeGenTypes &Types = CGM.getTypes();
259 ASTContext &Ctx = CGM.getContext();
Chris Lattnerce8754e2009-04-22 02:44:54 +0000260 // void objc_enumerationMutation (id)
John McCall2da83a32010-02-26 00:48:12 +0000261 llvm::SmallVector<CanQualType,1> Params;
262 Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
Daniel Dunbar9d82da42009-07-11 20:32:50 +0000263 const llvm::FunctionType *FTy =
John McCallab26cfa2010-02-05 21:31:56 +0000264 Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
Rafael Espindolac50c27c2010-03-30 20:24:48 +0000265 FunctionType::ExtInfo()),
266 false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000267 return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
268 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000269
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000270 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattnerce8754e2009-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 Dunbar59e476b2009-08-03 17:06:42 +0000275 llvm::FunctionType *FTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +0000276 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattnerce8754e2009-04-22 02:44:54 +0000277 return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000278 }
279
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000280 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner6fdd57c2009-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 Anderson9793f0e2009-07-29 22:16:19 +0000286 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner6fdd57c2009-04-17 22:12:36 +0000287 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
288 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000289
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000290 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattner0a696a422009-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 Anderson170229f2009-07-14 23:10:40 +0000295 llvm::FunctionType *FTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +0000296 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000297 return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
298 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000299
Fariborz Jahanian217af242010-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 Jahanianeee54df2009-01-22 00:37:21 +0000310 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000311 llvm::Constant *getGcAssignIvarFn() {
Fariborz Jahanian7a95d722009-09-24 22:25:38 +0000312 // id objc_assign_ivar(id, id *, ptrdiff_t)
Chris Lattner0a696a422009-04-22 02:38:11 +0000313 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
314 Args.push_back(ObjectPtrTy->getPointerTo());
Fariborz Jahanian30aa4aa2011-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 Anderson170229f2009-07-14 23:10:40 +0000320 llvm::FunctionType *FTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +0000321 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000322 return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
323 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000324
Fariborz Jahanian5f21d2f2009-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 Anderson9793f0e2009-07-29 22:16:19 +0000331 llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +0000332 return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
333 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000334
Fariborz Jahanianeee54df2009-01-22 00:37:21 +0000335 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattner0a696a422009-04-22 02:38:11 +0000336 llvm::Constant *getGcAssignStrongCastFn() {
Fariborz Jahanian217af242010-07-20 20:30:03 +0000337 // id objc_assign_strongCast(id, id *)
Chris Lattner0a696a422009-04-22 02:38:11 +0000338 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
339 Args.push_back(ObjectPtrTy->getPointerTo());
Owen Anderson170229f2009-07-14 23:10:40 +0000340 llvm::FunctionType *FTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +0000341 llvm::FunctionType::get(ObjectPtrTy, Args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000342 return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
343 }
Anders Carlsson9ab53d12009-02-16 22:59:18 +0000344
345 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattner0a696a422009-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 Anderson41a75022009-08-13 21:57:51 +0000350 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000351 return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
352 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000353
Fariborz Jahanian3336de12010-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 McCall17afe452010-10-16 08:21:07 +0000359 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Fariborz Jahanian3336de12010-05-28 17:34:43 +0000360 return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
361 }
362
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000363 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattnerdcceee72009-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 Anderson41a75022009-08-13 21:57:51 +0000368 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattnerdcceee72009-04-06 16:53:45 +0000369 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
370 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000371
Daniel Dunbar94ceb612009-02-24 01:43:46 +0000372 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattner0a696a422009-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 Anderson41a75022009-08-13 21:57:51 +0000377 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
Chris Lattner0a696a422009-04-22 02:38:11 +0000378 return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
379 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000380
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000381 llvm::Constant *getSendFn(bool IsSuper) const {
382 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
383 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000384
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000385 llvm::Constant *getSendFn2(bool IsSuper) const {
386 return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
387 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000388
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000389 llvm::Constant *getSendStretFn(bool IsSuper) const {
390 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
391 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000392
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000393 llvm::Constant *getSendStretFn2(bool IsSuper) const {
394 return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
395 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000396
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000397 llvm::Constant *getSendFpretFn(bool IsSuper) const {
398 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
399 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000400
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +0000401 llvm::Constant *getSendFpretFn2(bool IsSuper) const {
402 return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
403 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000404
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000405 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
406 ~ObjCCommonTypesHelper(){}
407};
Daniel Dunbarf6397fe2008-08-23 04:28:29 +0000408
Fariborz Jahanian279eda62009-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 Jahanian279eda62009-01-21 22:04:16 +0000412public:
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000413 /// SymtabTy - LLVM type for struct objc_symtab.
414 const llvm::StructType *SymtabTy;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000415 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
416 const llvm::Type *SymtabPtrTy;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000417 /// ModuleTy - LLVM type for struct objc_module.
418 const llvm::StructType *ModuleTy;
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000419
Daniel Dunbarb036db82008-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 Dunbarb036db82008-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 Dunbar938a77f2008-08-22 20:34:54 +0000443 /// CategoryTy - LLVM type for struct objc_category.
444 const llvm::StructType *CategoryTy;
Daniel Dunbar22d82ed2008-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 Dunbar22d82ed2008-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 Dunbar22d82ed2008-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 Dunbar59e476b2009-08-03 17:06:42 +0000463
Anders Carlsson9ff22482008-09-09 10:10:21 +0000464 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
465 const llvm::Type *ExceptionDataTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000466
Anders Carlsson9ff22482008-09-09 10:10:21 +0000467 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000468 llvm::Constant *getExceptionTryEnterFn() {
469 std::vector<const llvm::Type*> Params;
Owen Anderson9793f0e2009-07-29 22:16:19 +0000470 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
Owen Anderson170229f2009-07-14 23:10:40 +0000471 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000472 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000473 Params, false),
474 "objc_exception_try_enter");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000475 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000476
477 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000478 llvm::Constant *getExceptionTryExitFn() {
479 std::vector<const llvm::Type*> Params;
Owen Anderson9793f0e2009-07-29 22:16:19 +0000480 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
Owen Anderson170229f2009-07-14 23:10:40 +0000481 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000482 llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000483 Params, false),
484 "objc_exception_try_exit");
Chris Lattnerc6406db2009-04-22 02:26:14 +0000485 }
Anders Carlsson9ff22482008-09-09 10:10:21 +0000486
487 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000488 llvm::Constant *getExceptionExtractFn() {
489 std::vector<const llvm::Type*> Params;
Owen Anderson9793f0e2009-07-29 22:16:19 +0000490 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
491 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Chris Lattnerc6406db2009-04-22 02:26:14 +0000492 Params, false),
493 "objc_exception_extract");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000494
Chris Lattnerc6406db2009-04-22 02:26:14 +0000495 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000496
Anders Carlsson9ff22482008-09-09 10:10:21 +0000497 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattnerc6406db2009-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 Dunbar59e476b2009-08-03 17:06:42 +0000502 return CGM.CreateRuntimeFunction(
Owen Anderson41a75022009-08-13 21:57:51 +0000503 llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000504 Params, false),
505 "objc_exception_match");
506
Chris Lattnerc6406db2009-04-22 02:26:14 +0000507 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000508
Anders Carlsson9ff22482008-09-09 10:10:21 +0000509 /// SetJmpFn - LLVM _setjmp function.
Chris Lattnerc6406db2009-04-22 02:26:14 +0000510 llvm::Constant *getSetJmpFn() {
511 std::vector<const llvm::Type*> Params;
Benjamin Kramerabd5b902009-10-13 10:07:13 +0000512 Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
Chris Lattnerc6406db2009-04-22 02:26:14 +0000513 return
Owen Anderson41a75022009-08-13 21:57:51 +0000514 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
Chris Lattnerc6406db2009-04-22 02:26:14 +0000515 Params, false),
516 "_setjmp");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000517
Chris Lattnerc6406db2009-04-22 02:26:14 +0000518 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000519
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000520public:
521 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000522 ~ObjCTypesHelper() {}
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000523};
524
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000525/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000526/// modern abi
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000527class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000528public:
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000529
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000530 // MethodListnfABITy - LLVM for struct _method_list_t
531 const llvm::StructType *MethodListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000532
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000533 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
534 const llvm::Type *MethodListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000535
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000536 // ProtocolnfABITy = LLVM for struct _protocol_t
537 const llvm::StructType *ProtocolnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000538
Daniel Dunbar8de90f02009-02-15 07:36:20 +0000539 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
540 const llvm::Type *ProtocolnfABIPtrTy;
541
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000542 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
543 const llvm::StructType *ProtocolListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000544
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000545 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
546 const llvm::Type *ProtocolListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000547
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000548 // ClassnfABITy - LLVM for struct _class_t
549 const llvm::StructType *ClassnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000550
Fariborz Jahanian71394042009-01-23 23:53:38 +0000551 // ClassnfABIPtrTy - LLVM for struct _class_t*
552 const llvm::Type *ClassnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000553
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000554 // IvarnfABITy - LLVM for struct _ivar_t
555 const llvm::StructType *IvarnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000556
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000557 // IvarListnfABITy - LLVM for struct _ivar_list_t
558 const llvm::StructType *IvarListnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000559
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000560 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
561 const llvm::Type *IvarListnfABIPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000562
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000563 // ClassRonfABITy - LLVM for struct _class_ro_t
564 const llvm::StructType *ClassRonfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000565
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000566 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
567 const llvm::Type *ImpnfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000568
Fariborz Jahanian0232c052009-01-23 01:46:23 +0000569 // CategorynfABITy - LLVM for struct _category_t
570 const llvm::StructType *CategorynfABITy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000571
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000572 // New types for nonfragile abi messaging.
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000573
Fariborz Jahanian82c72e12009-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 Jahaniane4dc35d2009-02-04 20:42:28 +0000580 // MessageRefCTy - clang type for struct _message_ref_t
581 QualType MessageRefCTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000582
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000583 // MessageRefPtrTy - LLVM for struct _message_ref_t*
584 const llvm::Type *MessageRefPtrTy;
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +0000585 // MessageRefCPtrTy - clang type for struct _message_ref_t*
586 QualType MessageRefCPtrTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000587
Fariborz Jahanian4e87c832009-02-05 01:13:09 +0000588 // MessengerTy - Type of the messenger (shown as IMP above)
589 const llvm::FunctionType *MessengerTy;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000590
Fariborz Jahanian82c72e12009-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 Dunbar59e476b2009-08-03 17:06:42 +0000597
Fariborz Jahanian82c72e12009-02-03 23:49:23 +0000598 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
599 const llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000600
Chris Lattner2dfdb3e2009-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 Anderson9793f0e2009-07-29 22:16:19 +0000606 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +0000607 Params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000608 "objc_msgSend_fixup");
609 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000610
Chris Lattner2dfdb3e2009-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 Anderson9793f0e2009-07-29 22:16:19 +0000616 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +0000617 Params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000618 "objc_msgSend_fpret_fixup");
619 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000620
Chris Lattner2dfdb3e2009-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 Anderson9793f0e2009-07-29 22:16:19 +0000626 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +0000627 Params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000628 "objc_msgSend_stret_fixup");
629 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000630
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000631 llvm::Constant *getMessageSendSuper2FixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000632 // id objc_msgSendSuper2_fixup (struct objc_super *,
Chris Lattner2dfdb3e2009-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 Anderson9793f0e2009-07-29 22:16:19 +0000637 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +0000638 Params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000639 "objc_msgSendSuper2_fixup");
640 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000641
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000642 llvm::Constant *getMessageSendSuper2StretFixupFn() {
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000643 // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
Chris Lattner2dfdb3e2009-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 Anderson9793f0e2009-07-29 22:16:19 +0000648 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
Fariborz Jahanian557c1ed2011-02-28 21:19:34 +0000649 Params, true),
Chris Lattner2dfdb3e2009-04-22 02:53:24 +0000650 "objc_msgSendSuper2_stret_fixup");
651 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000652
Chris Lattnera7c00b42009-04-22 02:15:23 +0000653 llvm::Constant *getObjCEndCatchFn() {
Owen Anderson41a75022009-08-13 21:57:51 +0000654 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
Chris Lattner3dd1b4b2009-07-01 04:13:52 +0000655 false),
Chris Lattnera7c00b42009-04-22 02:15:23 +0000656 "objc_end_catch");
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000657
Chris Lattnera7c00b42009-04-22 02:15:23 +0000658 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000659
Chris Lattnera7c00b42009-04-22 02:15:23 +0000660 llvm::Constant *getObjCBeginCatchFn() {
661 std::vector<const llvm::Type*> Params;
662 Params.push_back(Int8PtrTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000663 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
Chris Lattnera7c00b42009-04-22 02:15:23 +0000664 Params, false),
665 "objc_begin_catch");
666 }
Daniel Dunbarb1559a42009-03-01 04:46:24 +0000667
668 const llvm::StructType *EHTypeTy;
669 const llvm::Type *EHTypePtrTy;
Daniel Dunbar0b0dcd92009-02-24 07:47:38 +0000670
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +0000671 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
672 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000673};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000674
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000675class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000676public:
677 // FIXME - accessibility
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000678 class GC_IVAR {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +0000679 public:
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000680 unsigned ivar_bytepos;
681 unsigned ivar_size;
682 GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000683 : ivar_bytepos(bytepos), ivar_size(size) {}
Daniel Dunbar22b0ada2009-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 Jahanian524bb202009-03-10 16:22:08 +0000689 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000690
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000691 class SKIP_SCAN {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000692 public:
693 unsigned skip;
694 unsigned scan;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000695 SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
Daniel Dunbar7b89ace2009-05-03 13:44:42 +0000696 : skip(_skip), scan(_scan) {}
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +0000697 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000698
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000699protected:
700 CodeGen::CodeGenModule &CGM;
Owen Andersonae86c192009-07-13 04:10:07 +0000701 llvm::LLVMContext &VMContext;
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000702 // FIXME! May not be needing this after all.
Daniel Dunbar8b8683f2008-08-12 00:12:39 +0000703 unsigned ObjCABI;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000704
Fariborz Jahaniancbaf73c2009-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 Dunbar59e476b2009-08-03 17:06:42 +0000708
Daniel Dunbarc61d0e92008-08-25 06:02:07 +0000709 /// LazySymbols - Symbols to generate a lazy reference for. See
710 /// DefinedSymbols and FinishModule().
Daniel Dunbard027a922009-09-07 00:20:42 +0000711 llvm::SetVector<IdentifierInfo*> LazySymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000712
Daniel Dunbarc61d0e92008-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 Dunbard027a922009-09-07 00:20:42 +0000717 llvm::SetVector<IdentifierInfo*> DefinedSymbols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000718
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000719 /// ClassNames - uniqued class names.
Daniel Dunbarb036db82008-08-13 03:21:16 +0000720 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000721
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000722 /// MethodVarNames - uniqued method variable names.
723 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000724
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +0000725 /// DefinedCategoryNames - list of category names in form Class_Category.
726 llvm::SetVector<std::string> DefinedCategoryNames;
727
Daniel Dunbarb036db82008-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 Dunbar59e476b2009-08-03 17:06:42 +0000731
Daniel Dunbar3c76cb52008-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 Dunbar59e476b2009-08-03 17:06:42 +0000735
Daniel Dunbar80a840b2008-08-23 00:19:03 +0000736 /// PropertyNames - uniqued method variable names.
737 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000738
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000739 /// ClassReferences - uniqued class references.
740 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000741
Daniel Dunbarcb515c82008-08-12 03:39:23 +0000742 /// SelectorReferences - uniqued selector references.
743 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000744
Daniel Dunbarb036db82008-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 Dunbar59e476b2009-08-03 17:06:42 +0000749
Daniel Dunbarc475d422008-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 Dunbar59e476b2009-08-03 17:06:42 +0000753
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000754 /// DefinedClasses - List of defined classes.
755 std::vector<llvm::GlobalValue*> DefinedClasses;
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000756
757 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
758 std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000759
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000760 /// DefinedCategories - List of defined categories.
761 std::vector<llvm::GlobalValue*> DefinedCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000762
Daniel Dunbar9a017d72009-05-15 22:33:15 +0000763 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
764 std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000765
Fariborz Jahanian0b1ccdc2009-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 Dunbard2386812009-10-19 01:21:19 +0000770 llvm::SmallVectorImpl<char> &NameOut);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000771
Fariborz Jahanian0b1ccdc2009-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 Dunbar59e476b2009-08-03 17:06:42 +0000776
Fariborz Jahanian0b1ccdc2009-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 Dunbar59e476b2009-08-03 17:06:42 +0000779
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +0000780 // FIXME: This is a horrible name.
781 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Daniel Dunbarf5c18462009-04-20 06:54:31 +0000782 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000783
Fariborz Jahanian0b1ccdc2009-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 Dunbar59e476b2009-08-03 17:06:42 +0000787
Fariborz Jahanian0b1ccdc2009-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 Dunbar59e476b2009-08-03 17:06:42 +0000791
Fariborz Jahanian9e3ad522009-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 Dunbar59e476b2009-08-03 17:06:42 +0000795
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +0000796 llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);
797
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000798 /// BuildIvarLayout - Builds ivar layout bitmap for the class
799 /// implementation for the __strong or __weak case.
800 ///
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000801 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
802 bool ForStrongLayout);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +0000803
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +0000804 llvm::Constant *BuildIvarLayoutBitmap(std::string &BitMap);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000805
Daniel Dunbar15bd8882009-05-03 14:10:34 +0000806 void BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000807 unsigned int BytePos, bool ForStrongLayout,
808 bool &HasUnion);
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +0000809 void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000810 const llvm::StructLayout *Layout,
Fariborz Jahanian524bb202009-03-10 16:22:08 +0000811 const RecordDecl *RD,
Chris Lattner5b36ddb2009-03-31 08:48:01 +0000812 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +0000813 unsigned int BytePos, bool ForStrongLayout,
Fariborz Jahaniana123b642009-04-24 16:17:09 +0000814 bool &HasUnion);
Fariborz Jahanian1bf72882009-03-12 22:50:49 +0000815
Fariborz Jahanian01dff422009-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 Dunbar59e476b2009-08-03 17:06:42 +0000820
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000821 /// EmitPropertyList - Emit the given property list. The return
822 /// value has type PropertyListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000823 llvm::Constant *EmitPropertyList(llvm::Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000824 const Decl *Container,
Fariborz Jahanian066347e2009-01-28 22:18:42 +0000825 const ObjCContainerDecl *OCD,
826 const ObjCCommonTypesHelper &ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000827
Fariborz Jahanian751c1e72009-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 Jahanian56b3b772009-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 Jahanian67726212009-03-08 20:18:37 +0000839
Daniel Dunbar30c65362009-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 Lattnerf56501c2009-07-17 23:57:13 +0000845 /// global to the "llvm.used" list.
Daniel Dunbar463cc8a2009-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 Dunbar4527d302009-04-14 17:42:51 +0000853 /// "llvm.used".
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000854 llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +0000855 llvm::Constant *Init,
856 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +0000857 unsigned Align,
858 bool AddToUsed);
Daniel Dunbar30c65362009-03-09 20:09:19 +0000859
John McCall9e8bb002011-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 Dunbarf5c18462009-04-20 06:54:31 +0000870
Daniel Dunbar5e639272010-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 Jahanian279eda62009-01-21 22:04:16 +0000875public:
Owen Andersonae86c192009-07-13 04:10:07 +0000876 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
Mike Stump11289f42009-09-09 15:08:12 +0000877 CGM(cgm), VMContext(cgm.getLLVMContext()) { }
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000878
David Chisnall481e3a82010-01-23 02:40:42 +0000879 virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000880
Fariborz Jahanian99113fd2009-01-26 21:38:32 +0000881 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
882 const ObjCContainerDecl *CD=0);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000883
Fariborz Jahanian56b3b772009-01-29 19:24:30 +0000884 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000885
Fariborz Jahanian56b3b772009-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 Dunbar59e476b2009-08-03 17:06:42 +0000890
Fariborz Jahanian56b3b772009-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 McCall351762c2011-02-07 10:33:21 +0000896 virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
897 const CGBlockInfo &blockInfo);
Fariborz Jahanianc05349e2010-08-04 16:57:49 +0000898
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000899};
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000900
Fariborz Jahanian279eda62009-01-21 22:04:16 +0000901class CGObjCMac : public CGObjCCommonMac {
902private:
903 ObjCTypesHelper ObjCTypes;
Daniel Dunbar3ad53482008-08-11 21:35:06 +0000904
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000905 /// EmitModuleInfo - Another marker encoding module level
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000906 /// information.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000907 void EmitModuleInfo();
908
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000909 /// EmitModuleSymols - Emit module symbols, the list of defined
910 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +0000911 llvm::Constant *EmitModuleSymbols();
912
Daniel Dunbar3ad53482008-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 Dunbarb036db82008-08-13 03:21:16 +0000916
Daniel Dunbar22d82ed2008-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 Dunbar59e476b2009-08-03 17:06:42 +0000924 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000925 const ObjCInterfaceDecl *ID);
Fariborz Jahanianeb80c982009-11-12 20:14:24 +0000926
927 /// EmitSuperClassRef - Emits reference to class's main metadata class.
928 llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
Daniel Dunbar22d82ed2008-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 Jahanianb042a592009-01-28 19:12:34 +0000936 bool ForClass);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000937
Daniel Dunbarca8531a2008-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 Dunbar22d82ed2008-08-21 04:36:09 +0000943 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarca8531a2008-08-25 08:19:24 +0000944 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000945 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
946 llvm::Constant *Protocols,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000947 const ConstantVector &Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000948
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000949 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000950
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000951 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000952
953 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar89654ee2008-08-26 08:29:31 +0000954 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000955 llvm::Constant *EmitMethodList(llvm::Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +0000956 const char *Section,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000957 const ConstantVector &Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +0000958
959 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar59e476b2009-08-03 17:06:42 +0000960 /// method declarations.
Daniel Dunbarb036db82008-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 Dunbar349e6fb2009-10-18 20:48:59 +0000970 llvm::Constant *EmitMethodDescList(llvm::Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +0000971 const char *Section,
972 const ConstantVector &Methods);
Daniel Dunbarb036db82008-08-13 03:21:16 +0000973
Daniel Dunbarc475d422008-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 Jahanian56b3b772009-01-29 19:24:30 +0000977 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-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 Jahanian56b3b772009-01-29 19:24:30 +0000983 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbarc475d422008-10-29 22:36:39 +0000984
Daniel Dunbarb036db82008-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 Dunbareb1f9a22008-08-27 02:31:56 +0000989 llvm::Constant *
990 EmitProtocolExtension(const ObjCProtocolDecl *PD,
991 const ConstantVector &OptInstanceMethods,
992 const ConstantVector &OptClassMethods);
Daniel Dunbarb036db82008-08-13 03:21:16 +0000993
994 /// EmitProtocolList - Generate the list of referenced
995 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +0000996 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +0000997 ObjCProtocolDecl::protocol_iterator begin,
998 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarb036db82008-08-13 03:21:16 +0000999
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001000 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1001 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001002 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1003 bool lval=false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001004
1005public:
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001006 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001007
Fariborz Jahanian71394042009-01-23 23:53:38 +00001008 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001009
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001010 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001011 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001012 QualType ResultType,
1013 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001014 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001015 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001016 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001017 const ObjCMethodDecl *Method);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001018
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001019 virtual CodeGen::RValue
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001020 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001021 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001022 QualType ResultType,
1023 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001024 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001025 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001026 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001027 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001028 const CallArgList &CallArgs,
1029 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001030
Daniel Dunbarcb463852008-11-01 01:53:16 +00001031 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001032 const ObjCInterfaceDecl *ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001033
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001034 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
1035 bool lval = false);
Fariborz Jahanianf3648b82009-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 McCall2ca705e2010-07-24 00:37:23 +00001042 virtual llvm::Constant *GetEHType(QualType T);
1043
Daniel Dunbar92992502008-08-15 22:20:32 +00001044 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001045
Daniel Dunbar92992502008-08-15 22:20:32 +00001046 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001047
Daniel Dunbarcb463852008-11-01 01:53:16 +00001048 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001049 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001050
Chris Lattnerd4808922009-03-22 21:03:39 +00001051 virtual llvm::Constant *GetPropertyGetFunction();
1052 virtual llvm::Constant *GetPropertySetFunction();
David Chisnall168b80f2010-12-26 22:13:16 +00001053 virtual llvm::Constant *GetGetStructFunction();
1054 virtual llvm::Constant *GetSetStructFunction();
Chris Lattnerd4808922009-03-22 21:03:39 +00001055 virtual llvm::Constant *EnumerationMutationFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001056
John McCallbd309292010-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 Carlsson1963b0c2008-09-09 10:04:29 +00001062 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1063 const ObjCAtThrowStmt &S);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001064 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001065 llvm::Value *AddrWeakObj);
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00001066 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001067 llvm::Value *src, llvm::Value *dst);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001068 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001069 llvm::Value *src, llvm::Value *dest,
1070 bool threadlocal = false);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00001071 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001072 llvm::Value *src, llvm::Value *dest,
1073 llvm::Value *ivarOffset);
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00001074 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1075 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001076 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1077 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001078 llvm::Value *size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001079
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001080 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1081 QualType ObjectTy,
1082 llvm::Value *BaseValue,
1083 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001084 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001085 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001086 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001087 const ObjCIvarDecl *Ivar);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001088};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001089
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001090class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001091private:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001092 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanian71394042009-01-23 23:53:38 +00001093 llvm::GlobalVariable* ObjCEmptyCacheVar;
1094 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001095
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001096 /// SuperClassReferences - uniqued super class references.
1097 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001098
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001099 /// MetaClassReferences - uniqued meta class references.
1100 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001101
1102 /// EHTypeReferences - uniqued class ehtype references.
1103 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001104
John McCall9e8bb002011-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 Dunbar59e476b2009-08-03 17:06:42 +00001108
Fariborz Jahanian67260552009-11-17 21:37:35 +00001109 /// DefinedMetaClasses - List of defined meta-classes.
1110 std::vector<llvm::GlobalValue*> DefinedMetaClasses;
1111
John McCall9e8bb002011-05-14 03:10:52 +00001112 /// isVTableDispatchedSelector - Returns true if SEL is a
1113 /// vtable-based selector.
1114 bool isVTableDispatchedSelector(Selector Sel);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001115
Fariborz Jahanian71394042009-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 Dunbar8f28d012009-04-08 04:21:03 +00001119
Daniel Dunbar19573e72009-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 Dunbar59e476b2009-08-03 17:06:42 +00001126 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
1127 unsigned InstanceStart,
1128 unsigned InstanceSize,
1129 const ObjCImplementationDecl *ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001130 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001131 llvm::Constant *IsAGV,
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00001132 llvm::Constant *SuperClassGV,
Fariborz Jahanian82208252009-01-31 00:59:10 +00001133 llvm::Constant *ClassRoGV,
1134 bool HiddenVisibility);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001135
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001136 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001137
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00001138 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001139
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001140 /// EmitMethodList - Emit the method list for the given
1141 /// implementation. The return value has type MethodListnfABITy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001142 llvm::Constant *EmitMethodList(llvm::Twine Name,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00001143 const char *Section,
Fariborz Jahanian7415caa2009-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 Dunbar59e476b2009-08-03 17:06:42 +00001151
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001152 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00001153 const ObjCIvarDecl *Ivar,
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00001154 unsigned long int offset);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001155
Fariborz Jahanian56b3b772009-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 Dunbar59e476b2009-08-03 17:06:42 +00001160
Fariborz Jahanian56b3b772009-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 Dunbar59e476b2009-08-03 17:06:42 +00001166
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001167 /// EmitProtocolList - Generate the list of referenced
1168 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001169 llvm::Constant *EmitProtocolList(llvm::Twine Name,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001170 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00001171 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001172
John McCall9e8bb002011-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 Dunbarc6928bb2009-03-01 04:40:10 +00001182
1183 /// GetClassGlobal - Return the global variable for the Objective-C
1184 /// class of the given name.
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00001185 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001186
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001187 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001188 /// for the given class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001189 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001190 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001191
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00001192 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
1193 /// for the given super class reference.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001194 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
1195 const ObjCInterfaceDecl *ID);
1196
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001197 /// EmitMetaClassRef - Return a Value * of the address of _class_t
1198 /// meta-data
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001199 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00001200 const ObjCInterfaceDecl *ID);
1201
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00001202 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
1203 /// the given ivar.
1204 ///
Daniel Dunbara1060522009-04-19 00:31:15 +00001205 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001206 const ObjCInterfaceDecl *ID,
1207 const ObjCIvarDecl *Ivar);
1208
Fariborz Jahanian74b77222009-02-11 20:51:17 +00001209 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
1210 /// for the given selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001211 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
1212 bool lval=false);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001213
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001214 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbarb1559a42009-03-01 04:46:24 +00001215 /// interface. The return value has type EHTypePtrTy.
John McCall2ca705e2010-07-24 00:37:23 +00001216 llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001217 bool ForDefinition);
Daniel Dunbar15894b72009-04-07 05:48:37 +00001218
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001219 const char *getMetaclassSymbolPrefix() const {
Daniel Dunbar15894b72009-04-07 05:48:37 +00001220 return "OBJC_METACLASS_$_";
1221 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001222
Daniel Dunbar15894b72009-04-07 05:48:37 +00001223 const char *getClassSymbolPrefix() const {
1224 return "OBJC_CLASS_$_";
1225 }
1226
Daniel Dunbar961202372009-05-03 12:57:56 +00001227 void GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00001228 uint32_t &InstanceStart,
1229 uint32_t &InstanceSize);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001230
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001231 // Shamelessly stolen from Analysis/CFRefCount.cpp
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001232 Selector GetNullarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001233 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1234 return CGM.getContext().Selectors.getSelector(0, &II);
1235 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001236
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001237 Selector GetUnarySelector(const char* name) const {
Fariborz Jahaniane4128642009-05-12 20:06:41 +00001238 IdentifierInfo* II = &CGM.getContext().Idents.get(name);
1239 return CGM.getContext().Selectors.getSelector(1, &II);
1240 }
Daniel Dunbar554fd792009-04-19 23:41:48 +00001241
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001242 /// ImplementationIsNonLazy - Check whether the given category or
1243 /// class implementation is "non-lazy".
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00001244 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00001245
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001246public:
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00001247 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001248 // FIXME. All stubs for now!
1249 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001250
Fariborz Jahanian71394042009-01-23 23:53:38 +00001251 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001252 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001253 QualType ResultType,
1254 Selector Sel,
1255 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001256 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001257 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001258 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001259
1260 virtual CodeGen::RValue
Fariborz Jahanian71394042009-01-23 23:53:38 +00001261 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001262 ReturnValueSlot Return,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001263 QualType ResultType,
1264 Selector Sel,
1265 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001266 bool isCategoryImpl,
Fariborz Jahanian71394042009-01-23 23:53:38 +00001267 llvm::Value *Receiver,
1268 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001269 const CallArgList &CallArgs,
1270 const ObjCMethodDecl *Method);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001271
Fariborz Jahanian71394042009-01-23 23:53:38 +00001272 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00001273 const ObjCInterfaceDecl *ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001274
Fariborz Jahanian9240f3d2010-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 Jahanianf3648b82009-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 Dunbar59e476b2009-08-03 17:06:42 +00001284
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00001285 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001286
Fariborz Jahanian71394042009-01-23 23:53:38 +00001287 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001288 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian097feda2009-01-30 18:58:59 +00001289 const ObjCProtocolDecl *PD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001290
John McCall2ca705e2010-07-24 00:37:23 +00001291 virtual llvm::Constant *GetEHType(QualType T);
1292
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001293 virtual llvm::Constant *GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001294 return ObjCTypes.getGetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001295 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001296 virtual llvm::Constant *GetPropertySetFunction() {
1297 return ObjCTypes.getSetPropertyFn();
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001298 }
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001299
David Chisnall168b80f2010-12-26 22:13:16 +00001300 virtual llvm::Constant *GetSetStructFunction() {
1301 return ObjCTypes.getCopyStructFn();
1302 }
1303 virtual llvm::Constant *GetGetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00001304 return ObjCTypes.getCopyStructFn();
1305 }
1306
Chris Lattnerd4808922009-03-22 21:03:39 +00001307 virtual llvm::Constant *EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00001308 return ObjCTypes.getEnumerationMutationFn();
Daniel Dunbard73ea8162009-02-16 18:48:45 +00001309 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001310
John McCallbd309292010-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 Jahanian71394042009-01-23 23:53:38 +00001315 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlsson9ab53d12009-02-16 22:59:18 +00001316 const ObjCAtThrowStmt &S);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001317 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001318 llvm::Value *AddrWeakObj);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001319 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001320 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001321 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian217af242010-07-20 20:30:03 +00001322 llvm::Value *src, llvm::Value *dest,
1323 bool threadlocal = false);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001324 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00001325 llvm::Value *src, llvm::Value *dest,
1326 llvm::Value *ivarOffset);
Fariborz Jahanian71394042009-01-23 23:53:38 +00001327 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian06292952009-02-16 22:52:32 +00001328 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00001329 virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
1330 llvm::Value *dest, llvm::Value *src,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00001331 llvm::Value *size);
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001332 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1333 QualType ObjectTy,
1334 llvm::Value *BaseValue,
1335 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00001336 unsigned CVRQualifiers);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001337 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00001338 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00001339 const ObjCIvarDecl *Ivar);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001340};
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001341
John McCall5880fb82011-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 Dunbar303e2c22008-08-11 02:45:11 +00001382} // end anonymous namespace
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001383
1384/* *** Helper Functions *** */
1385
1386/// getConstantGEP() - Help routine to construct simple GEPs.
Owen Anderson170229f2009-07-14 23:10:40 +00001387static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001388 llvm::Constant *C,
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001389 unsigned idx0,
1390 unsigned idx1) {
1391 llvm::Value *Idxs[] = {
Owen Anderson41a75022009-08-13 21:57:51 +00001392 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
1393 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001394 };
Owen Andersonade90fd2009-07-29 18:54:39 +00001395 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001396}
1397
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001398/// hasObjCExceptionAttribute - Return true if this class or any super
1399/// class has the __objc_exception__ attribute.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001400static bool hasObjCExceptionAttribute(ASTContext &Context,
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001401 const ObjCInterfaceDecl *OID) {
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +00001402 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001403 return true;
1404 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
Douglas Gregor78bd61f2009-06-18 16:11:24 +00001405 return hasObjCExceptionAttribute(Context, Super);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00001406 return false;
1407}
1408
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00001409/* *** CGObjCMac Public Interface *** */
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001410
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001411CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00001412 ObjCTypes(cgm) {
Fariborz Jahanian279eda62009-01-21 22:04:16 +00001413 ObjCABI = 1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001414 EmitImageInfo();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001415}
1416
Daniel Dunbar7c6d3a72008-08-16 00:25:02 +00001417/// GetClass - Return a reference to the class for the given interface
1418/// decl.
Daniel Dunbarcb463852008-11-01 01:53:16 +00001419llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001420 const ObjCInterfaceDecl *ID) {
1421 return EmitClassRef(Builder, ID);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001422}
1423
1424/// GetSelector - Return the pointer to the unique'd string for this selector.
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00001425llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
1426 bool lval) {
1427 return EmitSelector(Builder, Sel, lval);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001428}
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001429llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001430 *Method) {
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001431 return EmitSelector(Builder, Method->getSelector());
1432}
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001433
John McCall2ca705e2010-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 Dunbar8b8683f2008-08-12 00:12:39 +00001439/// Generate a constant CFString object.
Daniel Dunbar59e476b2009-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 Dunbar8b8683f2008-08-12 00:12:39 +00001447*/
1448
Fariborz Jahanian63408e82010-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 Jahanian71394042009-01-23 23:53:38 +00001458llvm::Constant *CGObjCCommonMac::GenerateConstantString(
David Chisnall481e3a82010-01-23 02:40:42 +00001459 const StringLiteral *SL) {
Fariborz Jahanian63408e82010-04-22 20:26:39 +00001460 return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
1461 CGM.GetAddrOfConstantCFString(SL) :
Fariborz Jahanian50c925f2010-10-19 17:19:29 +00001462 CGM.GetAddrOfConstantString(SL));
Daniel Dunbar303e2c22008-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 Dunbar97db84c2008-08-23 03:46:30 +00001468CodeGen::RValue
1469CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001470 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001471 QualType ResultType,
1472 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001473 const ObjCInterfaceDecl *Class,
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00001474 bool isCategoryImpl,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001475 llvm::Value *Receiver,
Daniel Dunbarc722b852008-08-30 03:02:31 +00001476 bool IsClassMessage,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001477 const CodeGen::CallArgList &CallArgs,
1478 const ObjCMethodDecl *Method) {
Daniel Dunbarf6397fe2008-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 Dunbar59e476b2009-08-03 17:06:42 +00001481 llvm::Value *ObjCSuper =
John McCall66475842011-03-04 08:00:29 +00001482 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001483 llvm::Value *ReceiverAsObject =
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001484 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001485 CGF.Builder.CreateStore(ReceiverAsObject,
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001486 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbarf6397fe2008-08-23 04:28:29 +00001487
Daniel Dunbarca8531a2008-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 Jahanianbac73ac2009-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 Stump658fe022009-07-30 22:28:39 +00001501 } else {
Fariborz Jahanianbac73ac2009-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 Dunbar59e476b2009-08-03 17:06:42 +00001506 }
Fariborz Jahanianda2efb02009-11-14 02:18:31 +00001507 }
1508 else if (isCategoryImpl)
1509 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1510 else {
Fariborz Jahanianeb80c982009-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 Dunbarca8531a2008-08-25 08:19:24 +00001514 }
Mike Stump18bb9282009-05-16 07:57:57 +00001515 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
1516 // ObjCTypes types.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001517 const llvm::Type *ClassTy =
Daniel Dunbarc722b852008-08-30 03:02:31 +00001518 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbarc475d422008-10-29 22:36:39 +00001519 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001520 CGF.Builder.CreateStore(Target,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001521 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
John McCall9e8bb002011-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 Dunbar303e2c22008-08-11 02:45:11 +00001526}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001527
1528/// Generate code for a message send expression.
Daniel Dunbar97db84c2008-08-23 03:46:30 +00001529CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00001530 ReturnValueSlot Return,
Daniel Dunbar4b8c6db2008-08-30 05:35:15 +00001531 QualType ResultType,
1532 Selector Sel,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00001533 llvm::Value *Receiver,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001534 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00001535 const ObjCInterfaceDecl *Class,
Fariborz Jahanianf3648b82009-05-05 21:36:57 +00001536 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-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 Dunbar97ff50d2008-08-23 09:25:55 +00001541}
1542
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00001543CodeGen::RValue
John McCall9e8bb002011-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 Dunbarc722b852008-08-30 03:02:31 +00001554 CallArgList ActualArgs;
Fariborz Jahanian969bc682009-04-24 21:07:43 +00001555 if (!IsSuper)
1556 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Eli Friedman43dca6a2011-05-02 17:57:46 +00001557 ActualArgs.add(RValue::get(Arg0), Arg0Ty);
1558 ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
Daniel Dunbarc722b852008-08-30 03:02:31 +00001559 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001560
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00001561 CodeGenTypes &Types = CGM.getTypes();
John McCallab26cfa2010-02-05 21:31:56 +00001562 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
Rafael Espindolac50c27c2010-03-30 20:24:48 +00001563 FunctionType::ExtInfo());
Daniel Dunbardf0e62d2009-09-17 04:01:40 +00001564 const llvm::FunctionType *FTy =
1565 Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001566
Anders Carlsson280e61f12010-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 McCall5880fb82011-05-14 21:12:11 +00001572 NullReturnState nullReturn;
1573
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001574 llvm::Constant *Fn = NULL;
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001575 if (CGM.ReturnTypeUsesSRet(FnInfo)) {
John McCall5880fb82011-05-14 21:12:11 +00001576 if (!IsSuper) nullReturn.init(CGF, Arg0);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001577 Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001578 : ObjCTypes.getSendStretFn(IsSuper);
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001579 } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
1580 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
1581 : ObjCTypes.getSendFpretFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001582 } else {
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00001583 Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001584 : ObjCTypes.getSendFn(IsSuper);
Daniel Dunbar3c683f5b2008-10-17 03:24:53 +00001585 }
Daniel Dunbar6f2e8392010-07-14 23:39:36 +00001586 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
John McCall5880fb82011-05-14 21:12:11 +00001587 RValue rvalue = CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
1588 return nullReturn.complete(CGF, rvalue, ResultType);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001589}
1590
Fariborz Jahanian9659f6b2010-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 McCall351762c2011-02-07 10:33:21 +00001607llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
1608 const CGBlockInfo &blockInfo) {
1609 llvm::Constant *nullPtr =
Fariborz Jahanianafa3c0a2010-08-04 18:44:59 +00001610 llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
John McCall351762c2011-02-07 10:33:21 +00001611
Fariborz Jahanian0aa35b92010-09-13 16:09:44 +00001612 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
John McCall351762c2011-02-07 10:33:21 +00001613 return nullPtr;
1614
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001615 bool hasUnion = false;
Fariborz Jahanian9659f6b2010-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 Jahaniancfddabf2010-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 McCall351762c2011-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 Jahanian933c6722010-09-11 01:27:29 +00001650 continue;
John McCall351762c2011-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 Jahanian903aba32010-08-05 21:00:25 +00001656 continue;
1657 }
Fariborz Jahanianf95e3582010-08-06 16:28:55 +00001658
John McCall351762c2011-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 Jahanian9659f6b2010-08-04 23:55:24 +00001665 else if (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak)
John McCall351762c2011-02-07 10:33:21 +00001666 SkipIvars.push_back(GC_IVAR(fieldOffset,
1667 fieldSize / ByteSizeInBits));
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00001668 }
1669
1670 if (IvarsInfo.empty())
John McCall351762c2011-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 Jahanian9659f6b2010-08-04 23:55:24 +00001677
1678 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00001679 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-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 Jahanianc05349e2010-08-04 16:57:49 +00001692}
1693
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001694llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar89da6ad2008-08-13 00:59:25 +00001695 const ObjCProtocolDecl *PD) {
Daniel Dunbar7050c552008-09-04 04:33:15 +00001696 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00001697 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbar7050c552008-09-04 04:33:15 +00001698 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1699
Owen Andersonade90fd2009-07-29 18:54:39 +00001700 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
Daniel Dunbarb036db82008-08-13 03:21:16 +00001701 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00001702}
1703
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001704void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Mike Stump18bb9282009-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 Dunbarc475d422008-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 Dunbar59e476b2009-08-03 17:06:42 +00001712 if (Protocols.count(PD->getIdentifier()))
Daniel Dunbarc475d422008-10-29 22:36:39 +00001713 GetOrEmitProtocol(PD);
1714}
1715
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00001716llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001717 if (DefinedProtocols.count(PD->getIdentifier()))
1718 return GetOrEmitProtocol(PD);
1719 return GetOrEmitProtocolRef(PD);
1720}
1721
Daniel Dunbarb036db82008-08-13 03:21:16 +00001722/*
Daniel Dunbar59e476b2009-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 Dunbarb036db82008-08-13 03:21:16 +00001731
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001732See EmitProtocolExtension().
Daniel Dunbarb036db82008-08-13 03:21:16 +00001733*/
Daniel Dunbarc475d422008-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 Dunbarc61d0e92008-08-25 06:02:07 +00001741 // FIXME: I don't understand why gcc generates this, or where it is
Mike Stump18bb9282009-05-16 07:57:57 +00001742 // resolved. Investigate. Its also wasteful to look this up over and over.
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00001743 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1744
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001745 // Construct method lists.
1746 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1747 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001748 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00001749 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-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 Dunbar59e476b2009-08-03 17:06:42 +00001756 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001757 }
1758
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001759 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00001760 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Daniel Dunbareb1f9a22008-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 Dunbar59e476b2009-08-03 17:06:42 +00001767 }
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001768 }
1769
Daniel Dunbarb036db82008-08-13 03:21:16 +00001770 std::vector<llvm::Constant*> Values(5);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001771 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001772 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001773 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001774 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
Daniel Dunbardec75f82008-08-21 21:57:41 +00001775 PD->protocol_begin(),
1776 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001777 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001778 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001779 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1780 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001781 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001782 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001783 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1784 ClassMethods);
Owen Anderson0e0189d2009-07-27 22:29:56 +00001785 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001786 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001787
Daniel Dunbarb036db82008-08-13 03:21:16 +00001788 if (Entry) {
Daniel Dunbarc475d422008-10-29 22:36:39 +00001789 // Already created, fix the linkage and update the initializer.
1790 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001791 Entry->setInitializer(Init);
1792 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001793 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00001794 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarb036db82008-08-13 03:21:16 +00001795 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001796 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001797 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00001798 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00001799 // FIXME: Is this necessary? Why only for protocol?
1800 Entry->setAlignment(4);
1801 }
Chris Lattnerf56501c2009-07-17 23:57:13 +00001802 CGM.AddUsedGlobal(Entry);
Daniel Dunbarc475d422008-10-29 22:36:39 +00001803
1804 return Entry;
Daniel Dunbarb036db82008-08-13 03:21:16 +00001805}
1806
Daniel Dunbarc475d422008-10-29 22:36:39 +00001807llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001808 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1809
1810 if (!Entry) {
Daniel Dunbarc475d422008-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 Dunbar59e476b2009-08-03 17:06:42 +00001814 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00001815 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
Daniel Dunbarc475d422008-10-29 22:36:39 +00001816 llvm::GlobalValue::ExternalLinkage,
1817 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001818 "\01L_OBJC_PROTOCOL_" + PD->getName());
Daniel Dunbarb036db82008-08-13 03:21:16 +00001819 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbarb036db82008-08-13 03:21:16 +00001820 // FIXME: Is this necessary? Why only for protocol?
1821 Entry->setAlignment(4);
1822 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001823
Daniel Dunbarb036db82008-08-13 03:21:16 +00001824 return Entry;
1825}
1826
1827/*
1828 struct _objc_protocol_extension {
Daniel Dunbar59e476b2009-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 Dunbarb036db82008-08-13 03:21:16 +00001833 };
1834*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001835llvm::Constant *
1836CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1837 const ConstantVector &OptInstanceMethods,
1838 const ConstantVector &OptClassMethods) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001839 uint64_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00001840 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001841 std::vector<llvm::Constant*> Values(4);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001842 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001843 Values[1] =
1844 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001845 + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001846 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1847 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001848 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001849 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001850 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1851 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001852 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00001853 0, PD, ObjCTypes);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001854
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001855 // Return null if no extension bits are used.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001856 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
Daniel Dunbarb036db82008-08-13 03:21:16 +00001857 Values[3]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00001858 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001859
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001860 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00001861 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001862
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001863 // No special section, but goes in llvm.used
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001864 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001865 Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001866 0, 0, true);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001867}
1868
1869/*
1870 struct objc_protocol_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001871 struct objc_protocol_list *next;
1872 long count;
1873 Protocol *list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00001874 };
1875*/
Daniel Dunbardec75f82008-08-21 21:57:41 +00001876llvm::Constant *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001877CGObjCMac::EmitProtocolList(llvm::Twine Name,
Daniel Dunbardec75f82008-08-21 21:57:41 +00001878 ObjCProtocolDecl::protocol_iterator begin,
1879 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00001880 std::vector<llvm::Constant*> ProtocolRefs;
1881
Daniel Dunbardec75f82008-08-21 21:57:41 +00001882 for (; begin != end; ++begin)
1883 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarb036db82008-08-13 03:21:16 +00001884
1885 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001886 if (ProtocolRefs.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00001887 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001888
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001889 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00001890 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
Daniel Dunbarb036db82008-08-13 03:21:16 +00001891
1892 std::vector<llvm::Constant*> Values(3);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00001893 // This field is only used by the runtime.
Owen Anderson0b75f232009-07-31 20:28:54 +00001894 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00001895 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbar59e476b2009-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 Dunbarb036db82008-08-13 03:21:16 +00001900 ProtocolRefs);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001901
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00001902 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001903 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00001904 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00001905 4, false);
Owen Andersonade90fd2009-07-29 18:54:39 +00001906 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00001907}
1908
Fariborz Jahanian751c1e72009-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 Dunbarb036db82008-08-13 03:21:16 +00001929/*
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001930 struct _objc_property {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001931 const char * const name;
1932 const char * const attributes;
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001933 };
1934
1935 struct _objc_property_list {
Daniel Dunbar59e476b2009-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 Dunbar80a840b2008-08-23 00:19:03 +00001939 };
1940*/
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00001941llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001942 const Decl *Container,
1943 const ObjCContainerDecl *OCD,
1944 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001945 std::vector<llvm::Constant*> Properties, Prop(2);
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00001946 llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001947 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1948 E = OCD->prop_end(); I != E; ++I) {
Steve Naroffba3dc382009-01-11 12:47:58 +00001949 const ObjCPropertyDecl *PD = *I;
Fariborz Jahanian751c1e72009-12-12 21:26:21 +00001950 PropertySet.insert(PD->getIdentifier());
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001951 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbar4932b362008-08-28 04:38:10 +00001952 Prop[1] = GetPropertyTypeString(PD, Container);
Owen Anderson0e0189d2009-07-27 22:29:56 +00001953 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001954 Prop));
1955 }
Fariborz Jahanian7966aff2010-06-22 16:33:55 +00001956 if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
Ted Kremenek0ef508d2010-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 Jahanian7966aff2010-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 Dunbar80a840b2008-08-23 00:19:03 +00001969
1970 // Return null for empty list.
1971 if (Properties.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00001972 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001973
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001974 unsigned PropertySize =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00001975 CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001976 std::vector<llvm::Constant*> Values(3);
Owen Andersonb7a2fe62009-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 Dunbar59e476b2009-08-03 17:06:42 +00001979 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001980 Properties.size());
Owen Anderson47034e12009-07-28 18:33:04 +00001981 Values[2] = llvm::ConstantArray::get(AT, Properties);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00001982 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001983
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001984 llvm::GlobalVariable *GV =
1985 CreateMetadataVar(Name, Init,
1986 (ObjCABI == 2) ? "__DATA, __objc_const" :
Daniel Dunbarb25452a2009-04-15 02:56:18 +00001987 "__OBJC,__property,regular,no_dead_strip",
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001988 (ObjCABI == 2) ? 8 : 4,
Daniel Dunbarb25452a2009-04-15 02:56:18 +00001989 true);
Owen Andersonade90fd2009-07-29 18:54:39 +00001990 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00001991}
1992
1993/*
Daniel Dunbarb036db82008-08-13 03:21:16 +00001994 struct objc_method_description_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00001995 int count;
1996 struct objc_method_description list[];
Daniel Dunbarb036db82008-08-13 03:21:16 +00001997 };
1998*/
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00001999llvm::Constant *
2000CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
2001 std::vector<llvm::Constant*> Desc(2);
Owen Anderson170229f2009-07-14 23:10:40 +00002002 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002003 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
2004 ObjCTypes.SelectorPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002005 Desc[1] = GetMethodVarType(MD);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002006 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002007 Desc);
2008}
Daniel Dunbarb036db82008-08-13 03:21:16 +00002009
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002010llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002011 const char *Section,
2012 const ConstantVector &Methods) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00002013 // Return null for empty list.
2014 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002015 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002016
2017 std::vector<llvm::Constant*> Values(2);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002018 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002019 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002020 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002021 Values[1] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002022 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbarb036db82008-08-13 03:21:16 +00002023
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002024 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002025 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbarb036db82008-08-13 03:21:16 +00002026 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002027}
2028
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002029/*
2030 struct _objc_category {
Daniel Dunbar59e476b2009-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 Dunbar938a77f2008-08-22 20:34:54 +00002038 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002039*/
Daniel Dunbar92992502008-08-15 22:20:32 +00002040void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002041 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002042
Mike Stump18bb9282009-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 Dunbar938a77f2008-08-22 20:34:54 +00002047 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002048 const ObjCCategoryDecl *Category =
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002049 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002050
2051 llvm::SmallString<256> ExtName;
2052 llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
2053 << OCD->getName();
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002054
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002055 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002056 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002057 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002058 // Instance methods should always be defined.
2059 InstanceMethods.push_back(GetMethodConstant(*i));
2060 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002061 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002062 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002063 // Class methods should always be defined.
2064 ClassMethods.push_back(GetMethodConstant(*i));
2065 }
2066
Daniel Dunbar938a77f2008-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 Jahaniane55f8662009-04-29 20:40:05 +00002070 LazySymbols.insert(Interface->getIdentifier());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002071 Values[2] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002072 EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002073 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002074 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002075 Values[3] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002076 EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002077 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002078 ClassMethods);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002079 if (Category) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002080 Values[4] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002081 EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002082 Category->protocol_begin(),
2083 Category->protocol_end());
2084 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002085 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002086 }
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002087 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002088
2089 // If there is no category @interface then there can be no properties.
2090 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002091 Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002092 OCD, Category, ObjCTypes);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002093 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002094 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Daniel Dunbar28e76ca2008-08-26 23:03:11 +00002095 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002096
Owen Anderson0e0189d2009-07-27 22:29:56 +00002097 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002098 Values);
2099
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002100 llvm::GlobalVariable *GV =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002101 CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002102 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002103 4, true);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002104 DefinedCategories.push_back(GV);
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00002105 DefinedCategoryNames.insert(ExtName.str());
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002106 // method definition entries must be clear for next implementation.
2107 MethodDefinitions.clear();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002108}
2109
Daniel Dunbar22d82ed2008-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 Dunbar22d82ed2008-08-21 04:36:09 +00002121/*
2122 struct _objc_class {
Daniel Dunbar59e476b2009-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 Dunbar22d82ed2008-08-21 04:36:09 +00002136 };
2137
2138 See EmitClassExtension();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002139*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002140void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002141 DefinedSymbols.insert(ID->getIdentifier());
2142
Chris Lattner86d7d912008-11-24 03:54:41 +00002143 std::string ClassName = ID->getNameAsString();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002144 // FIXME: Gross
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002145 ObjCInterfaceDecl *Interface =
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002146 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002147 llvm::Constant *Protocols =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002148 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00002149 Interface->all_referenced_protocol_begin(),
2150 Interface->all_referenced_protocol_end());
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002151 unsigned Flags = eClassFlags_Factory;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00002152 if (ID->getNumIvarInitializers())
2153 Flags |= eClassFlags_HasCXXStructors;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002154 unsigned Size =
Ken Dyckc8ae5502011-02-09 01:59:34 +00002155 CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002156
2157 // FIXME: Set CXX-structors flag.
John McCall457a04e2010-10-22 21:05:15 +00002158 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002159 Flags |= eClassFlags_Hidden;
2160
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002161 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002162 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002163 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002164 // Instance methods should always be defined.
2165 InstanceMethods.push_back(GetMethodConstant(*i));
2166 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002167 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002168 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002169 // Class methods should always be defined.
2170 ClassMethods.push_back(GetMethodConstant(*i));
2171 }
2172
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002173 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00002174 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Daniel Dunbar3c76cb52008-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 Dunbar22d82ed2008-08-21 04:36:09 +00002189 std::vector<llvm::Constant*> Values(12);
Daniel Dunbarccf61832009-05-03 08:56:52 +00002190 Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002191 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00002192 // Record a reference to the super class.
2193 LazySymbols.insert(Super->getIdentifier());
2194
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002195 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002196 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002197 ObjCTypes.ClassPtrTy);
2198 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002199 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002200 }
2201 Values[ 2] = GetClassName(ID->getIdentifier());
2202 // Version is always 0.
Owen Andersonb7a2fe62009-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 Jahanianb042a592009-01-28 19:12:34 +00002206 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002207 Values[ 7] =
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002208 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
Daniel Dunbar80a840b2008-08-23 00:19:03 +00002209 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002210 InstanceMethods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002211 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002212 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002213 Values[ 9] = Protocols;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002214 Values[10] = BuildIvarLayout(ID, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002215 Values[11] = EmitClassExtension(ID);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002216 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002217 Values);
Fariborz Jahanianeb80c982009-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 Dunbar22d82ed2008-08-21 04:36:09 +00002234 DefinedClasses.push_back(GV);
Fariborz Jahanianc0577942011-04-22 22:02:28 +00002235 // method definition entries must be clear for next implementation.
2236 MethodDefinitions.clear();
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002237}
2238
2239llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
2240 llvm::Constant *Protocols,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002241 const ConstantVector &Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002242 unsigned Flags = eClassFlags_Meta;
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002243 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002244
John McCall457a04e2010-10-22 21:05:15 +00002245 if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002246 Flags |= eClassFlags_Hidden;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002247
Daniel Dunbar22d82ed2008-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 Dunbar59e476b2009-08-03 17:06:42 +00002253 Values[ 0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002254 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002255 ObjCTypes.ClassPtrTy);
Daniel Dunbar938a77f2008-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 Dunbar22d82ed2008-08-21 04:36:09 +00002259 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002260 Values[ 1] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002261 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002262 ObjCTypes.ClassPtrTy);
2263 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00002264 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002265 }
2266 Values[ 2] = GetClassName(ID->getIdentifier());
2267 // Version is always 0.
Owen Andersonb7a2fe62009-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 Jahanianb042a592009-01-28 19:12:34 +00002271 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002272 Values[ 7] =
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002273 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002274 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002275 Methods);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002276 // cache is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002277 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002278 Values[ 9] = Protocols;
2279 // ivar_layout for metaclass is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00002280 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002281 // The class extension is always unused for metaclasses.
Owen Anderson0b75f232009-07-31 20:28:54 +00002282 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002283 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002284 Values);
2285
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002286 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner86d7d912008-11-24 03:54:41 +00002287 Name += ID->getNameAsCString();
Daniel Dunbarca8531a2008-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 Andersonc10c8d32009-07-08 19:05:04 +00002297 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002298 llvm::GlobalValue::InternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002299 Init, Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002300 }
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002301 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbarae333842009-03-09 22:18:41 +00002302 GV->setAlignment(4);
Chris Lattnerf56501c2009-07-17 23:57:13 +00002303 CGM.AddUsedGlobal(GV);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002304
2305 return GV;
2306}
2307
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002308llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerf3d3fae2008-11-24 05:29:24 +00002309 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002310
Mike Stump18bb9282009-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 Dunbarca8531a2008-08-25 08:19:24 +00002315
2316 // Check for an existing forward reference.
Fariborz Jahanian475831b2009-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 Dunbar59e476b2009-08-03 17:06:42 +00002319 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
2320 true)) {
Daniel Dunbarca8531a2008-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 Andersonc10c8d32009-07-08 19:05:04 +00002327 return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002328 llvm::GlobalValue::ExternalLinkage,
2329 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00002330 Name);
Daniel Dunbarca8531a2008-08-25 08:19:24 +00002331 }
2332}
2333
Fariborz Jahanianeb80c982009-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 Dunbar22d82ed2008-08-21 04:36:09 +00002350/*
2351 struct objc_class_ext {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002352 uint32_t size;
2353 const char *weak_ivar_layout;
2354 struct _objc_property_list *properties;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002355 };
2356*/
2357llvm::Constant *
2358CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002359 uint64_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00002360 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002361
2362 std::vector<llvm::Constant*> Values(3);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002363 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian6df69862009-04-22 23:00:43 +00002364 Values[1] = BuildIvarLayout(ID, false);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002365 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
Fariborz Jahanian066347e2009-01-28 22:18:42 +00002366 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002367
2368 // Return null if no extension bits are used.
2369 if (Values[1]->isNullValue() && Values[2]->isNullValue())
Owen Anderson0b75f232009-07-31 20:28:54 +00002370 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002371
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002372 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00002373 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002374 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002375 Init, "__OBJC,__class_ext,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002376 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002377}
2378
2379/*
2380 struct objc_ivar {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002381 char *ivar_name;
2382 char *ivar_type;
2383 int ivar_offset;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002384 };
2385
2386 struct objc_ivar_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002387 int ivar_count;
2388 struct objc_ivar list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002389 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002390*/
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002391llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002392 bool ForClass) {
Daniel Dunbar22d82ed2008-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 Anderson0b75f232009-07-31 20:28:54 +00002401 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002402
2403 ObjCInterfaceDecl *OID =
Fariborz Jahanianb042a592009-01-28 19:12:34 +00002404 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002405
Daniel Dunbarf5c18462009-04-20 06:54:31 +00002406 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian7c809592009-06-04 01:19:09 +00002407 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002408
Daniel Dunbarf5c18462009-04-20 06:54:31 +00002409 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
2410 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian7c809592009-06-04 01:19:09 +00002411 // Ignore unnamed bit-fields.
2412 if (!IVD->getDeclName())
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002413 continue;
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00002414 Ivar[0] = GetMethodVarName(IVD->getIdentifier());
2415 Ivar[1] = GetMethodVarType(IVD);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002416 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00002417 ComputeIvarBaseOffset(CGM, OID, IVD));
Owen Anderson0e0189d2009-07-27 22:29:56 +00002418 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002419 }
2420
2421 // Return null for empty list.
2422 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002423 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002424
2425 std::vector<llvm::Constant*> Values(2);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002426 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002427 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002428 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002429 Values[1] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002430 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002431
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002432 llvm::GlobalVariable *GV;
2433 if (ForClass)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002434 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002435 Init, "__OBJC,__class_vars,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00002436 4, true);
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002437 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002438 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00002439 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002440 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002441 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002442}
2443
2444/*
2445 struct objc_method {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002446 SEL method_name;
2447 char *method_types;
2448 void *method;
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002449 };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002450
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002451 struct objc_method_list {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002452 struct objc_method_list *obsolete;
2453 int count;
2454 struct objc_method methods_list[count];
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002455 };
2456*/
Daniel Dunbar3c76cb52008-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 Dunbareb1f9a22008-08-27 02:31:56 +00002461llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00002462 llvm::Function *Fn = GetMethodDefinition(MD);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002463 if (!Fn)
2464 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002465
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002466 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002467 Method[0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00002468 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002469 ObjCTypes.SelectorPtrTy);
2470 Method[1] = GetMethodVarType(MD);
Owen Andersonade90fd2009-07-29 18:54:39 +00002471 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00002472 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002473}
2474
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002475llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
Daniel Dunbar938a77f2008-08-22 20:34:54 +00002476 const char *Section,
Daniel Dunbareb1f9a22008-08-27 02:31:56 +00002477 const ConstantVector &Methods) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002478 // Return null for empty list.
2479 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00002480 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002481
2482 std::vector<llvm::Constant*> Values(3);
Owen Anderson0b75f232009-07-31 20:28:54 +00002483 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00002484 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00002485 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002486 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00002487 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00002488 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002489
Daniel Dunbarb25452a2009-04-15 02:56:18 +00002490 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00002491 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00002492 ObjCTypes.MethodListPtrTy);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002493}
2494
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00002495llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002496 const ObjCContainerDecl *CD) {
Daniel Dunbard2386812009-10-19 01:21:19 +00002497 llvm::SmallString<256> Name;
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00002498 GetNameForMethod(OMD, CD, Name);
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002499
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002500 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00002501 const llvm::FunctionType *MethodTy =
Daniel Dunbarbf8c24a2009-02-02 23:23:47 +00002502 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002503 llvm::Function *Method =
Daniel Dunbar7a95ca32008-09-10 04:01:49 +00002504 llvm::Function::Create(MethodTy,
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002505 llvm::GlobalValue::InternalLinkage,
Daniel Dunbard2386812009-10-19 01:21:19 +00002506 Name.str(),
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002507 &CGM.getModule());
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00002508 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002509
Daniel Dunbara94ecd22008-08-16 03:19:19 +00002510 return Method;
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002511}
2512
Daniel Dunbar30c65362009-03-09 20:09:19 +00002513llvm::GlobalVariable *
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00002514CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
Daniel Dunbar30c65362009-03-09 20:09:19 +00002515 llvm::Constant *Init,
2516 const char *Section,
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002517 unsigned Align,
2518 bool AddToUsed) {
Daniel Dunbar30c65362009-03-09 20:09:19 +00002519 const llvm::Type *Ty = Init->getType();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002520 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00002521 new llvm::GlobalVariable(CGM.getModule(), Ty, false,
Chris Lattnerf56501c2009-07-17 23:57:13 +00002522 llvm::GlobalValue::InternalLinkage, Init, Name);
Daniel Dunbar30c65362009-03-09 20:09:19 +00002523 if (Section)
2524 GV->setSection(Section);
Daniel Dunbar463cc8a2009-03-09 20:50:13 +00002525 if (Align)
2526 GV->setAlignment(Align);
2527 if (AddToUsed)
Chris Lattnerf56501c2009-07-17 23:57:13 +00002528 CGM.AddUsedGlobal(GV);
Daniel Dunbar30c65362009-03-09 20:09:19 +00002529 return GV;
2530}
2531
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002532llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar3ad53482008-08-11 21:35:06 +00002533 // Abuse this interface function as a place to finalize.
2534 FinishModule();
Daniel Dunbar303e2c22008-08-11 02:45:11 +00002535 return NULL;
2536}
2537
Chris Lattnerd4808922009-03-22 21:03:39 +00002538llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002539 return ObjCTypes.getGetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00002540}
2541
Chris Lattnerd4808922009-03-22 21:03:39 +00002542llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002543 return ObjCTypes.getSetPropertyFn();
Daniel Dunbara91c3e02008-09-24 03:38:44 +00002544}
2545
David Chisnall168b80f2010-12-26 22:13:16 +00002546llvm::Constant *CGObjCMac::GetGetStructFunction() {
2547 return ObjCTypes.getCopyStructFn();
2548}
2549llvm::Constant *CGObjCMac::GetSetStructFunction() {
Fariborz Jahanian5a8c2032010-04-12 18:18:10 +00002550 return ObjCTypes.getCopyStructFn();
2551}
2552
Chris Lattnerd4808922009-03-22 21:03:39 +00002553llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Chris Lattnerce8754e2009-04-22 02:44:54 +00002554 return ObjCTypes.getEnumerationMutationFn();
Anders Carlsson3f35a262008-08-31 04:05:03 +00002555}
2556
John McCallbd309292010-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 McCall65bea082010-07-21 06:59:36 +00002566namespace {
John McCallcda666c2010-07-21 07:22:38 +00002567 struct PerformFragileFinally : EHScopeStack::Cleanup {
John McCall65bea082010-07-21 06:59:36 +00002568 const Stmt &S;
John McCall2dd7d442010-08-04 05:59:32 +00002569 llvm::Value *SyncArgSlot;
John McCall65bea082010-07-21 06:59:36 +00002570 llvm::Value *CallTryExitVar;
2571 llvm::Value *ExceptionData;
2572 ObjCTypesHelper &ObjCTypes;
2573 PerformFragileFinally(const Stmt *S,
John McCall2dd7d442010-08-04 05:59:32 +00002574 llvm::Value *SyncArgSlot,
John McCall65bea082010-07-21 06:59:36 +00002575 llvm::Value *CallTryExitVar,
2576 llvm::Value *ExceptionData,
2577 ObjCTypesHelper *ObjCTypes)
John McCall2dd7d442010-08-04 05:59:32 +00002578 : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
John McCall65bea082010-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 McCallcebe0ca2010-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 McCall65bea082010-07-21 06:59:36 +00002605 CGF.EmitStmt(FinallyStmt->getFinallyBody());
2606
John McCallcebe0ca2010-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 McCall65bea082010-07-21 06:59:36 +00002615 } else {
2616 // Emit objc_sync_exit(expr); as finally's sole statement for
2617 // @synchronized.
John McCall2dd7d442010-08-04 05:59:32 +00002618 llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
John McCall65bea082010-07-21 06:59:36 +00002619 CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
2620 ->setDoesNotThrow();
2621 }
2622 }
2623 };
John McCall42227ed2010-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 McCall2dd7d442010-08-04 05:59:32 +00002640
John McCall42227ed2010-07-31 23:20:56 +00002641 void emitWriteHazard();
John McCall2dd7d442010-08-04 05:59:32 +00002642 void emitHazardsInNewBlocks();
John McCall42227ed2010-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 McCall42227ed2010-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 McCall2dd7d442010-08-04 05:59:32 +00002709void FragileHazards::emitHazardsInNewBlocks() {
John McCall42227ed2010-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 McCall2dd7d442010-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 McCall42227ed2010-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 McCall65bea082010-07-21 06:59:36 +00002772}
2773
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002774/*
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002775
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002776 Objective-C setjmp-longjmp (sjlj) Exception Handling
2777 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002778
John McCallbd309292010-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 Dunbar59e476b2009-08-03 17:06:42 +00002811 The basic framework for a @try-catch-finally is as follows:
2812 {
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002813 objc_exception_data d;
2814 id _rethrow = null;
Anders Carlssonda0e4562009-02-07 21:26:04 +00002815 bool _call_try_exit = true;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002816
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002817 objc_exception_try_enter(&d);
2818 if (!setjmp(d.jmp_buf)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002819 ... try body ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002820 } else {
Daniel Dunbar59e476b2009-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 Dunbard3dcb4f82008-09-28 01:03:14 +00002837 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002838 ... jump-through-finally to finally_end ...
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002839
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002840 finally:
Anders Carlssonda0e4562009-02-07 21:26:04 +00002841 if (_call_try_exit)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002842 objc_exception_try_exit(&d);
Anders Carlssonda0e4562009-02-07 21:26:04 +00002843
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002844 ... finally block ....
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002845 ... dispatch to finally destination ...
2846
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002847 finally_rethrow:
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002848 objc_exception_throw(_rethrow);
2849
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002850 finally_end:
2851 }
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002852
Daniel Dunbar59e476b2009-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 Dunbard3dcb4f82008-09-28 01:03:14 +00002857
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002858 We specialize this framework for a few particular circumstances:
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002859
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002860 - If there are no catch blocks, then we avoid emitting the second
2861 exception handling context.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002862
Daniel Dunbar59e476b2009-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 Dunbard3dcb4f82008-09-28 01:03:14 +00002865
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002866 - FIXME: If there is no @finally block we can do a few more
2867 simplifications.
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002868
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002869 Rethrows and Jumps-Through-Finally
2870 --
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00002871
John McCallbd309292010-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 Dunbard3dcb4f82008-09-28 01:03:14 +00002874
John McCallbd309292010-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 Dunbar2efd5382008-09-30 01:06:03 +00002879
John McCallbd309292010-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 Dunbard3dcb4f82008-09-28 01:03:14 +00002884*/
2885
Fariborz Jahanianc2ad6dc2008-11-21 00:49:24 +00002886void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2887 const Stmt &S) {
2888 bool isTry = isa<ObjCAtTryStmt>(S);
John McCallbd309292010-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 Dunbar59e476b2009-08-03 17:06:42 +00002899
Daniel Dunbar94ceb612009-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 McCall2dd7d442010-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 Dunbar94ceb612009-02-24 01:43:46 +00002906 if (!isTry) {
John McCall2dd7d442010-08-04 05:59:32 +00002907 llvm::Value *SyncArg =
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002908 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2909 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
John McCallbd309292010-07-06 01:34:17 +00002910 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
2911 ->setDoesNotThrow();
John McCall2dd7d442010-08-04 05:59:32 +00002912
2913 SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
2914 CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
Daniel Dunbar94ceb612009-02-24 01:43:46 +00002915 }
Daniel Dunbar2efd5382008-09-30 01:06:03 +00002916
John McCall2dd7d442010-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 McCall42227ed2010-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 McCallbd309292010-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 McCall2dd7d442010-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 McCallbd309292010-07-06 01:34:17 +00002936 llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
Anders Carlssonda0e4562009-02-07 21:26:04 +00002937 "_call_try_exit");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002938
John McCall9916e3f2010-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 McCallbd309292010-07-06 01:34:17 +00002943 // Push a normal cleanup to leave the try scope.
John McCallcda666c2010-07-21 07:22:38 +00002944 CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
John McCall2dd7d442010-08-04 05:59:32 +00002945 SyncArgSlot,
John McCallcda666c2010-07-21 07:22:38 +00002946 CallTryExitVar,
2947 ExceptionData,
2948 &ObjCTypes);
John McCallbd309292010-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 Dunbar75283ff2008-11-11 02:29:29 +00002967 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2968 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
John McCallbd309292010-07-06 01:34:17 +00002969 llvm::Value *DidCatch =
John McCallcebe0ca2010-08-11 00:16:14 +00002970 CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
2971 CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00002972
John McCallbd309292010-07-06 01:34:17 +00002973 // Emit the protected block.
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00002974 CGF.EmitBlock(TryBlock);
John McCall2dd7d442010-08-04 05:59:32 +00002975 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002976 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
John McCallbd309292010-07-06 01:34:17 +00002977 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
John McCall2dd7d442010-08-04 05:59:32 +00002978
2979 CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00002980
John McCallbd309292010-07-06 01:34:17 +00002981 // Emit the exception handler block.
Daniel Dunbar7f086782008-09-27 23:30:04 +00002982 CGF.EmitBlock(TryHandler);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00002983
John McCall42227ed2010-07-31 23:20:56 +00002984 // Don't optimize loads of the in-scope locals across this point.
2985 Hazards.emitWriteHazard();
2986
John McCallbd309292010-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 McCall2dd7d442010-08-04 05:59:32 +00002991 CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00002992 CGF.EmitBranchThroughCleanup(FinallyRethrow);
John McCallbd309292010-07-06 01:34:17 +00002993
2994 // Otherwise, we have to match against the caught exceptions.
2995 } else {
John McCall2dd7d442010-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 McCallbd309292010-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 Gregor96c79492010-04-23 22:50:49 +00003007 const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003008
John McCall2dd7d442010-08-04 05:59:32 +00003009 bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
John McCallbd309292010-07-06 01:34:17 +00003010
John McCall2dd7d442010-08-04 05:59:32 +00003011 llvm::BasicBlock *CatchBlock = 0;
3012 llvm::BasicBlock *CatchHandler = 0;
3013 if (HasFinally) {
John McCall9916e3f2010-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 McCall2dd7d442010-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 Carlsson4f1c7c32008-09-09 17:59:25 +00003024
John McCall2dd7d442010-08-04 05:59:32 +00003025 llvm::CallInst *SetJmpResult =
3026 CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
3027 "setjmp.result");
3028 SetJmpResult->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003029
John McCall2dd7d442010-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 Dunbar59e476b2009-08-03 17:06:42 +00003041
Daniel Dunbarb22ff592008-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 Gregor96c79492010-04-23 22:50:49 +00003046 for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
3047 const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003048
Douglas Gregor46a572b2010-04-26 16:46:50 +00003049 const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Steve Naroff7cae42b2009-07-10 23:34:53 +00003050 const ObjCObjectPointerType *OPT = 0;
Daniel Dunbar523208f2008-09-27 07:36:24 +00003051
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003052 // catch(...) always matches.
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003053 if (!CatchParam) {
3054 AllMatched = true;
3055 } else {
John McCall9dd450b2009-09-21 23:43:11 +00003056 OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003057
John McCallbd309292010-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 Dunbar86919f42008-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 Friedman55179ca2009-07-11 00:57:02 +00003062 if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003063 AllMatched = true;
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003064 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003065
John McCallbd309292010-07-06 01:34:17 +00003066 // If this is a catch-all, we don't need to test anything.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003067 if (AllMatched) {
John McCallbd309292010-07-06 01:34:17 +00003068 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
3069
Anders Carlsson9396a892008-09-11 09:15:33 +00003070 if (CatchParam) {
John McCall1c9c3fd2010-10-15 04:57:14 +00003071 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003072 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
John McCallbd309292010-07-06 01:34:17 +00003073
3074 // These types work out because ConvertType(id) == i8*.
Steve Naroff371b8fb2009-03-03 19:52:17 +00003075 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson9396a892008-09-11 09:15:33 +00003076 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003077
Anders Carlsson9396a892008-09-11 09:15:33 +00003078 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003079
3080 // The scope of the catch variable ends right here.
3081 CatchVarCleanups.ForceCleanup();
3082
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003083 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003084 break;
3085 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003086
Steve Naroff7cae42b2009-07-10 23:34:53 +00003087 assert(OPT && "Unexpected non-object pointer type in @catch");
John McCall96fa4842010-05-17 21:00:27 +00003088 const ObjCObjectType *ObjTy = OPT->getObjectType();
John McCallbd309292010-07-06 01:34:17 +00003089
3090 // FIXME: @catch (Class c) ?
John McCall96fa4842010-05-17 21:00:27 +00003091 ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
3092 assert(IDecl && "Catch parameter must have Objective-C type!");
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003093
3094 // Check if the @catch block matches the exception object.
John McCall96fa4842010-05-17 21:00:27 +00003095 llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003096
John McCallbd309292010-07-06 01:34:17 +00003097 llvm::CallInst *Match =
Chris Lattnerc6406db2009-04-22 02:26:14 +00003098 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
3099 Class, Caught, "match");
John McCallbd309292010-07-06 01:34:17 +00003100 Match->setDoesNotThrow();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003101
John McCallbd309292010-07-06 01:34:17 +00003102 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
3103 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003104
3105 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar7f086782008-09-27 23:30:04 +00003106 MatchedBlock, NextCatchBlock);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003107
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003108 // Emit the @catch block.
3109 CGF.EmitBlock(MatchedBlock);
John McCallbd309292010-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 McCall2dd7d442010-08-04 05:59:32 +00003113 CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
John McCallbd309292010-07-06 01:34:17 +00003114
John McCall1c9c3fd2010-10-15 04:57:14 +00003115 CGF.EmitAutoVarDecl(*CatchParam);
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003116 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003117
John McCallbd309292010-07-06 01:34:17 +00003118 // Initialize the catch variable.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003119 llvm::Value *Tmp =
3120 CGF.Builder.CreateBitCast(Caught,
3121 CGF.ConvertType(CatchParam->getType()),
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003122 "tmp");
Steve Naroff371b8fb2009-03-03 19:52:17 +00003123 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003124
Anders Carlsson9396a892008-09-11 09:15:33 +00003125 CGF.EmitStmt(CatchStmt->getCatchBody());
John McCallbd309292010-07-06 01:34:17 +00003126
3127 // We're done with the catch variable.
3128 CatchVarCleanups.ForceCleanup();
3129
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003130 CGF.EmitBranchThroughCleanup(FinallyEnd);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003131
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003132 CGF.EmitBlock(NextCatchBlock);
3133 }
3134
John McCallbd309292010-07-06 01:34:17 +00003135 CGF.ObjCEHValueStack.pop_back();
3136
John McCall2dd7d442010-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 McCall9916e3f2010-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 McCall2dd7d442010-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 Carlssonbfee7e92009-02-09 20:38:58 +00003165 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbarb22ff592008-09-27 07:03:52 +00003166 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003167 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003168
John McCall42227ed2010-07-31 23:20:56 +00003169 // Insert read hazards as required in the new blocks.
John McCall2dd7d442010-08-04 05:59:32 +00003170 Hazards.emitHazardsInNewBlocks();
John McCall42227ed2010-07-31 23:20:56 +00003171
John McCallbd309292010-07-06 01:34:17 +00003172 // Pop the cleanup.
John McCall2dd7d442010-08-04 05:59:32 +00003173 CGF.Builder.restoreIP(TryFallthroughIP);
3174 if (CGF.HaveInsertPoint())
3175 CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
John McCallbd309292010-07-06 01:34:17 +00003176 CGF.PopCleanupBlock();
John McCall2dd7d442010-08-04 05:59:32 +00003177 CGF.EmitBlock(FinallyEnd.getBlock(), true);
Anders Carlssonbfee7e92009-02-09 20:38:58 +00003178
John McCallbd309292010-07-06 01:34:17 +00003179 // Emit the rethrow block.
John McCall42227ed2010-07-31 23:20:56 +00003180 CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
John McCallad5d61e2010-07-23 21:56:41 +00003181 CGF.EmitBlock(FinallyRethrow.getBlock(), true);
John McCallbd309292010-07-06 01:34:17 +00003182 if (CGF.HaveInsertPoint()) {
John McCall9916e3f2010-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 McCall2dd7d442010-08-04 05:59:32 +00003187
John McCall9916e3f2010-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 McCallbd309292010-07-06 01:34:17 +00003198 ->setDoesNotThrow();
3199 CGF.Builder.CreateUnreachable();
Fariborz Jahaniane2caaaa2008-11-21 19:21:53 +00003200 }
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003201
John McCall42227ed2010-07-31 23:20:56 +00003202 CGF.Builder.restoreIP(SavedIP);
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003203}
3204
3205void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar2efd5382008-09-30 01:06:03 +00003206 const ObjCAtThrowStmt &S) {
Anders Carlssone005aa12008-09-09 16:16:55 +00003207 llvm::Value *ExceptionAsObject;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003208
Anders Carlssone005aa12008-09-09 16:16:55 +00003209 if (const Expr *ThrowExpr = S.getThrowExpr()) {
3210 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003211 ExceptionAsObject =
Anders Carlssone005aa12008-09-09 16:16:55 +00003212 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
3213 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003214 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbard3dcb4f82008-09-28 01:03:14 +00003215 "Unexpected rethrow outside @catch block.");
Anders Carlssonbf8a1be2009-02-07 21:37:21 +00003216 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlssone005aa12008-09-09 16:16:55 +00003217 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003218
John McCallbd309292010-07-06 01:34:17 +00003219 CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
3220 ->setDoesNotReturn();
Anders Carlsson4f1c7c32008-09-09 17:59:25 +00003221 CGF.Builder.CreateUnreachable();
Daniel Dunbar5c7e3932008-11-11 23:11:34 +00003222
3223 // Clear the insertion point to indicate we are in unreachable code.
3224 CGF.Builder.ClearInsertionPoint();
Anders Carlsson1963b0c2008-09-09 10:04:29 +00003225}
3226
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003227/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003228/// object: objc_read_weak (id *src)
3229///
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003230llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00003231 llvm::Value *AddrWeakObj) {
Eli Friedmana374b682009-03-07 03:57:15 +00003232 const llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003233 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
3234 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
3235 ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00003236 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003237 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00003238 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanianf5125d12008-11-18 21:45:40 +00003239 return read_weak;
3240}
3241
Fariborz Jahanian83f45b552008-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 Stump11289f42009-09-09 15:08:12 +00003246 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003247 const llvm::Type * SrcTy = src->getType();
3248 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003249 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-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 Dunbar59e476b2009-08-03 17:06:42 +00003252 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003253 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3254 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003255 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3256 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00003257 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian83f45b552008-11-18 22:37:34 +00003258 src, dst, "weakassign");
3259 return;
3260}
3261
Fariborz Jahaniand7db9642008-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 Jahanian217af242010-07-20 20:30:03 +00003266 llvm::Value *src, llvm::Value *dst,
3267 bool threadlocal) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003268 const llvm::Type * SrcTy = src->getType();
3269 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003270 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-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 Dunbar59e476b2009-08-03 17:06:42 +00003273 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003274 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3275 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003276 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3277 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-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 Jahaniand7db9642008-11-19 00:59:10 +00003284 return;
3285}
3286
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003287/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003288/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003289///
3290void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003291 llvm::Value *src, llvm::Value *dst,
3292 llvm::Value *ivarOffset) {
3293 assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003294 const llvm::Type * SrcTy = src->getType();
3295 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003296 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-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 Dunbar59e476b2009-08-03 17:06:42 +00003299 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003300 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3301 }
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003302 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3303 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00003304 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
3305 src, dst, ivarOffset);
Fariborz Jahaniane881b532008-11-20 19:23:36 +00003306 return;
3307}
3308
Fariborz Jahaniand7db9642008-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 Stump11289f42009-09-09 15:08:12 +00003313 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00003314 const llvm::Type * SrcTy = src->getType();
3315 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00003316 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-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 Dunbar59e476b2009-08-03 17:06:42 +00003319 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00003320 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
3321 }
Fariborz Jahanian50a12702008-11-19 17:34:06 +00003322 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
3323 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00003324 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahaniand7db9642008-11-19 00:59:10 +00003325 src, dst, "weakassign");
3326 return;
3327}
3328
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003329void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003330 llvm::Value *DestPtr,
3331 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003332 llvm::Value *size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003333 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
3334 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003335 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00003336 DestPtr, SrcPtr, size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00003337 return;
3338}
3339
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003340/// EmitObjCValueForIvar - Code Gen for ivar reference.
3341///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003342LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
3343 QualType ObjectTy,
3344 llvm::Value *BaseValue,
3345 const ObjCIvarDecl *Ivar,
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00003346 unsigned CVRQualifiers) {
John McCall8b07ec22010-05-15 11:32:37 +00003347 const ObjCInterfaceDecl *ID =
3348 ObjectTy->getAs<ObjCObjectType>()->getInterface();
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003349 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
3350 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanian9f84b782009-02-02 20:02:29 +00003351}
3352
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003353llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar722f4242009-04-22 05:08:15 +00003354 const ObjCInterfaceDecl *Interface,
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003355 const ObjCIvarDecl *Ivar) {
Daniel Dunbar9fd114d2009-04-22 07:32:20 +00003356 uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003357 return llvm::ConstantInt::get(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003358 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
3359 Offset);
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00003360}
3361
Daniel Dunbar3ad53482008-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 Dunbar5e639272010-04-25 20:39:01 +00003373 eImageInfo_FixAndContinue = (1 << 0),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003374 eImageInfo_GarbageCollected = (1 << 1),
3375 eImageInfo_GCOnly = (1 << 2),
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003376 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
3377
Daniel Dunbar5e639272010-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 Dunbar75e909f2009-04-20 07:11:47 +00003380 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003381};
3382
Daniel Dunbar5e639272010-04-25 20:39:01 +00003383void CGObjCCommonMac::EmitImageInfo() {
Daniel Dunbar3ad53482008-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 Dunbar59e476b2009-08-03 17:06:42 +00003392
Daniel Dunbar75e909f2009-04-20 07:11:47 +00003393 // We never allow @synthesize of a superclass property.
3394 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003395
Chris Lattner5e016ae2010-06-27 07:15:29 +00003396 const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
3397
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003398 // Emitted as int[2];
3399 llvm::Constant *values[2] = {
Chris Lattner5e016ae2010-06-27 07:15:29 +00003400 llvm::ConstantInt::get(Int32Ty, version),
3401 llvm::ConstantInt::get(Int32Ty, flags)
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003402 };
Chris Lattner5e016ae2010-06-27 07:15:29 +00003403 llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
Daniel Dunbarc2d4b622009-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 Dunbar59e476b2009-08-03 17:06:42 +00003410 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003411 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
Owen Anderson47034e12009-07-28 18:33:04 +00003412 llvm::ConstantArray::get(AT, values, 2),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003413 Section,
3414 0,
3415 true);
3416 GV->setConstant(true);
Daniel Dunbar3ad53482008-08-11 21:35:06 +00003417}
3418
Daniel Dunbar7bd00bd2008-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 Sandsc76fe8b2009-05-09 07:08:47 +00003431 uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003432
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003433 std::vector<llvm::Constant*> Values(4);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003434 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
3435 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbar92992502008-08-15 22:20:32 +00003436 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbarb036db82008-08-13 03:21:16 +00003437 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003438 Values[3] = EmitModuleSymbols();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003439 CreateMetadataVar("\01L_OBJC_MODULES",
Owen Anderson0e0189d2009-07-27 22:29:56 +00003440 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003441 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbarae333842009-03-09 22:18:41 +00003442 4, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003443}
3444
3445llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003446 unsigned NumClasses = DefinedClasses.size();
3447 unsigned NumCategories = DefinedCategories.size();
3448
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003449 // Return null if no symbols were defined.
3450 if (!NumClasses && !NumCategories)
Owen Anderson0b75f232009-07-31 20:28:54 +00003451 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003452
3453 std::vector<llvm::Constant*> Values(5);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003454 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
Owen Anderson0b75f232009-07-31 20:28:54 +00003455 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00003456 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
3457 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003458
Daniel Dunbar938a77f2008-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 Dunbar22d82ed2008-08-21 04:36:09 +00003461 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003462 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00003463 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003464 ObjCTypes.Int8PtrTy);
3465 for (unsigned i=0; i<NumCategories; i++)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003466 Symbols[NumClasses + i] =
Owen Andersonade90fd2009-07-29 18:54:39 +00003467 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
Daniel Dunbar938a77f2008-08-22 20:34:54 +00003468 ObjCTypes.Int8PtrTy);
3469
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003470 Values[4] =
Owen Anderson9793f0e2009-07-29 22:16:19 +00003471 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003472 NumClasses + NumCategories),
3473 Symbols);
3474
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00003475 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003476
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003477 llvm::GlobalVariable *GV =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003478 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
3479 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003480 4, true);
Owen Andersonade90fd2009-07-29 18:54:39 +00003481 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003482}
3483
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003484llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003485 const ObjCInterfaceDecl *ID) {
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00003486 LazySymbols.insert(ID->getIdentifier());
3487
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003488 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003489
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003490 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003491 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00003492 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003493 ObjCTypes.ClassPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003494 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003495 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
3496 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003497 4, true);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003498 }
3499
Daniel Dunbarc76493a2009-11-29 21:23:36 +00003500 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003501}
3502
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00003503llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
3504 bool lvalue) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003505 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003506
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003507 if (!Entry) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003508 llvm::Constant *Casted =
Owen Andersonade90fd2009-07-29 18:54:39 +00003509 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003510 ObjCTypes.SelectorPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003511 Entry =
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003512 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
3513 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbarb25452a2009-04-15 02:56:18 +00003514 4, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003515 }
3516
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00003517 if (lvalue)
3518 return Entry;
Daniel Dunbarc76493a2009-11-29 21:23:36 +00003519 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003520}
3521
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00003522llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarb036db82008-08-13 03:21:16 +00003523 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003524
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003525 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003526 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003527 llvm::ConstantArray::get(VMContext,
3528 Ident->getNameStart()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003529 ((ObjCABI == 2) ?
3530 "__TEXT,__objc_classname,cstring_literals" :
3531 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003532 1, true);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003533
Owen Anderson170229f2009-07-14 23:10:40 +00003534 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00003535}
3536
Argyrios Kyrtzidis13257c52010-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 Jahanian01dff422009-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 Dunbar59e476b2009-08-03 17:06:42 +00003556 const ObjCCommonTypesHelper &ObjCTypes) {
Owen Anderson0b75f232009-07-31 20:28:54 +00003557 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Fariborz Jahanian01dff422009-03-05 19:17:31 +00003558}
3559
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003560void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003561 unsigned int BytePos,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003562 bool ForStrongLayout,
3563 bool &HasUnion) {
3564 const RecordDecl *RD = RT->getDecl();
3565 // FIXME - Use iterator.
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00003566 llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003567 const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003568 const llvm::StructLayout *RecLayout =
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003569 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003570
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003571 BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
3572 ForStrongLayout, HasUnion);
3573}
3574
Daniel Dunbar36e2a1e2009-05-03 21:05:10 +00003575void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003576 const llvm::StructLayout *Layout,
3577 const RecordDecl *RD,
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003578 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003579 unsigned int BytePos, bool ForStrongLayout,
3580 bool &HasUnion) {
Fariborz Jahanian3b0f8862009-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 Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003586 FieldDecl *LastFieldBitfieldOrUnnamed = 0;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003587 uint64_t MaxFieldOffset = 0;
3588 uint64_t MaxSkippedFieldOffset = 0;
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003589 uint64_t LastBitfieldOrUnnamedOffset = 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003590
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003591 if (RecFields.empty())
3592 return;
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003593 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
3594 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
3595
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003596 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003597 FieldDecl *Field = RecFields[i];
Daniel Dunbar62b10702009-05-03 23:35:23 +00003598 uint64_t FieldOffset;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00003599 if (RD) {
Daniel Dunbard51c1a62010-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 Dyckc5ca8762011-04-14 00:43:09 +00003603 FieldOffset = RL.getFieldOffset(i) / ByteSizeInBits;
Anders Carlssone2c6baf2009-07-24 17:23:54 +00003604 } else
Daniel Dunbar62b10702009-05-03 23:35:23 +00003605 FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003606
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003607 // Skip over unnamed or bitfields
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003608 if (!Field->getIdentifier() || Field->isBitField()) {
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003609 LastFieldBitfieldOrUnnamed = Field;
3610 LastBitfieldOrUnnamedOffset = FieldOffset;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003611 continue;
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003612 }
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003613
Argyrios Kyrtzidis2fdb5b52010-09-06 12:00:10 +00003614 LastFieldBitfieldOrUnnamed = 0;
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003615 QualType FQT = Field->getType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003616 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003617 if (FQT->isUnionType())
3618 HasUnion = true;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003619
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003620 BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003621 BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003622 ForStrongLayout, HasUnion);
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003623 continue;
3624 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003625
Chris Lattner5b36ddb2009-03-31 08:48:01 +00003626 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003627 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003628 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003629 uint64_t ElCount = CArray->getSize().getZExtValue();
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003630 assert(CArray && "only array with known element size is supported");
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003631 FQT = CArray->getElementType();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003632 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
3633 const ConstantArrayType *CArray =
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003634 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanianf5fec022009-04-21 18:33:06 +00003635 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003636 FQT = CArray->getElementType();
3637 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003638
3639 assert(!FQT->isUnionType() &&
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003640 "layout for array of unions not supported");
Fariborz Jahanian9a7d57d2011-01-03 19:23:18 +00003641 if (FQT->isRecordType() && ElCount) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003642 int OldIndex = IvarsInfo.size() - 1;
3643 int OldSkIndex = SkipIvars.size() -1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003644
Ted Kremenekc23c7e62009-07-29 21:53:49 +00003645 const RecordType *RT = FQT->getAs<RecordType>();
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003646 BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003647 ForStrongLayout, HasUnion);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003648
Fariborz Jahanian3b0f8862009-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 Dunbar59e476b2009-08-03 17:06:42 +00003652 for (int FirstIndex = IvarsInfo.size() - 1,
3653 FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003654 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Daniel Dunbar7b89ace2009-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 Jahanian3b0f8862009-03-11 00:07:04 +00003661 }
3662 continue;
3663 }
Fariborz Jahanian524bb202009-03-10 16:22:08 +00003664 }
Fariborz Jahanian3b0f8862009-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 McCall8ccfcb52009-09-24 19:53:00 +00003667 Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
Daniel Dunbar7abf83c2009-05-03 13:55:09 +00003668
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003669 unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
John McCall8ccfcb52009-09-24 19:53:00 +00003670 if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
3671 || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00003672 if (IsUnion) {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003673 uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
Daniel Dunbar22007d32009-05-03 13:32:01 +00003674 if (UnionIvarSize > MaxUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003675 MaxUnionIvarSize = UnionIvarSize;
3676 MaxField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003677 MaxFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003678 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00003679 } else {
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003680 IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003681 FieldSize / WordSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003682 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003683 } else if ((ForStrongLayout &&
John McCall8ccfcb52009-09-24 19:53:00 +00003684 (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
3685 || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
Daniel Dunbar22007d32009-05-03 13:32:01 +00003686 if (IsUnion) {
Mike Stump18bb9282009-05-16 07:57:57 +00003687 // FIXME: Why the asymmetry? We divide by word size in bits on other
3688 // side.
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003689 uint64_t UnionIvarSize = FieldSize;
Daniel Dunbar22007d32009-05-03 13:32:01 +00003690 if (UnionIvarSize > MaxSkippedUnionIvarSize) {
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003691 MaxSkippedUnionIvarSize = UnionIvarSize;
3692 MaxSkippedField = Field;
Daniel Dunbar5b743912009-05-03 23:31:46 +00003693 MaxSkippedFieldOffset = FieldOffset;
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003694 }
Daniel Dunbar22007d32009-05-03 13:32:01 +00003695 } else {
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003696 // FIXME: Why the asymmetry, we divide by byte size in bits here?
Daniel Dunbar94f46dc2009-05-03 14:17:18 +00003697 SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003698 FieldSize / ByteSizeInBits));
Fariborz Jahanian3b0f8862009-03-11 00:07:04 +00003699 }
3700 }
3701 }
Daniel Dunbar15bd8882009-05-03 14:10:34 +00003702
Argyrios Kyrtzidis2fdb5b52010-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 Jahanianf5fec022009-04-21 18:33:06 +00003722 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003723
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003724 if (MaxField)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003725 IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003726 MaxUnionIvarSize));
3727 if (MaxSkippedField)
Daniel Dunbar5b743912009-05-03 23:31:46 +00003728 SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
Daniel Dunbar7b89ace2009-05-03 13:44:42 +00003729 MaxSkippedUnionIvarSize));
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00003730}
3731
Fariborz Jahanian1f78a9a2010-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 Jahaniancbaf73c2009-03-11 20:59:05 +00003738 unsigned int WordsToScan, WordsToSkip;
Benjamin Kramerabd5b902009-10-13 10:07:13 +00003739 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003740
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003741 // Build the string of skip/scan nibbles
Fariborz Jahaniance5676572009-04-24 17:15:27 +00003742 llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003743 unsigned int WordSize =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003744 CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003745 if (IvarsInfo[0].ivar_bytepos == 0) {
3746 WordsToSkip = 0;
3747 WordsToScan = IvarsInfo[0].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003748 } else {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003749 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
3750 WordsToScan = IvarsInfo[0].ivar_size;
3751 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003752 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003753 unsigned int TailPrevGCObjC =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003754 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003755 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003756 // consecutive 'scanned' object pointers.
3757 WordsToScan += IvarsInfo[i].ivar_size;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003758 } else {
Fariborz Jahaniancbaf73c2009-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 Jahanian1bf72882009-03-12 22:50:49 +00003764 SKIP_SCAN SkScan;
3765 SkScan.skip = WordsToSkip;
3766 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003767 SkipScanIvars.push_back(SkScan);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003768
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003769 // Skip the hole.
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003770 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3771 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003772 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003773 WordsToSkip = 0;
3774 WordsToScan = IvarsInfo[i].ivar_size;
3775 }
3776 }
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003777 if (WordsToScan > 0) {
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003778 SKIP_SCAN SkScan;
3779 SkScan.skip = WordsToSkip;
3780 SkScan.scan = WordsToScan;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003781 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003782 }
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003783
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003784 if (!SkipIvars.empty()) {
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003785 unsigned int LastIndex = SkipIvars.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003786 int LastByteSkipped =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003787 SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003788 LastIndex = IvarsInfo.size()-1;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003789 int LastByteScanned =
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003790 IvarsInfo[LastIndex].ivar_bytepos +
3791 IvarsInfo[LastIndex].ivar_size * WordSize;
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003792 // Compute number of bytes to skip at the tail end of the last ivar scanned.
Benjamin Kramerd20ef752009-12-25 15:43:36 +00003793 if (LastByteSkipped > LastByteScanned) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003794 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahanian1bf72882009-03-12 22:50:49 +00003795 SKIP_SCAN SkScan;
3796 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3797 SkScan.scan = 0;
Fariborz Jahaniana123b642009-04-24 16:17:09 +00003798 SkipScanIvars.push_back(SkScan);
Fariborz Jahaniancbaf73c2009-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 Jahaniana123b642009-04-24 16:17:09 +00003803 int SkipScan = SkipScanIvars.size()-1;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003804 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-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 Jahanian9659f6b2010-08-04 23:55:24 +00003814
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003815 // Generate the string.
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003816 for (int i = 0; i <= SkipScan; i++) {
Fariborz Jahaniancbaf73c2009-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 Jahanian9659f6b2010-08-04 23:55:24 +00003822
Fariborz Jahaniancbaf73c2009-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 Jahanian9659f6b2010-08-04 23:55:24 +00003826
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003827 // next (skip small, scan)
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003828 if (skip_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003829 byte = skip_small << 4;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003830 if (scan_big > 0) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003831 byte |= 0xf;
3832 --scan_big;
Daniel Dunbard22aa4a2009-05-03 23:21:22 +00003833 } else if (scan_small) {
Fariborz Jahaniancbaf73c2009-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 Dunbard22aa4a2009-05-03 23:21:22 +00003843 if (scan_small) {
Fariborz Jahaniancbaf73c2009-03-11 20:59:05 +00003844 byte = scan_small;
3845 BitMap += byte;
3846 }
3847 }
3848 // null terminate string.
Fariborz Jahanianf909f922009-03-25 22:36:49 +00003849 unsigned char zero = 0;
3850 BitMap += zero;
Fariborz Jahanian9659f6b2010-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 Dunbar7c9295a2011-03-25 20:09:09 +00003855 ((ObjCABI == 2) ?
3856 "__TEXT,__objc_classname,cstring_literals" :
3857 "__TEXT,__cstring,cstring_literals"),
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003858 1, true);
3859 return getConstantGEP(VMContext, Entry, 0, 0);
3860}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003861
Fariborz Jahanian9659f6b2010-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 Jahaniana50b3a22010-08-20 21:21:08 +00003887 llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003888 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
Fariborz Jahaniana50b3a22010-08-20 21:21:08 +00003889 CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003890
Fariborz Jahaniana50b3a22010-08-20 21:21:08 +00003891 llvm::SmallVector<FieldDecl*, 32> RecFields;
Fariborz Jahanian9659f6b2010-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 Jahanian1f78a9a2010-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 Jahanian9659f6b2010-08-04 23:55:24 +00003911 std::string BitMap;
Fariborz Jahanian1f78a9a2010-08-05 00:19:48 +00003912 llvm::Constant *C = BuildIvarLayoutBitmap(BitMap);
Fariborz Jahanian9659f6b2010-08-04 23:55:24 +00003913
3914 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003915 printf("\n%s ivar layout for class '%s': ",
Fariborz Jahanian80c9ce22009-04-20 22:03:45 +00003916 ForStrongLayout ? "strong" : "weak",
Daniel Dunbar56df9772010-08-17 22:39:59 +00003917 OMD->getClassInterface()->getName().data());
Fariborz Jahanian80c9ce22009-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 Jahanian9659f6b2010-08-04 23:55:24 +00003926 return C;
Fariborz Jahanianc559f3f2009-03-05 22:39:55 +00003927}
3928
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003929llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003930 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3931
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003932 // FIXME: Avoid std::string copying.
3933 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003934 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
Owen Anderson41a75022009-08-13 21:57:51 +00003935 llvm::ConstantArray::get(VMContext, Sel.getAsString()),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003936 ((ObjCABI == 2) ?
3937 "__TEXT,__objc_methname,cstring_literals" :
3938 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003939 1, true);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003940
Owen Anderson170229f2009-07-14 23:10:40 +00003941 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarb036db82008-08-13 03:21:16 +00003942}
3943
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003944// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003945llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003946 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3947}
3948
Daniel Dunbarf5c18462009-04-20 06:54:31 +00003949llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel4b6e4bb2009-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 Dunbarb036db82008-08-13 03:21:16 +00003954
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003955 if (!Entry)
3956 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson41a75022009-08-13 21:57:51 +00003957 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003958 ((ObjCABI == 2) ?
3959 "__TEXT,__objc_methtype,cstring_literals" :
3960 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003961 1, true);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003962
Owen Anderson170229f2009-07-14 23:10:40 +00003963 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbarcb515c82008-08-12 03:39:23 +00003964}
3965
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003966llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003967 std::string TypeStr;
Daniel Dunbar3c76cb52008-08-26 21:51:14 +00003968 CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
3969 TypeStr);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003970
3971 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3972
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003973 if (!Entry)
3974 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
Owen Anderson41a75022009-08-13 21:57:51 +00003975 llvm::ConstantArray::get(VMContext, TypeStr),
Daniel Dunbar7c9295a2011-03-25 20:09:09 +00003976 ((ObjCABI == 2) ?
3977 "__TEXT,__objc_methtype,cstring_literals" :
3978 "__TEXT,__cstring,cstring_literals"),
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003979 1, true);
Devang Patel4b6e4bb2009-03-04 18:21:39 +00003980
Owen Anderson170229f2009-07-14 23:10:40 +00003981 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00003982}
3983
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003984// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00003985llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003986 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003987
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003988 if (!Entry)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00003989 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00003990 llvm::ConstantArray::get(VMContext,
3991 Ident->getNameStart()),
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00003992 "__TEXT,__cstring,cstring_literals",
Daniel Dunbar3241fae2009-04-14 23:14:47 +00003993 1, true);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003994
Owen Anderson170229f2009-07-14 23:10:40 +00003995 return getConstantGEP(VMContext, Entry, 0, 0);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00003996}
3997
3998// FIXME: Merge into a single cstring creation function.
Daniel Dunbar4932b362008-08-28 04:38:10 +00003999// FIXME: This Decl should be more precise.
Daniel Dunbarc2d4b622009-03-09 21:49:58 +00004000llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004001CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
4002 const Decl *Container) {
Daniel Dunbar4932b362008-08-28 04:38:10 +00004003 std::string TypeStr;
4004 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbar80a840b2008-08-23 00:19:03 +00004005 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
4006}
4007
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004008void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
Fariborz Jahanian0b1ccdc2009-01-21 23:34:32 +00004009 const ObjCContainerDecl *CD,
Daniel Dunbard2386812009-10-19 01:21:19 +00004010 llvm::SmallVectorImpl<char> &Name) {
4011 llvm::raw_svector_ostream OS(Name);
Fariborz Jahanian0196a1c2009-01-10 21:06:09 +00004012 assert (CD && "Missing container decl in GetNameForMethod");
Daniel Dunbard2386812009-10-19 01:21:19 +00004013 OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
4014 << '[' << CD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004015 if (const ObjCCategoryImplDecl *CID =
Daniel Dunbard2386812009-10-19 01:21:19 +00004016 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
Benjamin Kramerb11416d2010-04-17 09:33:03 +00004017 OS << '(' << CID << ')';
Daniel Dunbard2386812009-10-19 01:21:19 +00004018 OS << ' ' << D->getSelector().getAsString() << ']';
Daniel Dunbara94ecd22008-08-16 03:19:19 +00004019}
4020
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004021void CGObjCMac::FinishModule() {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004022 EmitModuleInfo();
4023
Daniel Dunbarc475d422008-10-29 22:36:39 +00004024 // Emit the dummy bodies for any protocols which were referenced but
4025 // never defined.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004026 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
Chris Lattnerf56501c2009-07-17 23:57:13 +00004027 I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
4028 if (I->second->hasInitializer())
Daniel Dunbarc475d422008-10-29 22:36:39 +00004029 continue;
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004030
Daniel Dunbarc475d422008-10-29 22:36:39 +00004031 std::vector<llvm::Constant*> Values(5);
Owen Anderson0b75f232009-07-31 20:28:54 +00004032 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004033 Values[1] = GetClassName(I->first);
Owen Anderson0b75f232009-07-31 20:28:54 +00004034 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004035 Values[3] = Values[4] =
Owen Anderson0b75f232009-07-31 20:28:54 +00004036 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004037 I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004038 I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
Daniel Dunbarc475d422008-10-29 22:36:39 +00004039 Values));
Chris Lattnerf56501c2009-07-17 23:57:13 +00004040 CGM.AddUsedGlobal(I->second);
Daniel Dunbarc475d422008-10-29 22:36:39 +00004041 }
4042
Daniel Dunbarc61d0e92008-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 Dunbard027a922009-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 Dunbarc61d0e92008-08-25 06:02:07 +00004053
Daniel Dunbard027a922009-09-07 00:20:42 +00004054 llvm::raw_svector_ostream OS(Asm);
Daniel Dunbard027a922009-09-07 00:20:42 +00004055 for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
4056 e = DefinedSymbols.end(); I != e; ++I)
Daniel Dunbar07d07852009-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 Lattnera299f2c2010-04-17 18:26:20 +00004059 for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
Fariborz Jahanian9adb2e62010-06-21 22:05:18 +00004060 e = LazySymbols.end(); I != e; ++I) {
Chris Lattnera299f2c2010-04-17 18:26:20 +00004061 OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
Fariborz Jahanian9adb2e62010-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 Lattnera299f2c2010-04-17 18:26:20 +00004068
Daniel Dunbard027a922009-09-07 00:20:42 +00004069 CGM.getModule().setModuleInlineAsm(OS.str());
Daniel Dunbarc61d0e92008-08-25 06:02:07 +00004070 }
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004071}
4072
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004073CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004074 : CGObjCCommonMac(cgm),
Mike Stump11289f42009-09-09 15:08:12 +00004075 ObjCTypes(cgm) {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004076 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004077 ObjCABI = 2;
4078}
4079
Daniel Dunbar3ad53482008-08-11 21:35:06 +00004080/* *** */
4081
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004082ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004083 : VMContext(cgm.getLLVMContext()), CGM(cgm) {
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004084 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4085 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004086
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004087 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004088 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004089 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00004090 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Benjamin Kramerabd5b902009-10-13 10:07:13 +00004091 Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004092
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004093 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004094 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004095 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004096
Mike Stump18bb9282009-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 Dunbarb036db82008-08-13 03:21:16 +00004099 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
Owen Anderson9793f0e2009-07-29 22:16:19 +00004100 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004101
Fariborz Jahanian279eda62009-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 Dunbar59e476b2009-08-03 17:06:42 +00004106
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004107 // FIXME: This is leaked.
4108 // FIXME: Merge with rewriter code?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004109
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004110 // struct _objc_super {
4111 // id self;
4112 // Class cls;
4113 // }
Abramo Bagnara6150c882010-05-11 21:36:43 +00004114 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004115 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00004116 SourceLocation(), SourceLocation(),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004117 &Ctx.Idents.get("_objc_super"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004118 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004119 Ctx.getObjCIdType(), 0, 0, false));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004120 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004121 Ctx.getObjCClassType(), 0, 0, false));
Douglas Gregord5058122010-02-11 01:19:42 +00004122 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004123
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004124 SuperCTy = Ctx.getTagDeclType(RD);
4125 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004126
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004127 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004128 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
4129
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004130 // struct _prop_t {
4131 // char *name;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004132 // char *attributes;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004133 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004134 PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004135 CGM.getModule().addTypeName("struct._prop_t",
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004136 PropertyTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004137
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004138 // struct _prop_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004139 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004140 // uint32_t count_of_properties;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004141 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004142 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004143 PropertyListTy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004144 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004145 llvm::ArrayType::get(PropertyTy, 0),
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004146 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004147 CGM.getModule().addTypeName("struct._prop_list_t",
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004148 PropertyListTy);
4149 // struct _prop_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004150 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004151
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004152 // struct _objc_method {
4153 // SEL _cmd;
4154 // char *method_type;
4155 // char *_imp;
4156 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004157 MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004158 Int8PtrTy,
4159 Int8PtrTy,
4160 NULL);
4161 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004162
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004163 // struct _objc_cache *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004164 CacheTy = llvm::OpaqueType::get(VMContext);
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004165 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004166 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004167}
Daniel Dunbar7bd00bd2008-08-12 06:48:42 +00004168
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004169ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004170 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004171 // struct _objc_method_description {
4172 // SEL name;
4173 // char *types;
4174 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004175 MethodDescriptionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004176 llvm::StructType::get(VMContext, SelectorPtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004177 Int8PtrTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00004178 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004179 CGM.getModule().addTypeName("struct._objc_method_description",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004180 MethodDescriptionTy);
4181
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004182 // struct _objc_method_description_list {
4183 // int count;
4184 // struct _objc_method_description[1];
4185 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004186 MethodDescriptionListTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004187 llvm::StructType::get(VMContext, IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004188 llvm::ArrayType::get(MethodDescriptionTy, 0),
Daniel Dunbarb036db82008-08-13 03:21:16 +00004189 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004190 CGM.getModule().addTypeName("struct._objc_method_description_list",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004191 MethodDescriptionListTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004192
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004193 // struct _objc_method_description_list *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004194 MethodDescriptionListPtrTy =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004195 llvm::PointerType::getUnqual(MethodDescriptionListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004196
Daniel Dunbarb036db82008-08-13 03:21:16 +00004197 // Protocol description structures
4198
Fariborz Jahanian4b4c8262009-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 Dunbar59e476b2009-08-03 17:06:42 +00004205 ProtocolExtensionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004206 llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004207 MethodDescriptionListPtrTy,
4208 MethodDescriptionListPtrTy,
Daniel Dunbarb036db82008-08-13 03:21:16 +00004209 PropertyListPtrTy,
4210 NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004211 CGM.getModule().addTypeName("struct._objc_protocol_extension",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004212 ProtocolExtensionTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004213
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004214 // struct _objc_protocol_extension *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004215 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004216
Daniel Dunbarc475d422008-10-29 22:36:39 +00004217 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarb036db82008-08-13 03:21:16 +00004218
Owen Andersonc36edfe2009-08-13 23:27:53 +00004219 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
4220 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004221
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004222 const llvm::Type *T =
Mike Stump11289f42009-09-09 15:08:12 +00004223 llvm::StructType::get(VMContext,
Owen Anderson758428f2009-08-05 23:18:46 +00004224 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004225 LongTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004226 llvm::ArrayType::get(ProtocolTyHolder, 0),
Fariborz Jahanian279eda62009-01-21 22:04:16 +00004227 NULL);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004228 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
4229
Fariborz Jahanian4b4c8262009-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 Anderson758428f2009-08-05 23:18:46 +00004237 T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004238 Int8PtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004239 llvm::PointerType::getUnqual(ProtocolListTyHolder),
Daniel Dunbarb036db82008-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 Dunbar59e476b2009-08-03 17:06:42 +00004246 CGM.getModule().addTypeName("struct._objc_protocol_list",
Daniel Dunbarb036db82008-08-13 03:21:16 +00004247 ProtocolListTy);
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004248 // struct _objc_protocol_list *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004249 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
Daniel Dunbarb036db82008-08-13 03:21:16 +00004250
4251 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004252 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004253 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004254
4255 // Class description structures
4256
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004257 // struct _objc_ivar {
4258 // char *ivar_name;
4259 // char *ivar_type;
4260 // int ivar_offset;
4261 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004262 IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004263 Int8PtrTy,
4264 IntTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004265 NULL);
4266 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
4267
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004268 // struct _objc_ivar_list *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004269 IvarListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004270 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004271 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004272
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004273 // struct _objc_method_list *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004274 MethodListTy = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004275 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004276 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004277
Fariborz Jahanian4b4c8262009-01-21 00:39:53 +00004278 // struct _objc_class_extension *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004279 ClassExtensionTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004280 llvm::StructType::get(VMContext, IntTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004281 Int8PtrTy,
4282 PropertyListPtrTy,
4283 NULL);
4284 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004285 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004286
Owen Andersonc36edfe2009-08-13 23:27:53 +00004287 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004288
Fariborz Jahanian4b4c8262009-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 Anderson758428f2009-08-05 23:18:46 +00004303 T = llvm::StructType::get(VMContext,
4304 llvm::PointerType::getUnqual(ClassTyHolder),
Owen Anderson9793f0e2009-07-29 22:16:19 +00004305 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar22d82ed2008-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 Dunbar59e476b2009-08-03 17:06:42 +00004318
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004319 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
4320 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004321 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004322
Fariborz Jahanian4b4c8262009-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 Anderson758428f2009-08-05 23:18:46 +00004331 CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
Daniel Dunbar938a77f2008-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 Dunbar22d82ed2008-08-21 04:36:09 +00004341 // Global metadata structures
4342
Fariborz Jahanian4b4c8262009-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 Anderson758428f2009-08-05 23:18:46 +00004350 SymtabTy = llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004351 SelectorPtrTy,
4352 ShortTy,
4353 ShortTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004354 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004355 NULL);
4356 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004357 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004358
Fariborz Jahanianeee54df2009-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 Dunbar59e476b2009-08-03 17:06:42 +00004365 ModuleTy =
Owen Anderson758428f2009-08-05 23:18:46 +00004366 llvm::StructType::get(VMContext, LongTy,
Daniel Dunbar22d82ed2008-08-21 04:36:09 +00004367 LongTy,
4368 Int8PtrTy,
4369 SymtabPtrTy,
4370 NULL);
4371 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar97ff50d2008-08-23 09:25:55 +00004372
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004373
Mike Stump18bb9282009-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 Carlsson9ff22482008-09-09 10:10:21 +00004376 uint64_t SetJmpBufferSize = 18;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004377
Anders Carlsson9ff22482008-09-09 10:10:21 +00004378 // Exceptions
Owen Anderson9793f0e2009-07-29 22:16:19 +00004379 const llvm::Type *StackPtrTy = llvm::ArrayType::get(
Benjamin Kramerabd5b902009-10-13 10:07:13 +00004380 llvm::Type::getInt8PtrTy(VMContext), 4);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004381
4382 ExceptionDataTy =
Chris Lattner5e016ae2010-06-27 07:15:29 +00004383 llvm::StructType::get(VMContext,
4384 llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
4385 SetJmpBufferSize),
Anders Carlsson9ff22482008-09-09 10:10:21 +00004386 StackPtrTy, NULL);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004387 CGM.getModule().addTypeName("struct._objc_exception_data",
Anders Carlsson9ff22482008-09-09 10:10:21 +00004388 ExceptionDataTy);
4389
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004390}
4391
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004392ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Mike Stump11289f42009-09-09 15:08:12 +00004393 : ObjCCommonTypesHelper(cgm) {
Fariborz Jahanianb15a3d52009-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 Anderson758428f2009-08-05 23:18:46 +00004399 MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004400 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004401 llvm::ArrayType::get(MethodTy, 0),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004402 NULL);
4403 CGM.getModule().addTypeName("struct.__method_list_t",
4404 MethodListnfABITy);
4405 // struct method_list_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004406 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004407
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004408 // struct _protocol_t {
4409 // id isa; // NULL
4410 // const char * const protocol_name;
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004411 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahanianb15a3d52009-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 Jahanian0232c052009-01-23 01:46:23 +00004416 // const struct _prop_list_t * properties;
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004417 // const uint32_t size; // sizeof(struct _protocol_t)
4418 // const uint32_t flags; // = 0
4419 // }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004420
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004421 // Holder for struct _protocol_list_t *
Owen Andersonc36edfe2009-08-13 23:27:53 +00004422 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004423
Owen Anderson758428f2009-08-05 23:18:46 +00004424 ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004425 Int8PtrTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004426 llvm::PointerType::getUnqual(
Fariborz Jahanian0232c052009-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 Dunbar8de90f02009-02-15 07:36:20 +00004438
4439 // struct _protocol_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004440 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004441
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004442 // struct _protocol_list_t {
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004443 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004444 // struct _protocol_t *[protocol_count];
Fariborz Jahanianb15a3d52009-01-22 23:02:58 +00004445 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004446 ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004447 llvm::ArrayType::get(
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004448 ProtocolnfABIPtrTy, 0),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004449 NULL);
4450 CGM.getModule().addTypeName("struct._objc_protocol_list",
4451 ProtocolListnfABITy);
Daniel Dunbar8de90f02009-02-15 07:36:20 +00004452 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004453 ProtocolListnfABITy);
4454
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004455 // struct _objc_protocol_list*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004456 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004457
Fariborz Jahanianb15a3d52009-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 Stump11289f42009-09-09 15:08:12 +00004465 IvarnfABITy = llvm::StructType::get(VMContext,
Owen Anderson758428f2009-08-05 23:18:46 +00004466 llvm::PointerType::getUnqual(LongTy),
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004467 Int8PtrTy,
4468 Int8PtrTy,
4469 IntTy,
4470 IntTy,
4471 NULL);
4472 CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004473
Fariborz Jahanianb15a3d52009-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 Anderson758428f2009-08-05 23:18:46 +00004479 IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004480 IntTy,
Owen Anderson9793f0e2009-07-29 22:16:19 +00004481 llvm::ArrayType::get(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004482 IvarnfABITy, 0),
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004483 NULL);
4484 CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004485
Owen Anderson9793f0e2009-07-29 22:16:19 +00004486 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004487
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004488 // struct _class_ro_t {
Fariborz Jahanianb15a3d52009-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 Dunbar59e476b2009-08-03 17:06:42 +00004501
Fariborz Jahanian0232c052009-01-23 01:46:23 +00004502 // FIXME. Add 'reserved' field in 64bit abi mode!
Owen Anderson758428f2009-08-05 23:18:46 +00004503 ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
Fariborz Jahanian0232c052009-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 Dunbar59e476b2009-08-03 17:06:42 +00004516
Fariborz Jahanian0232c052009-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 Anderson9793f0e2009-07-29 22:16:19 +00004521 ImpnfABITy = llvm::PointerType::getUnqual(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004522 llvm::FunctionType::get(ObjectPtrTy, Params, false));
4523
Fariborz Jahanian0232c052009-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 Dunbar59e476b2009-08-03 17:06:42 +00004531
Owen Andersonc36edfe2009-08-13 23:27:53 +00004532 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
Owen Anderson170229f2009-07-14 23:10:40 +00004533 ClassnfABITy =
Owen Anderson758428f2009-08-05 23:18:46 +00004534 llvm::StructType::get(VMContext,
4535 llvm::PointerType::getUnqual(ClassTyHolder),
Daniel Dunbar59e476b2009-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 Jahanian0232c052009-01-23 01:46:23 +00004541 CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
4542
4543 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004544 ClassnfABITy);
4545
Fariborz Jahanian71394042009-01-23 23:53:38 +00004546 // LLVM for struct _class_t *
Owen Anderson9793f0e2009-07-29 22:16:19 +00004547 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004548
Fariborz Jahanian0232c052009-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 Jahanian5a63e4c2009-01-23 17:41:22 +00004556 // }
Owen Anderson758428f2009-08-05 23:18:46 +00004557 CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
Fariborz Jahanian71394042009-01-23 23:53:38 +00004558 ClassnfABIPtrTy,
Fariborz Jahanian5a63e4c2009-01-23 17:41:22 +00004559 MethodListnfABIPtrTy,
4560 MethodListnfABIPtrTy,
4561 ProtocolListnfABIPtrTy,
4562 PropertyListPtrTy,
4563 NULL);
4564 CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004565
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004566 // New types for nonfragile abi messaging.
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004567 CodeGen::CodeGenTypes &Types = CGM.getTypes();
4568 ASTContext &Ctx = CGM.getContext();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004569
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004570 // MessageRefTy - LLVM for:
4571 // struct _message_ref_t {
4572 // IMP messenger;
4573 // SEL name;
4574 // };
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004575
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004576 // First the clang type for struct _message_ref_t
Abramo Bagnara6150c882010-05-11 21:36:43 +00004577 RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
Daniel Dunbar0c005372010-04-29 16:29:11 +00004578 Ctx.getTranslationUnitDecl(),
Abramo Bagnara29c2d462011-03-09 14:09:51 +00004579 SourceLocation(), SourceLocation(),
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004580 &Ctx.Idents.get("_message_ref_t"));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004581 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004582 Ctx.VoidPtrTy, 0, 0, false));
Abramo Bagnaradff19302011-03-08 08:55:46 +00004583 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(), 0,
Argyrios Kyrtzidis60ed5602009-08-19 01:27:57 +00004584 Ctx.getObjCSelType(), 0, 0, false));
Douglas Gregord5058122010-02-11 01:19:42 +00004585 RD->completeDefinition();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004586
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00004587 MessageRefCTy = Ctx.getTagDeclType(RD);
4588 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
4589 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004590
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004591 // MessageRefPtrTy - LLVM for struct _message_ref_t*
Owen Anderson9793f0e2009-07-29 22:16:19 +00004592 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004593
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004594 // SuperMessageRefTy - LLVM for:
4595 // struct _super_message_ref_t {
4596 // SUPER_IMP messenger;
4597 // SEL name;
4598 // };
Owen Anderson758428f2009-08-05 23:18:46 +00004599 SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004600 SelectorPtrTy,
4601 NULL);
4602 CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004603
Fariborz Jahanian82c72e12009-02-03 23:49:23 +00004604 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004605 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
4606
Daniel Dunbarb1559a42009-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 Anderson758428f2009-08-05 23:18:46 +00004613 EHTypeTy = llvm::StructType::get(VMContext,
4614 llvm::PointerType::getUnqual(Int8PtrTy),
Daniel Dunbarb1559a42009-03-01 04:46:24 +00004615 Int8PtrTy,
4616 ClassnfABIPtrTy,
4617 NULL);
Daniel Dunbar76b7acc2009-03-02 06:08:11 +00004618 CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
Owen Anderson9793f0e2009-07-29 22:16:19 +00004619 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00004620}
4621
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004622llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
Fariborz Jahanian71394042009-01-23 23:53:38 +00004623 FinishNonFragileABIModule();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004624
Fariborz Jahanian71394042009-01-23 23:53:38 +00004625 return NULL;
4626}
4627
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004628void CGObjCNonFragileABIMac::AddModuleClassList(const
4629 std::vector<llvm::GlobalValue*>
4630 &Container,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004631 const char *SymbolName,
4632 const char *SectionName) {
4633 unsigned NumClasses = Container.size();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004634
Daniel Dunbar19573e72009-05-15 21:48:48 +00004635 if (!NumClasses)
4636 return;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004637
Daniel Dunbar19573e72009-05-15 21:48:48 +00004638 std::vector<llvm::Constant*> Symbols(NumClasses);
4639 for (unsigned i=0; i<NumClasses; i++)
Owen Andersonade90fd2009-07-29 18:54:39 +00004640 Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
Daniel Dunbar19573e72009-05-15 21:48:48 +00004641 ObjCTypes.Int8PtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004642 llvm::Constant* Init =
Owen Anderson9793f0e2009-07-29 22:16:19 +00004643 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004644 NumClasses),
4645 Symbols);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004646
Daniel Dunbar19573e72009-05-15 21:48:48 +00004647 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00004648 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004649 llvm::GlobalValue::InternalLinkage,
4650 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00004651 SymbolName);
Daniel Dunbar710cb202010-04-25 20:39:32 +00004652 GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
Daniel Dunbar19573e72009-05-15 21:48:48 +00004653 GV->setSection(SectionName);
Chris Lattnerf56501c2009-07-17 23:57:13 +00004654 CGM.AddUsedGlobal(GV);
Daniel Dunbar19573e72009-05-15 21:48:48 +00004655}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004656
Fariborz Jahanian71394042009-01-23 23:53:38 +00004657void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
4658 // nonfragile abi has no module definition.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004659
Daniel Dunbar19573e72009-05-15 21:48:48 +00004660 // Build list of all implemented class addresses in array
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004661 // L_OBJC_LABEL_CLASS_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004662 AddModuleClassList(DefinedClasses,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004663 "\01L_OBJC_LABEL_CLASS_$",
4664 "__DATA, __objc_classlist, regular, no_dead_strip");
Fariborz Jahanian67260552009-11-17 21:37:35 +00004665
Fariborz Jahanian67260552009-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 Jahanian67260552009-11-17 21:37:35 +00004671 }
4672
Fariborz Jahaniana6227fd2009-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 Jahanian67260552009-11-17 21:37:35 +00004679
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004680 AddModuleClassList(DefinedNonLazyClasses,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004681 "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
4682 "__DATA, __objc_nlclslist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004683
Fariborz Jahanian279abd32009-01-30 20:55:31 +00004684 // Build list of all implemented category addresses in array
4685 // L_OBJC_LABEL_CATEGORY_$.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004686 AddModuleClassList(DefinedCategories,
Daniel Dunbar19573e72009-05-15 21:48:48 +00004687 "\01L_OBJC_LABEL_CATEGORY_$",
4688 "__DATA, __objc_catlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004689 AddModuleClassList(DefinedNonLazyCategories,
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004690 "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
4691 "__DATA, __objc_nlcatlist, regular, no_dead_strip");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004692
Daniel Dunbar5e639272010-04-25 20:39:01 +00004693 EmitImageInfo();
Fariborz Jahanian71394042009-01-23 23:53:38 +00004694}
4695
John McCall9e8bb002011-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 Dunbar59e476b2009-08-03 17:06:42 +00004698/// except for the 19 selectors in the list, we generate 32bit-style
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004699/// message dispatch call for all the rest.
John McCall9e8bb002011-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 Dunbarfca18c1b42010-04-24 17:56:46 +00004703 switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
4704 default:
John McCall9e8bb002011-05-14 03:10:52 +00004705 llvm_unreachable("Invalid dispatch method!");
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004706 case CodeGenOptions::Legacy:
Fariborz Jahaniandfb39832010-04-19 17:53:30 +00004707 return false;
John McCall9e8bb002011-05-14 03:10:52 +00004708 case CodeGenOptions::NonLegacy:
4709 return true;
Daniel Dunbarfca18c1b42010-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 McCall9e8bb002011-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 Dunbar59e476b2009-08-03 17:06:42 +00004723
John McCall9e8bb002011-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 Jahanian5d5ed2d2009-05-11 19:25:47 +00004755 }
Daniel Dunbarfca18c1b42010-04-24 17:56:46 +00004756
John McCall9e8bb002011-05-14 03:10:52 +00004757 return VTableDispatchMethods.count(Sel);
Fariborz Jahanian5d5ed2d2009-05-11 19:25:47 +00004758}
4759
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004760// Metadata flags
4761enum MetaDataDlags {
4762 CLS = 0x0,
4763 CLS_META = 0x1,
4764 CLS_ROOT = 0x2,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004765 OBJC2_CLS_HIDDEN = 0x10,
Fariborz Jahanian9e3ad522009-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 Jahanian56b3b772009-01-29 19:24:30 +00004777/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian9e3ad522009-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 Dunbar59e476b2009-08-03 17:06:42 +00004784 unsigned flags,
4785 unsigned InstanceStart,
4786 unsigned InstanceSize,
4787 const ObjCImplementationDecl *ID) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004788 std::string ClassName = ID->getNameAsString();
4789 std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
Owen Andersonb7a2fe62009-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 Jahanian9e3ad522009-01-24 20:21:50 +00004793 // FIXME. For 64bit targets add 0 here.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004794 Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4795 : BuildIvarLayout(ID, true);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004796 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahanian99113fd2009-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 Dunbar59e476b2009-08-03 17:06:42 +00004802 for (ObjCImplementationDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004803 i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-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 Dunbar59e476b2009-08-03 17:06:42 +00004809 for (ObjCImplementationDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004810 i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004811 // Instance methods should always be defined.
4812 Methods.push_back(GetMethodConstant(*i));
4813 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004814 for (ObjCImplementationDecl::propimpl_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004815 i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004816 ObjCPropertyImplDecl *PID = *i;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004817
Fariborz Jahaniand27a8202009-01-28 22:46:49 +00004818 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4819 ObjCPropertyDecl *PD = PID->getPropertyDecl();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004820
Fariborz Jahaniand27a8202009-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 Jahanian99113fd2009-01-26 21:38:32 +00004829 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004830 Values[ 5] = EmitMethodList(MethodListName,
4831 "__DATA, __objc_const", Methods);
4832
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00004833 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4834 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004835 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004836 + OID->getName(),
Ted Kremenek0ef508d2010-09-01 01:21:15 +00004837 OID->all_referenced_protocol_begin(),
4838 OID->all_referenced_protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004839
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00004840 if (flags & CLS_META)
Owen Anderson0b75f232009-07-31 20:28:54 +00004841 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00004842 else
4843 Values[ 7] = EmitIvarList(ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004844 Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4845 : BuildIvarLayout(ID, false);
Fariborz Jahanian066347e2009-01-28 22:18:42 +00004846 if (flags & CLS_META)
Owen Anderson0b75f232009-07-31 20:28:54 +00004847 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahanian066347e2009-01-28 22:18:42 +00004848 else
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00004849 Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
4850 ID, ID->getClassInterface(), ObjCTypes);
Owen Anderson0e0189d2009-07-27 22:29:56 +00004851 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004852 Values);
4853 llvm::GlobalVariable *CLASS_RO_GV =
Daniel Dunbar59e476b2009-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 Jahanianc22f2362009-01-31 02:43:27 +00004860 CLASS_RO_GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00004861 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00004862 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004863 return CLASS_RO_GV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00004864
Fariborz Jahanian9e3ad522009-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 Jahanian4723fb72009-01-24 21:21:53 +00004877llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
Daniel Dunbar59e476b2009-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 Jahanian9e3ad522009-01-24 20:21:50 +00004883 std::vector<llvm::Constant*> Values(5);
4884 Values[0] = IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004885 Values[1] = SuperClassGV;
4886 if (!Values[1])
4887 Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004888 Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
4889 Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4890 Values[4] = ClassRoGV; // &CLASS_RO_GV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004891 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004892 Values);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00004893 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4894 GV->setInitializer(Init);
Fariborz Jahanian04087232009-01-31 01:07:39 +00004895 GV->setSection("__DATA, __objc_data");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00004896 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00004897 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian82208252009-01-31 00:59:10 +00004898 if (HiddenVisibility)
4899 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004900 return GV;
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004901}
4902
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004903bool
Fariborz Jahaniana6bed832009-05-21 01:03:45 +00004904CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00004905 return OD->getClassMethod(GetNullarySelector("load")) != 0;
Daniel Dunbar9a017d72009-05-15 22:33:15 +00004906}
4907
Daniel Dunbar961202372009-05-03 12:57:56 +00004908void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
Daniel Dunbar554fd792009-04-19 23:41:48 +00004909 uint32_t &InstanceStart,
4910 uint32_t &InstanceSize) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004911 const ASTRecordLayout &RL =
Daniel Dunbar9252ee12009-05-04 21:26:30 +00004912 CGM.getContext().getASTObjCImplementationLayout(OID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004913
Daniel Dunbar9b042e02009-05-04 23:23:09 +00004914 // InstanceSize is really instance end.
Ken Dyckd5090c12011-02-11 02:20:09 +00004915 InstanceSize = RL.getDataSize().getQuantity();
Daniel Dunbar9b042e02009-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 Dyckc5ca8762011-04-14 00:43:09 +00004921 InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
Daniel Dunbar554fd792009-04-19 23:41:48 +00004922}
4923
Fariborz Jahanian71394042009-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 Dunbar59e476b2009-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 Jahanian71394042009-01-23 23:53:38 +00004935 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004936 CGM.getModule(),
4937 ObjCTypes.ImpnfABITy,
4938 false,
4939 llvm::GlobalValue::ExternalLinkage,
4940 0,
4941 "_objc_empty_vtable");
Fariborz Jahanian71394042009-01-23 23:53:38 +00004942 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004943 assert(ID->getClassInterface() &&
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004944 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbare3f5cfc2009-04-20 20:18:54 +00004945 // FIXME: Is this correct (that meta class size is never computed)?
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004946 uint32_t InstanceStart =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00004947 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004948 uint32_t InstanceSize = InstanceStart;
4949 uint32_t flags = CLS_META;
Daniel Dunbar15894b72009-04-07 05:48:37 +00004950 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4951 std::string ObjCClassName(getClassSymbolPrefix());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004952
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004953 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004954
4955 bool classIsHidden =
John McCall457a04e2010-10-22 21:05:15 +00004956 ID->getClassInterface()->getVisibility() == HiddenVisibility;
Fariborz Jahanian82208252009-01-31 00:59:10 +00004957 if (classIsHidden)
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004958 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00004959 if (ID->getNumIvarInitializers())
4960 flags |= eClassFlags_ABI2_HasCXXStructors;
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004961 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004962 // class is root
4963 flags |= CLS_ROOT;
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00004964 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004965 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004966 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004967 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00004968 const ObjCInterfaceDecl *Root = ID->getClassInterface();
4969 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4970 Root = Super;
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004971 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00004972 if (Root->isWeakImported())
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004973 IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00004974 // work on super class metadata symbol.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004975 std::string SuperClassName =
Fariborz Jahaniana6227fd2009-12-01 18:25:24 +00004976 ObjCMetaClassName +
4977 ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00004978 SuperClassGV = GetClassGlobal(SuperClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00004979 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00004980 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian9e3ad522009-01-24 20:21:50 +00004981 }
4982 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4983 InstanceStart,
4984 InstanceSize,ID);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004985 std::string TClassName = ObjCMetaClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00004986 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian82208252009-01-31 00:59:10 +00004987 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4988 classIsHidden);
Fariborz Jahanian67260552009-11-17 21:37:35 +00004989 DefinedMetaClasses.push_back(MetaTClass);
Daniel Dunbar15894b72009-04-07 05:48:37 +00004990
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00004991 // Metadata for the class
4992 flags = CLS;
Fariborz Jahanian82208252009-01-31 00:59:10 +00004993 if (classIsHidden)
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00004994 flags |= OBJC2_CLS_HIDDEN;
Fariborz Jahanian0dec1e02010-04-28 21:28:56 +00004995 if (ID->getNumIvarInitializers())
4996 flags |= eClassFlags_ABI2_HasCXXStructors;
Daniel Dunbar8f28d012009-04-08 04:21:03 +00004997
Douglas Gregor78bd61f2009-06-18 16:11:24 +00004998 if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
Daniel Dunbar8f28d012009-04-08 04:21:03 +00004999 flags |= CLS_EXCEPTION;
5000
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005001 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005002 flags |= CLS_ROOT;
5003 SuperClassGV = 0;
Chris Lattnerb433b272009-04-19 06:02:28 +00005004 } else {
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005005 // Has a root. Current class is not a root.
Fariborz Jahanian03b300b2009-02-26 18:23:47 +00005006 std::string RootClassName =
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005007 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005008 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005009 if (ID->getClassInterface()->getSuperClass()->isWeakImported())
Fariborz Jahanian67260552009-11-17 21:37:35 +00005010 SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005011 }
Daniel Dunbar961202372009-05-03 12:57:56 +00005012 GetClassSizeInfo(ID, InstanceStart, InstanceSize);
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005013 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005014 InstanceStart,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005015 InstanceSize,
Fariborz Jahaniana887e632009-01-24 23:43:01 +00005016 ID);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005017
Fariborz Jahanian4723fb72009-01-24 21:21:53 +00005018 TClassName = ObjCClassName + ClassName;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005019 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian82208252009-01-31 00:59:10 +00005020 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
5021 classIsHidden);
Fariborz Jahanian279abd32009-01-30 20:55:31 +00005022 DefinedClasses.push_back(ClassMD);
Daniel Dunbar8f28d012009-04-08 04:21:03 +00005023
Daniel Dunbar9a017d72009-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 Dunbar8f28d012009-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 Jahanianc0577942011-04-22 22:02:28 +00005031 // Make sure method definition entries are all clear for next implementation.
5032 MethodDefinitions.clear();
Fariborz Jahanian71394042009-01-23 23:53:38 +00005033}
5034
Fariborz Jahanian097feda2009-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 Dunbar59e476b2009-08-03 17:06:42 +00005044 const ObjCProtocolDecl *PD) {
5045
Fariborz Jahanian464423d2009-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 Dunbar59e476b2009-08-03 17:06:42 +00005049 llvm::Constant *Init =
5050 llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
5051 ObjCTypes.ExternalProtocolPtrTy);
5052
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005053 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
Daniel Dunbar56df9772010-08-17 22:39:59 +00005054 ProtocolName += PD->getName();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005055
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005056 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
5057 if (PTGV)
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005058 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005059 PTGV = new llvm::GlobalVariable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005060 CGM.getModule(),
5061 Init->getType(), false,
5062 llvm::GlobalValue::WeakAnyLinkage,
5063 Init,
5064 ProtocolName);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005065 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
5066 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005067 CGM.AddUsedGlobal(PTGV);
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005068 return Builder.CreateLoad(PTGV, "tmp");
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005069}
5070
Fariborz Jahanian0c8d0602009-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 Dunbar9a017d72009-05-15 22:33:15 +00005081void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005082 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005083 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005084 std::string ExtCatName(Prefix + Interface->getNameAsString()+
5085 "_$_" + OCD->getNameAsString());
5086 std::string ExtClassName(getClassSymbolPrefix() +
Daniel Dunbar15894b72009-04-07 05:48:37 +00005087 Interface->getNameAsString());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005088
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005089 std::vector<llvm::Constant*> Values(6);
5090 Values[0] = GetClassName(OCD->getIdentifier());
5091 // meta-class entry symbol
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005092 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Douglas Gregor20b2ebd2011-03-23 00:50:03 +00005093 if (Interface->isWeakImported())
Fariborz Jahanian3ad8dcf2009-11-17 22:02:21 +00005094 ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
5095
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005096 Values[1] = ClassGV;
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005097 std::vector<llvm::Constant*> Methods;
5098 std::string MethodListName(Prefix);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005099 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005100 "_$_" + OCD->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005101
5102 for (ObjCCategoryImplDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005103 i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005104 // Instance methods should always be defined.
5105 Methods.push_back(GetMethodConstant(*i));
5106 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005107
5108 Values[2] = EmitMethodList(MethodListName,
5109 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005110 Methods);
5111
5112 MethodListName = Prefix;
5113 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
5114 OCD->getNameAsString();
5115 Methods.clear();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005116 for (ObjCCategoryImplDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005117 i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005118 // Class methods should always be defined.
5119 Methods.push_back(GetMethodConstant(*i));
5120 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005121
5122 Values[3] = EmitMethodList(MethodListName,
5123 "__DATA, __objc_const",
Fariborz Jahanian2612e142009-01-26 22:58:07 +00005124 Methods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005125 const ObjCCategoryDecl *Category =
Fariborz Jahanian066347e2009-01-28 22:18:42 +00005126 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005127 if (Category) {
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005128 llvm::SmallString<256> ExtName;
5129 llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
5130 << OCD->getName();
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005131 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005132 + Interface->getName() + "_$_"
5133 + Category->getName(),
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005134 Category->protocol_begin(),
5135 Category->protocol_end());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005136 Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
5137 OCD, Category, ObjCTypes);
Mike Stump658fe022009-07-30 22:28:39 +00005138 } else {
Owen Anderson0b75f232009-07-31 20:28:54 +00005139 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
5140 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
Fariborz Jahaniand8fc1052009-02-13 17:52:22 +00005141 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005142
5143 llvm::Constant *Init =
5144 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005145 Values);
5146 llvm::GlobalVariable *GCATV
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005147 = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005148 false,
5149 llvm::GlobalValue::InternalLinkage,
5150 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005151 ExtCatName);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005152 GCATV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005153 CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005154 GCATV->setSection("__DATA, __objc_const");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005155 CGM.AddUsedGlobal(GCATV);
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005156 DefinedCategories.push_back(GCATV);
Daniel Dunbar9a017d72009-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 Jahanianc0577942011-04-22 22:02:28 +00005161 // method definition entries must be clear for next implementation.
5162 MethodDefinitions.clear();
Fariborz Jahanian0c8d0602009-01-26 18:32:24 +00005163}
Fariborz Jahanian99113fd2009-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 Dunbar59e476b2009-08-03 17:06:42 +00005169 const ObjCMethodDecl *MD) {
Argyrios Kyrtzidis13257c52010-08-09 10:54:20 +00005170 llvm::Function *Fn = GetMethodDefinition(MD);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005171 if (!Fn)
5172 return 0;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005173
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005174 std::vector<llvm::Constant*> Method(3);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005175 Method[0] =
Owen Andersonade90fd2009-07-29 18:54:39 +00005176 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005177 ObjCTypes.SelectorPtrTy);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005178 Method[1] = GetMethodVarType(MD);
Owen Andersonade90fd2009-07-29 18:54:39 +00005179 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005180 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
Fariborz Jahanian99113fd2009-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 Dunbar349e6fb2009-10-18 20:48:59 +00005190llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
5191 const char *Section,
5192 const ConstantVector &Methods) {
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005193 // Return null for empty list.
5194 if (Methods.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005195 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005196
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005197 std::vector<llvm::Constant*> Values(3);
5198 // sizeof(struct _objc_method)
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005199 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005200 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005201 // method_count
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005202 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
Owen Anderson9793f0e2009-07-29 22:16:19 +00005203 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005204 Methods.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005205 Values[2] = llvm::ConstantArray::get(AT, Methods);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005206 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005207
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005208 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005209 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005210 llvm::GlobalValue::InternalLinkage,
5211 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005212 Name);
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005213 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005214 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005215 GV->setSection(Section);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005216 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00005217 return llvm::ConstantExpr::getBitCast(GV,
Fariborz Jahanian99113fd2009-01-26 21:38:32 +00005218 ObjCTypes.MethodListnfABIPtrTy);
5219}
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005220
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005221/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
5222/// the given ivar.
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005223llvm::GlobalVariable *
5224CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
5225 const ObjCIvarDecl *Ivar) {
5226 const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
Daniel Dunbar3f86b9c2009-05-05 00:36:57 +00005227 std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
Douglas Gregorbcced4e2009-04-09 21:40:53 +00005228 '.' + Ivar->getNameAsString();
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005229 llvm::GlobalVariable *IvarOffsetGV =
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005230 CGM.getModule().getGlobalVariable(Name);
5231 if (!IvarOffsetGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005232 IvarOffsetGV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005233 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005234 false,
5235 llvm::GlobalValue::ExternalLinkage,
5236 0,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005237 Name);
Fariborz Jahanian4e7ae062009-02-10 20:21:06 +00005238 return IvarOffsetGV;
5239}
5240
Daniel Dunbar8c7f9812010-04-02 21:14:02 +00005241llvm::Constant *
5242CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
5243 const ObjCIvarDecl *Ivar,
5244 unsigned long int Offset) {
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005245 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005246 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005247 Offset));
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005248 IvarOffsetGV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005249 CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
Daniel Dunbarbf90b332009-04-19 00:44:02 +00005250
Mike Stump18bb9282009-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 Dunbarbf90b332009-04-19 00:44:02 +00005253 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
5254 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
John McCall457a04e2010-10-22 21:05:15 +00005255 ID->getVisibility() == HiddenVisibility)
Fariborz Jahanian3d3426f2009-01-28 01:36:42 +00005256 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarf5f359f2009-04-14 06:00:08 +00005257 else
Fariborz Jahanianbc3c77b2009-04-06 18:30:00 +00005258 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Bill Wendlingf7d45982011-05-04 21:37:25 +00005259 IvarOffsetGV->setSection("__DATA, __objc_ivar");
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005260 return IvarOffsetGV;
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005261}
5262
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005263/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005264/// implementation. The return value has type
Fariborz Jahanian7415caa2009-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 Dunbarf5c18462009-04-20 06:54:31 +00005279
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005280llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005281 const ObjCImplementationDecl *ID) {
5282
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005283 std::vector<llvm::Constant*> Ivars, Ivar(5);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005284
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005285 const ObjCInterfaceDecl *OID = ID->getClassInterface();
5286 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005287
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005288 // FIXME. Consolidate this with similar code in GenerateClass.
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005289
Daniel Dunbarae032262009-04-20 00:33:43 +00005290 // Collect declared and synthesized ivars in a small vector.
Fariborz Jahanian63a224a2009-03-31 18:11:23 +00005291 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Fariborz Jahanian7c809592009-06-04 01:19:09 +00005292 CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005293
Daniel Dunbarf5c18462009-04-20 06:54:31 +00005294 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
5295 ObjCIvarDecl *IVD = OIvars[i];
Fariborz Jahanian7c809592009-06-04 01:19:09 +00005296 // Ignore unnamed bit-fields.
5297 if (!IVD->getDeclName())
5298 continue;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005299 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar961202372009-05-03 12:57:56 +00005300 ComputeIvarBaseOffset(CGM, ID, IVD));
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005301 Ivar[1] = GetMethodVarName(IVD->getIdentifier());
5302 Ivar[2] = GetMethodVarType(IVD);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005303 const llvm::Type *FieldTy =
Daniel Dunbar725dc2c2009-04-22 08:22:17 +00005304 CGM.getTypes().ConvertTypeForMem(IVD->getType());
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005305 unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005306 unsigned Align = CGM.getContext().getPreferredTypeAlign(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005307 IVD->getType().getTypePtr()) >> 3;
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005308 Align = llvm::Log2_32(Align);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005309 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbarae032262009-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 Andersonb7a2fe62009-07-24 23:12:58 +00005315 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005316 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005317 }
5318 // Return null for empty list.
5319 if (Ivars.empty())
Owen Anderson0b75f232009-07-31 20:28:54 +00005320 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005321 std::vector<llvm::Constant*> Values(3);
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005322 unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
Owen Andersonb7a2fe62009-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 Anderson9793f0e2009-07-29 22:16:19 +00005325 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005326 Ivars.size());
Owen Anderson47034e12009-07-28 18:33:04 +00005327 Values[2] = llvm::ConstantArray::get(AT, Ivars);
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005328 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005329 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
5330 llvm::GlobalVariable *GV =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005331 new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian7415caa2009-01-27 19:38:51 +00005332 llvm::GlobalValue::InternalLinkage,
5333 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005334 Prefix + OID->getName());
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005335 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005336 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Fariborz Jahanian40a4bcd2009-01-28 01:05:23 +00005337 GV->setSection("__DATA, __objc_const");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005338
Chris Lattnerf56501c2009-07-17 23:57:13 +00005339 CGM.AddUsedGlobal(GV);
Owen Andersonade90fd2009-07-29 18:54:39 +00005340 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005341}
5342
5343llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005344 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005345 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005346
Fariborz Jahanian56b3b772009-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 Dunbar59e476b2009-08-03 17:06:42 +00005351 Entry =
5352 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
5353 llvm::GlobalValue::ExternalLinkage,
5354 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005355 "\01l_OBJC_PROTOCOL_$_" + PD->getName());
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005356 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005357 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005358
Fariborz Jahanian56b3b772009-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 Dunbar59e476b2009-08-03 17:06:42 +00005380 const ObjCProtocolDecl *PD) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005381 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005382
Fariborz Jahanian56b3b772009-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 Jahanian56b3b772009-01-29 19:24:30 +00005387 // Construct method lists.
5388 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
5389 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005390 for (ObjCProtocolDecl::instmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005391 i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005392 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005393 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005394 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5395 OptInstanceMethods.push_back(C);
5396 } else {
5397 InstanceMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005398 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005399 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005400
5401 for (ObjCProtocolDecl::classmeth_iterator
Argyrios Kyrtzidiscfbfe782009-06-30 02:36:12 +00005402 i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005403 ObjCMethodDecl *MD = *i;
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005404 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005405 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
5406 OptClassMethods.push_back(C);
5407 } else {
5408 ClassMethods.push_back(C);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005409 }
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005410 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005411
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005412 std::vector<llvm::Constant*> Values(10);
5413 // isa is NULL
Owen Anderson0b75f232009-07-31 20:28:54 +00005414 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005415 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005416 Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
5417 PD->protocol_begin(),
5418 PD->protocol_end());
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005419
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005420 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005421 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005422 "__DATA, __objc_const",
5423 InstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005424 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005425 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005426 "__DATA, __objc_const",
5427 ClassMethods);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005428 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005429 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005430 "__DATA, __objc_const",
5431 OptInstanceMethods);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005432 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005433 + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005434 "__DATA, __objc_const",
5435 OptClassMethods);
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005436 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005437 0, PD, ObjCTypes);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005438 uint32_t Size =
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005439 CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005440 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Owen Anderson0b75f232009-07-31 20:28:54 +00005441 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005442 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005443 Values);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005444
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005445 if (Entry) {
5446 // Already created, fix the linkage and update the initializer.
Mike Stumpa6ca3342009-03-07 16:33:28 +00005447 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005448 Entry->setInitializer(Init);
5449 } else {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005450 Entry =
Daniel Dunbar349e6fb2009-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 Jahanianc22f2362009-01-31 02:43:27 +00005454 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005455 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005456 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005457 }
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005458 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005459 CGM.AddUsedGlobal(Entry);
5460
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005461 // Use this protocol meta-data to build protocol list table in section
5462 // __DATA, __objc_protolist
Daniel Dunbar349e6fb2009-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 Jahanianc22f2362009-01-31 02:43:27 +00005467 PTGV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005468 CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbarb25452a2009-04-15 02:56:18 +00005469 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanian61cd4b52009-01-29 20:10:59 +00005470 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Chris Lattnerf56501c2009-07-17 23:57:13 +00005471 CGM.AddUsedGlobal(PTGV);
Fariborz Jahanian56b3b772009-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 Dunbar349e6fb2009-10-18 20:48:59 +00005484CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
5485 ObjCProtocolDecl::protocol_iterator begin,
5486 ObjCProtocolDecl::protocol_iterator end) {
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005487 std::vector<llvm::Constant*> ProtocolRefs;
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005488
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005489 // Just return null for empty protocol lists
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005490 if (begin == end)
Owen Anderson0b75f232009-07-31 20:28:54 +00005491 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005492
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005493 // FIXME: We shouldn't need to do this lookup here, should we?
Daniel Dunbar349e6fb2009-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 Jahanian56b3b772009-01-29 19:24:30 +00005498 if (GV)
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00005499 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005500
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005501 for (; begin != end; ++begin)
5502 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
5503
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005504 // This list is null terminated.
Owen Anderson0b75f232009-07-31 20:28:54 +00005505 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005506 ObjCTypes.ProtocolnfABIPtrTy));
5507
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005508 std::vector<llvm::Constant*> Values(2);
Owen Anderson170229f2009-07-14 23:10:40 +00005509 Values[0] =
Owen Andersonb7a2fe62009-07-24 23:12:58 +00005510 llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005511 Values[1] =
Owen Anderson47034e12009-07-28 18:33:04 +00005512 llvm::ConstantArray::get(
Owen Anderson9793f0e2009-07-29 22:16:19 +00005513 llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005514 ProtocolRefs.size()),
5515 ProtocolRefs);
5516
Nick Lewycky41eaf0a2009-09-19 20:00:52 +00005517 llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
Owen Andersonc10c8d32009-07-08 19:05:04 +00005518 GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005519 llvm::GlobalValue::InternalLinkage,
5520 Init,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005521 Name);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005522 GV->setSection("__DATA, __objc_const");
Fariborz Jahanianc22f2362009-01-31 02:43:27 +00005523 GV->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005524 CGM.getTargetData().getABITypeAlignment(Init->getType()));
Chris Lattnerf56501c2009-07-17 23:57:13 +00005525 CGM.AddUsedGlobal(GV);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005526 return llvm::ConstantExpr::getBitCast(GV,
Daniel Dunbar8de90f02009-02-15 07:36:20 +00005527 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian56b3b772009-01-29 19:24:30 +00005528}
5529
Fariborz Jahaniand9c28b82009-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 Anderson170229f2009-07-14 23:10:40 +00005540 Desc[0] =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005541 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
5542 ObjCTypes.SelectorPtrTy);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005543 Desc[1] = GetMethodVarType(MD);
Fariborz Jahanian097feda2009-01-30 18:58:59 +00005544 // Protocol methods have no implementation. So, this entry is always NULL.
Owen Anderson0b75f232009-07-31 20:28:54 +00005545 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Owen Anderson0e0189d2009-07-27 22:29:56 +00005546 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
Fariborz Jahaniand9c28b82009-01-30 00:46:37 +00005547}
Fariborz Jahanianc88a70d2009-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 Dunbar59e476b2009-08-03 17:06:42 +00005554///
Fariborz Jahanian712bfa62009-02-03 19:03:09 +00005555LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
John McCall96fa4842010-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 Dunbar9fd114d2009-04-22 07:32:20 +00005562 return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
5563 EmitIvarOffset(CGF, ID, Ivar));
Fariborz Jahanianc88a70d2009-02-03 00:09:52 +00005564}
5565
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005566llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005567 CodeGen::CodeGenFunction &CGF,
5568 const ObjCInterfaceDecl *Interface,
5569 const ObjCIvarDecl *Ivar) {
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005570 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
Fariborz Jahanian21fc74c2009-02-10 19:02:04 +00005571}
5572
John McCall234eac82011-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 Dunbar59e476b2009-08-03 17:06:42 +00005579
John McCall234eac82011-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 McCall9e8bb002011-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 McCall234eac82011-05-13 23:16:18 +00005606 // Compute the actual arguments.
5607 CallArgList args;
5608
John McCall9e8bb002011-05-14 03:10:52 +00005609 // First argument: the receiver / super-call structure.
John McCall234eac82011-05-13 23:16:18 +00005610 if (!isSuper)
John McCall9e8bb002011-05-14 03:10:52 +00005611 arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
5612 args.add(RValue::get(arg0), arg0Type);
John McCall234eac82011-05-13 23:16:18 +00005613
John McCall9e8bb002011-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 McCall234eac82011-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 McCall5880fb82011-05-14 21:12:11 +00005624 NullReturnState nullReturn;
5625
John McCall9e8bb002011-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 McCall234eac82011-05-13 23:16:18 +00005633 llvm::Constant *fn = 0;
5634 std::string messageRefName("\01l_");
5635 if (CGM.ReturnTypeUsesSRet(fnInfo)) {
John McCall234eac82011-05-13 23:16:18 +00005636 if (isSuper) {
5637 fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
5638 messageRefName += "objc_msgSendSuper2_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005639 } else {
John McCall5880fb82011-05-14 21:12:11 +00005640 nullReturn.init(CGF, arg0);
John McCall234eac82011-05-13 23:16:18 +00005641 fn = ObjCTypes.getMessageSendStretFixupFn();
5642 messageRefName += "objc_msgSend_stret_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005643 }
John McCall234eac82011-05-13 23:16:18 +00005644 } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
5645 fn = ObjCTypes.getMessageSendFpretFixupFn();
5646 messageRefName += "objc_msgSend_fpret_fixup";
Mike Stump658fe022009-07-30 22:28:39 +00005647 } else {
John McCall234eac82011-05-13 23:16:18 +00005648 if (isSuper) {
5649 fn = ObjCTypes.getMessageSendSuper2FixupFn();
5650 messageRefName += "objc_msgSendSuper2_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005651 } else {
John McCall234eac82011-05-13 23:16:18 +00005652 fn = ObjCTypes.getMessageSendFixupFn();
5653 messageRefName += "objc_msgSend_fixup";
Chris Lattner396639d2010-08-18 16:09:06 +00005654 }
Fariborz Jahaniane4dc35d2009-02-04 20:42:28 +00005655 }
John McCall234eac82011-05-13 23:16:18 +00005656 assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
5657 messageRefName += '_';
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005658
John McCall234eac82011-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 McCall9e8bb002011-05-14 03:10:52 +00005666 // Build the message ref structure.
John McCall234eac82011-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 McCall9e8bb002011-05-14 03:10:52 +00005683 // Update the message ref argument.
John McCall234eac82011-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 McCall5880fb82011-05-14 21:12:11 +00005696 RValue result = CGF.EmitCall(fnInfo, callee, returnSlot, args);
5697 return nullReturn.complete(CGF, result, resultType);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005698}
5699
5700/// Generate code for a message send expression in the nonfragile abi.
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005701CodeGen::RValue
5702CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
John McCall78a15112010-05-22 01:48:05 +00005703 ReturnValueSlot Return,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005704 QualType ResultType,
5705 Selector Sel,
5706 llvm::Value *Receiver,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005707 const CallArgList &CallArgs,
David Chisnall01aa4672010-04-28 19:33:36 +00005708 const ObjCInterfaceDecl *Class,
Daniel Dunbaraff9fca2009-09-17 04:01:22 +00005709 const ObjCMethodDecl *Method) {
John McCall9e8bb002011-05-14 03:10:52 +00005710 return isVTableDispatchedSelector(Sel)
5711 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005712 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00005713 false, CallArgs, Method)
5714 : EmitMessageSend(CGF, Return, ResultType,
5715 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005716 Receiver, CGF.getContext().getObjCIdType(),
John McCall9e8bb002011-05-14 03:10:52 +00005717 false, CallArgs, Method, ObjCTypes);
Fariborz Jahanian3d9296e2009-02-04 00:22:57 +00005718}
5719
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005720llvm::GlobalVariable *
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005721CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005722 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5723
Daniel Dunbara6468342009-03-02 05:18:14 +00005724 if (!GV) {
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005725 GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005726 false, llvm::GlobalValue::ExternalLinkage,
5727 0, Name);
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005728 }
5729
5730 return GV;
5731}
5732
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005733llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
5734 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005735 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005736
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005737 if (!Entry) {
Daniel Dunbar15894b72009-04-07 05:48:37 +00005738 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarc6928bb2009-03-01 04:40:10 +00005739 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005740 Entry =
5741 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005742 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005743 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005744 "\01L_OBJC_CLASSLIST_REFERENCES_$_");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005745 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005746 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005747 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005748 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005749 CGM.AddUsedGlobal(Entry);
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005750 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005751
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005752 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005753}
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005754
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005755llvm::Value *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005756CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005757 const ObjCInterfaceDecl *ID) {
5758 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005759
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005760 if (!Entry) {
5761 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5762 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005763 Entry =
5764 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005765 false, llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005766 ClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005767 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005768 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005769 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005770 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005771 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005772 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005773 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005774
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005775 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian33f66e62009-02-05 20:41:40 +00005776}
5777
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005778/// EmitMetaClassRef - Return a Value * of the address of _class_t
5779/// meta-data
5780///
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005781llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5782 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005783 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5784 if (Entry)
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005785 return Builder.CreateLoad(Entry, "tmp");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005786
Daniel Dunbar15894b72009-04-07 05:48:37 +00005787 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00005788 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005789 Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00005790 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005791 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005792 MetaClassGV,
Owen Andersonc10c8d32009-07-08 19:05:04 +00005793 "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005794 Entry->setAlignment(
Daniel Dunbar710cb202010-04-25 20:39:32 +00005795 CGM.getTargetData().getABITypeAlignment(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005796 ObjCTypes.ClassnfABIPtrTy));
5797
Daniel Dunbare60aa052009-04-15 19:03:14 +00005798 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005799 CGM.AddUsedGlobal(Entry);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005800
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005801 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005802}
5803
Fariborz Jahanian33f66e62009-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 Gregor20b2ebd2011-03-23 00:50:03 +00005808 if (ID->isWeakImported()) {
Fariborz Jahanian95ace552009-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 Jahanian33f66e62009-02-05 20:41:40 +00005814 return EmitClassRef(Builder, ID);
5815}
5816
Fariborz Jahanian6b7cd6e2009-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 McCall78a15112010-05-22 01:48:05 +00005822 ReturnValueSlot Return,
Daniel Dunbar59e476b2009-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 Dunbaraff9fca2009-09-17 04:01:22 +00005829 const CodeGen::CallArgList &CallArgs,
5830 const ObjCMethodDecl *Method) {
Fariborz Jahanian6b7cd6e2009-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 McCall66475842011-03-04 08:00:29 +00005835 CGF.CreateTempAlloca(ObjCTypes.SuperTy, "objc_super");
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005836
Fariborz Jahanian6b7cd6e2009-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 Dunbar59e476b2009-08-03 17:06:42 +00005841
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005842 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanianbac73ac2009-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 Dunbar508a7dd2009-04-18 08:51:00 +00005848 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005849 Target = CGF.Builder.CreateStructGEP(Target, 0);
5850 Target = CGF.Builder.CreateLoad(Target);
Mike Stump658fe022009-07-30 22:28:39 +00005851 } else
Fariborz Jahanianbac73ac2009-02-28 20:07:56 +00005852 Target = EmitMetaClassRef(CGF.Builder, Class);
Mike Stump658fe022009-07-30 22:28:39 +00005853 } else
Daniel Dunbar508a7dd2009-04-18 08:51:00 +00005854 Target = EmitSuperClassRef(CGF.Builder, Class);
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005855
Mike Stump18bb9282009-05-16 07:57:57 +00005856 // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
5857 // ObjCTypes types.
Fariborz Jahanian6b7cd6e2009-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 Dunbar59e476b2009-08-03 17:06:42 +00005863
John McCall9e8bb002011-05-14 03:10:52 +00005864 return (isVTableDispatchedSelector(Sel))
5865 ? EmitVTableMessageSend(CGF, Return, ResultType, Sel,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005866 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00005867 true, CallArgs, Method)
5868 : EmitMessageSend(CGF, Return, ResultType,
5869 EmitSelector(CGF.Builder, Sel),
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005870 ObjCSuper, ObjCTypes.SuperPtrCTy,
John McCall9e8bb002011-05-14 03:10:52 +00005871 true, CallArgs, Method, ObjCTypes);
Fariborz Jahanian6b7cd6e2009-02-06 20:09:23 +00005872}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005873
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005874llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00005875 Selector Sel, bool lval) {
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005876 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005877
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005878 if (!Entry) {
Daniel Dunbar59e476b2009-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 Jahanian5d5ed2d2009-05-11 19:25:47 +00005886 Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Chris Lattnerf56501c2009-07-17 23:57:13 +00005887 CGM.AddUsedGlobal(Entry);
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005888 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005889
Fariborz Jahanian9240f3d2010-06-17 19:56:20 +00005890 if (lval)
5891 return Entry;
Daniel Dunbarc76493a2009-11-29 21:23:36 +00005892 return Builder.CreateLoad(Entry, "tmp");
Fariborz Jahanian74b77222009-02-11 20:51:17 +00005893}
Fariborz Jahanian06292952009-02-16 22:52:32 +00005894/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005895/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
Fariborz Jahanian06292952009-02-16 22:52:32 +00005896///
5897void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005898 llvm::Value *src,
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005899 llvm::Value *dst,
5900 llvm::Value *ivarOffset) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005901 const llvm::Type * SrcTy = src->getType();
5902 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005903 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-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 Jahanian1b074a32009-03-13 00:42:52 +00005907 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5908 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005909 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5910 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian7a95d722009-09-24 22:25:38 +00005911 CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
5912 src, dst, ivarOffset);
Fariborz Jahanian06292952009-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 Dunbar59e476b2009-08-03 17:06:42 +00005920 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005921 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005922 const llvm::Type * SrcTy = src->getType();
5923 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005924 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-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 Dunbar59e476b2009-08-03 17:06:42 +00005927 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian1b074a32009-03-13 00:42:52 +00005928 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5929 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005930 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5931 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner0a696a422009-04-22 02:38:11 +00005932 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005933 src, dst, "weakassign");
5934 return;
5935}
5936
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005937void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005938 CodeGen::CodeGenFunction &CGF,
5939 llvm::Value *DestPtr,
5940 llvm::Value *SrcPtr,
Fariborz Jahanian021510e2010-06-15 22:44:06 +00005941 llvm::Value *Size) {
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005942 SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
5943 DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005944 CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
Fariborz Jahanian021510e2010-06-15 22:44:06 +00005945 DestPtr, SrcPtr, Size);
Fariborz Jahanian5f21d2f2009-07-08 01:18:33 +00005946 return;
5947}
5948
Fariborz Jahanian06292952009-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 Dunbar59e476b2009-08-03 17:06:42 +00005953 CodeGen::CodeGenFunction &CGF,
Mike Stump11289f42009-09-09 15:08:12 +00005954 llvm::Value *AddrWeakObj) {
Eli Friedmana374b682009-03-07 03:57:15 +00005955 const llvm::Type* DestTy =
Daniel Dunbar59e476b2009-08-03 17:06:42 +00005956 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
5957 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Chris Lattnerce8754e2009-04-22 02:44:54 +00005958 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
Fariborz Jahanian06292952009-02-16 22:52:32 +00005959 AddrWeakObj, "weakread");
Eli Friedmana374b682009-03-07 03:57:15 +00005960 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian06292952009-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 Stump11289f42009-09-09 15:08:12 +00005968 llvm::Value *src, llvm::Value *dst) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005969 const llvm::Type * SrcTy = src->getType();
5970 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005971 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-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 Jahanian1b074a32009-03-13 00:42:52 +00005975 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5976 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005977 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5978 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner6fdd57c2009-04-17 22:12:36 +00005979 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian06292952009-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 Jahanian217af242010-07-20 20:30:03 +00005988 llvm::Value *src, llvm::Value *dst,
5989 bool threadlocal) {
Fariborz Jahanianaedcfa42009-03-23 19:10:40 +00005990 const llvm::Type * SrcTy = src->getType();
5991 if (!isa<llvm::PointerType>(SrcTy)) {
Duncan Sandsc76fe8b2009-05-09 07:08:47 +00005992 unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
Fariborz Jahanianaedcfa42009-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 Jahanian1b074a32009-03-13 00:42:52 +00005996 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5997 }
Fariborz Jahanian06292952009-02-16 22:52:32 +00005998 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5999 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian217af242010-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 Jahanian06292952009-02-16 22:52:32 +00006006 return;
6007}
Fariborz Jahanian74b77222009-02-11 20:51:17 +00006008
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006009void
John McCallbd309292010-07-06 01:34:17 +00006010CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
6011 const ObjCAtSynchronizedStmt &S) {
David Chisnall3e575602011-03-25 17:46:35 +00006012 EmitAtSynchronizedStmt(CGF, S,
6013 cast<llvm::Function>(ObjCTypes.getSyncEnterFn()),
6014 cast<llvm::Function>(ObjCTypes.getSyncExitFn()));
John McCallbd309292010-07-06 01:34:17 +00006015}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006016
John McCall2ca705e2010-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 McCallbd309292010-07-06 01:34:17 +00006042void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
6043 const ObjCAtTryStmt &S) {
David Chisnall3e575602011-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 Dunbar0b0dcd92009-02-24 07:47:38 +00006048}
6049
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006050/// EmitThrowStmt - Generate code for a throw statement.
6051void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
6052 const ObjCAtThrowStmt &S) {
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006053 if (const Expr *ThrowExpr = S.getThrowExpr()) {
John McCall17afe452010-10-16 08:21:07 +00006054 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
John McCalld5091822010-10-16 16:34:08 +00006055 Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy,
6056 "tmp");
John McCall17afe452010-10-16 08:21:07 +00006057 llvm::Value *Args[] = { Exception };
6058 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(),
6059 Args, Args+1)
6060 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006061 } else {
John McCall17afe452010-10-16 08:21:07 +00006062 CGF.EmitCallOrInvoke(ObjCTypes.getExceptionRethrowFn(), 0, 0)
6063 .setDoesNotReturn();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006064 }
6065
John McCall17afe452010-10-16 08:21:07 +00006066 CGF.Builder.CreateUnreachable();
Anders Carlsson9ab53d12009-02-16 22:59:18 +00006067 CGF.Builder.ClearInsertionPoint();
6068}
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006069
John McCall2ca705e2010-07-24 00:37:23 +00006070llvm::Constant *
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006071CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006072 bool ForDefinition) {
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006073 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006074
Daniel Dunbar8f28d012009-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 Dunbard7beeea2009-04-07 06:43:45 +00006080
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006081 // If this type (or a super class) has the __objc_exception__
6082 // attribute, emit an external reference.
Douglas Gregor78bd61f2009-06-18 16:11:24 +00006083 if (hasObjCExceptionAttribute(CGM.getContext(), ID))
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006084 return Entry =
Owen Andersonc10c8d32009-07-08 19:05:04 +00006085 new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006086 llvm::GlobalValue::ExternalLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006087 0,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006088 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006089 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006090 }
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006091
Daniel Dunbar8f28d012009-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 Dunbar15894b72009-04-07 05:48:37 +00006095 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006096 std::string VTableName = "objc_ehtype_vtable";
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006097 llvm::GlobalVariable *VTableGV =
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006098 CGM.getModule().getGlobalVariable(VTableName);
6099 if (!VTableGV)
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006100 VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
6101 false,
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006102 llvm::GlobalValue::ExternalLinkage,
Owen Andersonc10c8d32009-07-08 19:05:04 +00006103 0, VTableName);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006104
Chris Lattner5e016ae2010-06-27 07:15:29 +00006105 llvm::Value *VTableIdx =
6106 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006107
6108 std::vector<llvm::Constant*> Values(3);
Owen Andersonade90fd2009-07-29 18:54:39 +00006109 Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006110 Values[1] = GetClassName(ID->getIdentifier());
Fariborz Jahanian899e7eb2009-04-14 18:41:56 +00006111 Values[2] = GetClassGlobal(ClassName);
Owen Anderson170229f2009-07-14 23:10:40 +00006112 llvm::Constant *Init =
Owen Anderson0e0189d2009-07-27 22:29:56 +00006113 llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
Daniel Dunbarb1559a42009-03-01 04:46:24 +00006114
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006115 if (Entry) {
6116 Entry->setInitializer(Init);
6117 } else {
Owen Andersonc10c8d32009-07-08 19:05:04 +00006118 Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006119 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006120 Init,
Daniel Dunbar349e6fb2009-10-18 20:48:59 +00006121 ("OBJC_EHTYPE_$_" +
Daniel Dunbar07d07852009-10-18 21:17:35 +00006122 ID->getIdentifier()->getName()));
Daniel Dunbar8f28d012009-04-08 04:21:03 +00006123 }
6124
John McCall457a04e2010-10-22 21:05:15 +00006125 if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
Daniel Dunbar15894b72009-04-07 05:48:37 +00006126 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar710cb202010-04-25 20:39:32 +00006127 Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
6128 ObjCTypes.EHTypeTy));
Daniel Dunbar8f28d012009-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 Dunbarb1559a42009-03-01 04:46:24 +00006136
6137 return Entry;
6138}
Daniel Dunbar59e476b2009-08-03 17:06:42 +00006139
Daniel Dunbar8b8683f2008-08-12 00:12:39 +00006140/* *** */
6141
Daniel Dunbarb036db82008-08-13 03:21:16 +00006142CodeGen::CGObjCRuntime *
6143CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
David Chisnall067f0ed2011-03-22 21:21:24 +00006144 if (CGM.getLangOptions().ObjCNonFragileABI)
6145 return new CGObjCNonFragileABIMac(CGM);
Daniel Dunbar303e2c22008-08-11 02:45:11 +00006146 return new CGObjCMac(CGM);
6147}