blob: 97410cb213c73aa76b96d001e29d30f74defa7c1 [file] [log] [blame]
Daniel Dunbar8c85fac2008-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//
10// This provides Objective-C code generation targetting the Apple runtime.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
Daniel Dunbar1be1df32008-08-11 21:35:06 +000015
16#include "CodeGenModule.h"
Daniel Dunbarace33292008-08-16 03:19:19 +000017#include "CodeGenFunction.h"
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000018#include "clang/AST/ASTContext.h"
Daniel Dunbarde300732008-08-11 04:54:23 +000019#include "clang/AST/Decl.h"
Daniel Dunbarcffcdac2008-08-13 03:21:16 +000020#include "clang/AST/DeclObjC.h"
Daniel Dunbar1be1df32008-08-11 21:35:06 +000021#include "clang/Basic/LangOptions.h"
22
Daniel Dunbar75de89f2009-02-24 07:47:38 +000023#include "llvm/Intrinsics.h"
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000024#include "llvm/Module.h"
Daniel Dunbar35b777f2008-10-29 22:36:39 +000025#include "llvm/ADT/DenseSet.h"
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +000026#include "llvm/Target/TargetData.h"
Daniel Dunbarace33292008-08-16 03:19:19 +000027#include <sstream>
Daniel Dunbar8c85fac2008-08-11 02:45:11 +000028
29using namespace clang;
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +000030using namespace CodeGen;
Daniel Dunbar8c85fac2008-08-11 02:45:11 +000031
32namespace {
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000033
Daniel Dunbarfe131f02008-08-27 02:31:56 +000034 typedef std::vector<llvm::Constant*> ConstantVector;
35
Daniel Dunbarcffcdac2008-08-13 03:21:16 +000036 // FIXME: We should find a nicer way to make the labels for
37 // metadata, string concatenation is lame.
38
Fariborz Jahanian48543f52009-01-21 22:04:16 +000039class ObjCCommonTypesHelper {
40protected:
41 CodeGen::CodeGenModule &CGM;
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000042
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000043public:
Fariborz Jahanianad51ca02009-03-23 19:10:40 +000044 const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +000045 const llvm::Type *Int8PtrTy;
Fariborz Jahanian48543f52009-01-21 22:04:16 +000046
Daniel Dunbar6fa3daf2008-08-12 05:28:47 +000047 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
48 const llvm::Type *ObjectPtrTy;
Fariborz Jahanianc192d4d2008-11-18 20:18:11 +000049
50 /// PtrObjectPtrTy - LLVM type for id *
51 const llvm::Type *PtrObjectPtrTy;
52
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +000053 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Daniel Dunbar6fa3daf2008-08-12 05:28:47 +000054 const llvm::Type *SelectorPtrTy;
Daniel Dunbarcffcdac2008-08-13 03:21:16 +000055 /// ProtocolPtrTy - LLVM type for external protocol handles
56 /// (typeof(Protocol))
57 const llvm::Type *ExternalProtocolPtrTy;
Fariborz Jahanian48543f52009-01-21 22:04:16 +000058
Daniel Dunbar0ed60b02008-08-30 03:02:31 +000059 // SuperCTy - clang type for struct objc_super.
60 QualType SuperCTy;
61 // SuperPtrCTy - clang type for struct objc_super *.
62 QualType SuperPtrCTy;
Fariborz Jahanian48543f52009-01-21 22:04:16 +000063
Daniel Dunbar15245e52008-08-23 04:28:29 +000064 /// SuperTy - LLVM type for struct objc_super.
65 const llvm::StructType *SuperTy;
Daniel Dunbar87062ff2008-08-23 09:25:55 +000066 /// SuperPtrTy - LLVM type for struct objc_super *.
67 const llvm::Type *SuperPtrTy;
Fariborz Jahanian48543f52009-01-21 22:04:16 +000068
Fariborz Jahaniand0374812009-01-22 23:02:58 +000069 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
70 /// in GCC parlance).
71 const llvm::StructType *PropertyTy;
72
73 /// PropertyListTy - LLVM type for struct objc_property_list
74 /// (_prop_list_t in GCC parlance).
75 const llvm::StructType *PropertyListTy;
76 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
77 const llvm::Type *PropertyListPtrTy;
78
79 // MethodTy - LLVM type for struct objc_method.
80 const llvm::StructType *MethodTy;
81
Fariborz Jahanian781f2732009-01-23 01:46:23 +000082 /// CacheTy - LLVM type for struct objc_cache.
83 const llvm::Type *CacheTy;
84 /// CachePtrTy - LLVM type for struct objc_cache *.
85 const llvm::Type *CachePtrTy;
86
Chris Lattneraea1aee2009-03-22 21:03:39 +000087 llvm::Constant *GetPropertyFn, *SetPropertyFn;
Fariborz Jahanian4b161702009-01-22 00:37:21 +000088
Chris Lattneraea1aee2009-03-22 21:03:39 +000089 llvm::Constant *EnumerationMutationFn;
Fariborz Jahanian4b161702009-01-22 00:37:21 +000090
91 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
Chris Lattneraea1aee2009-03-22 21:03:39 +000092 llvm::Constant *GcReadWeakFn;
Fariborz Jahanian4b161702009-01-22 00:37:21 +000093
94 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
Chris Lattner293c1d32009-04-17 22:12:36 +000095 llvm::Constant *getGcAssignWeakFn() {
96 // id objc_assign_weak (id, id *)
97 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
98 Args.push_back(ObjectPtrTy->getPointerTo());
99 llvm::FunctionType *FTy =
100 llvm::FunctionType::get(ObjectPtrTy, Args, false);
101 return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
102 }
Fariborz Jahanian4b161702009-01-22 00:37:21 +0000103
104 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
Chris Lattneraea1aee2009-03-22 21:03:39 +0000105 llvm::Constant *GcAssignGlobalFn;
Fariborz Jahanian4b161702009-01-22 00:37:21 +0000106
107 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
Chris Lattneraea1aee2009-03-22 21:03:39 +0000108 llvm::Constant *GcAssignIvarFn;
Fariborz Jahanian4b161702009-01-22 00:37:21 +0000109
110 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
Chris Lattneraea1aee2009-03-22 21:03:39 +0000111 llvm::Constant *GcAssignStrongCastFn;
Anders Carlsson1cf75362009-02-16 22:59:18 +0000112
113 /// ExceptionThrowFn - LLVM objc_exception_throw function.
Chris Lattneraea1aee2009-03-22 21:03:39 +0000114 llvm::Constant *ExceptionThrowFn;
Anders Carlsson1cf75362009-02-16 22:59:18 +0000115
Daniel Dunbar34416d62009-02-24 01:43:46 +0000116 /// SyncEnterFn - LLVM object_sync_enter function.
Chris Lattner23e24652009-04-06 16:53:45 +0000117 llvm::Constant *getSyncEnterFn() {
118 // void objc_sync_enter (id)
119 std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
120 llvm::FunctionType *FTy =
121 llvm::FunctionType::get(llvm::Type::VoidTy, Args, false);
122 return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
123 }
Daniel Dunbar34416d62009-02-24 01:43:46 +0000124
125 /// SyncExitFn - LLVM object_sync_exit function.
Chris Lattneraea1aee2009-03-22 21:03:39 +0000126 llvm::Constant *SyncExitFn;
Daniel Dunbar34416d62009-02-24 01:43:46 +0000127
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000128 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
129 ~ObjCCommonTypesHelper(){}
130};
Daniel Dunbar15245e52008-08-23 04:28:29 +0000131
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000132/// ObjCTypesHelper - Helper class that encapsulates lazy
133/// construction of varies types used during ObjC generation.
134class ObjCTypesHelper : public ObjCCommonTypesHelper {
135private:
136
Chris Lattner61114192009-04-22 02:32:31 +0000137 llvm::Constant *getMessageSendFn() {
138 // id objc_msgSend (id, SEL, ...)
139 std::vector<const llvm::Type*> Params;
140 Params.push_back(ObjectPtrTy);
141 Params.push_back(SelectorPtrTy);
142 return
143 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
144 Params, true),
145 "objc_msgSend");
146 }
147
148 llvm::Constant *getMessageSendStretFn() {
149 // id objc_msgSend_stret (id, SEL, ...)
150 std::vector<const llvm::Type*> Params;
151 Params.push_back(ObjectPtrTy);
152 Params.push_back(SelectorPtrTy);
153 return
154 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
155 Params, true),
156 "objc_msgSend_stret");
157
158 }
159
160 llvm::Constant *getMessageSendFpretFn() {
161 // FIXME: This should be long double on x86_64?
162 // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
163 std::vector<const llvm::Type*> Params;
164 Params.push_back(ObjectPtrTy);
165 Params.push_back(SelectorPtrTy);
166 return
167 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::DoubleTy,
168 Params,
169 true),
170 "objc_msgSend_fpret");
171
172 }
173
174 llvm::Constant *getMessageSendSuperFn() {
175 // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
176 std::vector<const llvm::Type*> Params;
177 Params.push_back(SuperPtrTy);
178 Params.push_back(SelectorPtrTy);
179 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
180 Params, true),
181 "objc_msgSendSuper");
182 }
183 llvm::Constant *getMessageSendSuperStretFn() {
184 // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
185 // SEL op, ...)
186 std::vector<const llvm::Type*> Params;
187 Params.push_back(Int8PtrTy);
188 Params.push_back(SuperPtrTy);
189 Params.push_back(SelectorPtrTy);
190 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
191 Params, true),
192 "objc_msgSendSuper_stret");
193 }
194
195 llvm::Constant *getMessageSendSuperFpretFn() {
196 // There is no objc_msgSendSuper_fpret? How can that work?
197 return getMessageSendSuperFn();
198 }
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000199
200public:
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000201 /// SymtabTy - LLVM type for struct objc_symtab.
202 const llvm::StructType *SymtabTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000203 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
204 const llvm::Type *SymtabPtrTy;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000205 /// ModuleTy - LLVM type for struct objc_module.
206 const llvm::StructType *ModuleTy;
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000207
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000208 /// ProtocolTy - LLVM type for struct objc_protocol.
209 const llvm::StructType *ProtocolTy;
210 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
211 const llvm::Type *ProtocolPtrTy;
212 /// ProtocolExtensionTy - LLVM type for struct
213 /// objc_protocol_extension.
214 const llvm::StructType *ProtocolExtensionTy;
215 /// ProtocolExtensionTy - LLVM type for struct
216 /// objc_protocol_extension *.
217 const llvm::Type *ProtocolExtensionPtrTy;
218 /// MethodDescriptionTy - LLVM type for struct
219 /// objc_method_description.
220 const llvm::StructType *MethodDescriptionTy;
221 /// MethodDescriptionListTy - LLVM type for struct
222 /// objc_method_description_list.
223 const llvm::StructType *MethodDescriptionListTy;
224 /// MethodDescriptionListPtrTy - LLVM type for struct
225 /// objc_method_description_list *.
226 const llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000227 /// ProtocolListTy - LLVM type for struct objc_property_list.
228 const llvm::Type *ProtocolListTy;
229 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
230 const llvm::Type *ProtocolListPtrTy;
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000231 /// CategoryTy - LLVM type for struct objc_category.
232 const llvm::StructType *CategoryTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000233 /// ClassTy - LLVM type for struct objc_class.
234 const llvm::StructType *ClassTy;
235 /// ClassPtrTy - LLVM type for struct objc_class *.
236 const llvm::Type *ClassPtrTy;
237 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
238 const llvm::StructType *ClassExtensionTy;
239 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
240 const llvm::Type *ClassExtensionPtrTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000241 // IvarTy - LLVM type for struct objc_ivar.
242 const llvm::StructType *IvarTy;
243 /// IvarListTy - LLVM type for struct objc_ivar_list.
244 const llvm::Type *IvarListTy;
245 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
246 const llvm::Type *IvarListPtrTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000247 /// MethodListTy - LLVM type for struct objc_method_list.
248 const llvm::Type *MethodListTy;
249 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
250 const llvm::Type *MethodListPtrTy;
Anders Carlsson9acb0a42008-09-09 10:10:21 +0000251
252 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
253 const llvm::Type *ExceptionDataTy;
254
Anders Carlsson9acb0a42008-09-09 10:10:21 +0000255 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
Chris Lattnere05d4cb2009-04-22 02:26:14 +0000256 llvm::Constant *getExceptionTryEnterFn() {
257 std::vector<const llvm::Type*> Params;
258 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
259 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
260 Params, false),
261 "objc_exception_try_enter");
262 }
Anders Carlsson9acb0a42008-09-09 10:10:21 +0000263
264 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
Chris Lattnere05d4cb2009-04-22 02:26:14 +0000265 llvm::Constant *getExceptionTryExitFn() {
266 std::vector<const llvm::Type*> Params;
267 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
268 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
269 Params, false),
270 "objc_exception_try_exit");
271 }
Anders Carlsson9acb0a42008-09-09 10:10:21 +0000272
273 /// ExceptionExtractFn - LLVM objc_exception_extract function.
Chris Lattnere05d4cb2009-04-22 02:26:14 +0000274 llvm::Constant *getExceptionExtractFn() {
275 std::vector<const llvm::Type*> Params;
276 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
277 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
278 Params, false),
279 "objc_exception_extract");
280
281 }
Anders Carlsson9acb0a42008-09-09 10:10:21 +0000282
283 /// ExceptionMatchFn - LLVM objc_exception_match function.
Chris Lattnere05d4cb2009-04-22 02:26:14 +0000284 llvm::Constant *getExceptionMatchFn() {
285 std::vector<const llvm::Type*> Params;
286 Params.push_back(ClassPtrTy);
287 Params.push_back(ObjectPtrTy);
288 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty,
289 Params, false),
290 "objc_exception_match");
291
292 }
Anders Carlsson9acb0a42008-09-09 10:10:21 +0000293
294 /// SetJmpFn - LLVM _setjmp function.
Chris Lattnere05d4cb2009-04-22 02:26:14 +0000295 llvm::Constant *getSetJmpFn() {
296 std::vector<const llvm::Type*> Params;
297 Params.push_back(llvm::PointerType::getUnqual(llvm::Type::Int32Ty));
298 return
299 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty,
300 Params, false),
301 "_setjmp");
302
303 }
Chris Lattnerdd978702008-11-15 21:26:17 +0000304
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000305public:
306 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000307 ~ObjCTypesHelper() {}
Daniel Dunbaraecef4c2008-10-17 03:24:53 +0000308
309
Chris Lattneraea1aee2009-03-22 21:03:39 +0000310 llvm::Constant *getSendFn(bool IsSuper) {
Chris Lattner61114192009-04-22 02:32:31 +0000311 return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
Daniel Dunbaraecef4c2008-10-17 03:24:53 +0000312 }
313
Chris Lattneraea1aee2009-03-22 21:03:39 +0000314 llvm::Constant *getSendStretFn(bool IsSuper) {
Chris Lattner61114192009-04-22 02:32:31 +0000315 return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
Daniel Dunbaraecef4c2008-10-17 03:24:53 +0000316 }
317
Chris Lattneraea1aee2009-03-22 21:03:39 +0000318 llvm::Constant *getSendFpretFn(bool IsSuper) {
Chris Lattner61114192009-04-22 02:32:31 +0000319 return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
Daniel Dunbaraecef4c2008-10-17 03:24:53 +0000320 }
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000321};
322
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000323/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000324/// modern abi
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000325class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanianf52110f2009-02-04 20:42:28 +0000326public:
Chris Lattneraea1aee2009-03-22 21:03:39 +0000327 llvm::Constant *MessageSendFixupFn, *MessageSendFpretFixupFn,
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +0000328 *MessageSendStretFixupFn, *MessageSendIdFixupFn,
329 *MessageSendIdStretFixupFn, *MessageSendSuper2FixupFn,
330 *MessageSendSuper2StretFixupFn;
331
Fariborz Jahanian781f2732009-01-23 01:46:23 +0000332 // MethodListnfABITy - LLVM for struct _method_list_t
333 const llvm::StructType *MethodListnfABITy;
334
335 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
336 const llvm::Type *MethodListnfABIPtrTy;
337
338 // ProtocolnfABITy = LLVM for struct _protocol_t
339 const llvm::StructType *ProtocolnfABITy;
340
Daniel Dunbar1f42bb02009-02-15 07:36:20 +0000341 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
342 const llvm::Type *ProtocolnfABIPtrTy;
343
Fariborz Jahanian781f2732009-01-23 01:46:23 +0000344 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
345 const llvm::StructType *ProtocolListnfABITy;
346
347 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
348 const llvm::Type *ProtocolListnfABIPtrTy;
349
350 // ClassnfABITy - LLVM for struct _class_t
351 const llvm::StructType *ClassnfABITy;
352
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000353 // ClassnfABIPtrTy - LLVM for struct _class_t*
354 const llvm::Type *ClassnfABIPtrTy;
355
Fariborz Jahanian781f2732009-01-23 01:46:23 +0000356 // IvarnfABITy - LLVM for struct _ivar_t
357 const llvm::StructType *IvarnfABITy;
358
359 // IvarListnfABITy - LLVM for struct _ivar_list_t
360 const llvm::StructType *IvarListnfABITy;
361
362 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
363 const llvm::Type *IvarListnfABIPtrTy;
364
365 // ClassRonfABITy - LLVM for struct _class_ro_t
366 const llvm::StructType *ClassRonfABITy;
367
368 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
369 const llvm::Type *ImpnfABITy;
370
371 // CategorynfABITy - LLVM for struct _category_t
372 const llvm::StructType *CategorynfABITy;
373
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +0000374 // New types for nonfragile abi messaging.
375
376 // MessageRefTy - LLVM for:
377 // struct _message_ref_t {
378 // IMP messenger;
379 // SEL name;
380 // };
381 const llvm::StructType *MessageRefTy;
Fariborz Jahanianf52110f2009-02-04 20:42:28 +0000382 // MessageRefCTy - clang type for struct _message_ref_t
383 QualType MessageRefCTy;
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +0000384
385 // MessageRefPtrTy - LLVM for struct _message_ref_t*
386 const llvm::Type *MessageRefPtrTy;
Fariborz Jahanianf52110f2009-02-04 20:42:28 +0000387 // MessageRefCPtrTy - clang type for struct _message_ref_t*
388 QualType MessageRefCPtrTy;
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +0000389
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +0000390 // MessengerTy - Type of the messenger (shown as IMP above)
391 const llvm::FunctionType *MessengerTy;
392
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +0000393 // SuperMessageRefTy - LLVM for:
394 // struct _super_message_ref_t {
395 // SUPER_IMP messenger;
396 // SEL name;
397 // };
398 const llvm::StructType *SuperMessageRefTy;
399
400 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
401 const llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar75de89f2009-02-24 07:47:38 +0000402
403 /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C
404 /// exception personality function.
Chris Lattner23e24652009-04-06 16:53:45 +0000405 llvm::Value *getEHPersonalityPtr() {
406 llvm::Constant *Personality =
407 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty,
408 std::vector<const llvm::Type*>(),
409 true),
410 "__objc_personality_v0");
411 return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy);
412 }
Daniel Dunbar75de89f2009-02-24 07:47:38 +0000413
Chris Lattner93dca5b2009-04-22 02:15:23 +0000414 llvm::Constant *getUnwindResumeOrRethrowFn() {
415 std::vector<const llvm::Type*> Params;
416 Params.push_back(Int8PtrTy);
417 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
418 Params, false),
419 "_Unwind_Resume_or_Rethrow");
420 }
421
422 llvm::Constant *getObjCEndCatchFn() {
423 std::vector<const llvm::Type*> Params;
424 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
425 Params, false),
426 "objc_end_catch");
427
428 }
429
430 llvm::Constant *getObjCBeginCatchFn() {
431 std::vector<const llvm::Type*> Params;
432 Params.push_back(Int8PtrTy);
433 return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
434 Params, false),
435 "objc_begin_catch");
436 }
Daniel Dunbar9c285e72009-03-01 04:46:24 +0000437
438 const llvm::StructType *EHTypeTy;
439 const llvm::Type *EHTypePtrTy;
Daniel Dunbar75de89f2009-02-24 07:47:38 +0000440
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000441 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
442 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000443};
444
445class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +0000446public:
447 // FIXME - accessibility
Fariborz Jahanian37931062009-03-10 16:22:08 +0000448 class GC_IVAR {
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +0000449 public:
Fariborz Jahanian37931062009-03-10 16:22:08 +0000450 unsigned int ivar_bytepos;
451 unsigned int ivar_size;
452 GC_IVAR() : ivar_bytepos(0), ivar_size(0) {}
453 };
454
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +0000455 class SKIP_SCAN {
456 public:
457 unsigned int skip;
458 unsigned int scan;
459 SKIP_SCAN() : skip(0), scan(0) {}
460 };
461
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000462protected:
463 CodeGen::CodeGenModule &CGM;
464 // FIXME! May not be needing this after all.
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000465 unsigned ObjCABI;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000466
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +0000467 // gc ivar layout bitmap calculation helper caches.
468 llvm::SmallVector<GC_IVAR, 16> SkipIvars;
469 llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
470 llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
Fariborz Jahanian37931062009-03-10 16:22:08 +0000471
Daniel Dunbar8ede0052008-08-25 06:02:07 +0000472 /// LazySymbols - Symbols to generate a lazy reference for. See
473 /// DefinedSymbols and FinishModule().
474 std::set<IdentifierInfo*> LazySymbols;
475
476 /// DefinedSymbols - External symbols which are defined by this
477 /// module. The symbols in this list and LazySymbols are used to add
478 /// special linker symbols which ensure that Objective-C modules are
479 /// linked properly.
480 std::set<IdentifierInfo*> DefinedSymbols;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000481
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000482 /// ClassNames - uniqued class names.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000483 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000484
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000485 /// MethodVarNames - uniqued method variable names.
486 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000487
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000488 /// MethodVarTypes - uniqued method type signatures. We have to use
489 /// a StringMap here because have no other unique reference.
490 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000491
Daniel Dunbar12996f52008-08-26 21:51:14 +0000492 /// MethodDefinitions - map of methods which have been defined in
493 /// this translation unit.
494 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000495
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000496 /// PropertyNames - uniqued method variable names.
497 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000498
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000499 /// ClassReferences - uniqued class references.
500 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000501
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000502 /// SelectorReferences - uniqued selector references.
503 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000504
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000505 /// Protocols - Protocols for which an objc_protocol structure has
506 /// been emitted. Forward declarations are handled by creating an
507 /// empty structure whose initializer is filled in when/if defined.
508 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000509
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000510 /// DefinedProtocols - Protocols which have actually been
511 /// defined. We should not need this, see FIXME in GenerateProtocol.
512 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000513
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000514 /// DefinedClasses - List of defined classes.
515 std::vector<llvm::GlobalValue*> DefinedClasses;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000516
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000517 /// DefinedCategories - List of defined categories.
518 std::vector<llvm::GlobalValue*> DefinedCategories;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000519
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000520 /// UsedGlobals - List of globals to pack into the llvm.used metadata
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000521 /// to prevent them from being clobbered.
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000522 std::vector<llvm::GlobalVariable*> UsedGlobals;
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000523
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +0000524 /// GetNameForMethod - Return a name for the given method.
525 /// \param[out] NameOut - The return value.
526 void GetNameForMethod(const ObjCMethodDecl *OMD,
527 const ObjCContainerDecl *CD,
528 std::string &NameOut);
529
530 /// GetMethodVarName - Return a unique constant for the given
531 /// selector's name. The return value has type char *.
532 llvm::Constant *GetMethodVarName(Selector Sel);
533 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
534 llvm::Constant *GetMethodVarName(const std::string &Name);
535
536 /// GetMethodVarType - Return a unique constant for the given
537 /// selector's name. The return value has type char *.
538
539 // FIXME: This is a horrible name.
540 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Daniel Dunbar356f0742009-04-20 06:54:31 +0000541 llvm::Constant *GetMethodVarType(const FieldDecl *D);
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +0000542
543 /// GetPropertyName - Return a unique constant for the given
544 /// name. The return value has type char *.
545 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
546
547 // FIXME: This can be dropped once string functions are unified.
548 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
549 const Decl *Container);
550
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +0000551 /// GetClassName - Return a unique constant for the given selector's
552 /// name. The return value has type char *.
553 llvm::Constant *GetClassName(IdentifierInfo *Ident);
554
Fariborz Jahanian6d49ab62009-03-11 21:42:00 +0000555 /// GetInterfaceDeclStructLayout - Get layout for ivars of given
556 /// interface declaration.
557 const llvm::StructLayout *GetInterfaceDeclStructLayout(
558 const ObjCInterfaceDecl *ID) const;
559
Fariborz Jahanian01b3e342009-03-05 22:39:55 +0000560 /// BuildIvarLayout - Builds ivar layout bitmap for the class
561 /// implementation for the __strong or __weak case.
562 ///
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +0000563 llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
564 bool ForStrongLayout);
Fariborz Jahanian01b3e342009-03-05 22:39:55 +0000565
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +0000566 void BuildAggrIvarLayout(const ObjCInterfaceDecl *OI,
567 const llvm::StructLayout *Layout,
Fariborz Jahanian37931062009-03-10 16:22:08 +0000568 const RecordDecl *RD,
Chris Lattner9329cf52009-03-31 08:48:01 +0000569 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Fariborz Jahanian01b3e342009-03-05 22:39:55 +0000570 unsigned int BytePos, bool ForStrongLayout,
571 int &Index, int &SkIndex, bool &HasUnion);
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +0000572
Fariborz Jahanian7345eba2009-03-05 19:17:31 +0000573 /// GetIvarLayoutName - Returns a unique constant for the given
574 /// ivar layout bitmap.
575 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
576 const ObjCCommonTypesHelper &ObjCTypes);
577
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +0000578 /// EmitPropertyList - Emit the given property list. The return
579 /// value has type PropertyListPtrTy.
580 llvm::Constant *EmitPropertyList(const std::string &Name,
581 const Decl *Container,
582 const ObjCContainerDecl *OCD,
583 const ObjCCommonTypesHelper &ObjCTypes);
584
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000585 /// GetProtocolRef - Return a reference to the internal protocol
586 /// description, creating an empty one if it has not been
587 /// defined. The return value has type ProtocolPtrTy.
588 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahaniand65949b2009-03-08 20:18:37 +0000589
590 /// GetIvarBaseOffset - returns ivars byte offset.
591 uint64_t GetIvarBaseOffset(const llvm::StructLayout *Layout,
Chris Lattnerd391dab2009-03-31 08:33:16 +0000592 const FieldDecl *Field);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000593
Chris Lattnerd391dab2009-03-31 08:33:16 +0000594 /// GetFieldBaseOffset - return's field byte offset.
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +0000595 uint64_t GetFieldBaseOffset(const ObjCInterfaceDecl *OI,
596 const llvm::StructLayout *Layout,
Chris Lattnerd391dab2009-03-31 08:33:16 +0000597 const FieldDecl *Field);
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +0000598
Daniel Dunbarc4594f22009-03-09 20:09:19 +0000599 /// CreateMetadataVar - Create a global variable with internal
600 /// linkage for use by the Objective-C runtime.
601 ///
602 /// This is a convenience wrapper which not only creates the
603 /// variable, but also sets the section and alignment and adds the
604 /// global to the UsedGlobals list.
Daniel Dunbareddddd22009-03-09 20:50:13 +0000605 ///
606 /// \param Name - The variable name.
607 /// \param Init - The variable initializer; this is also used to
608 /// define the type of the variable.
609 /// \param Section - The section the variable should go into, or 0.
610 /// \param Align - The alignment for the variable, or 0.
611 /// \param AddToUsed - Whether the variable should be added to
Daniel Dunbar6b343692009-04-14 17:42:51 +0000612 /// "llvm.used".
Daniel Dunbarc4594f22009-03-09 20:09:19 +0000613 llvm::GlobalVariable *CreateMetadataVar(const std::string &Name,
614 llvm::Constant *Init,
615 const char *Section,
Daniel Dunbareddddd22009-03-09 20:50:13 +0000616 unsigned Align,
617 bool AddToUsed);
Daniel Dunbarc4594f22009-03-09 20:09:19 +0000618
Daniel Dunbar356f0742009-04-20 06:54:31 +0000619 /// GetNamedIvarList - Return the list of ivars in the interface
620 /// itself (not including super classes and not including unnamed
621 /// bitfields).
622 ///
623 /// For the non-fragile ABI, this also includes synthesized property
624 /// ivars.
625 void GetNamedIvarList(const ObjCInterfaceDecl *OID,
626 llvm::SmallVector<ObjCIvarDecl*, 16> &Res) const;
627
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000628public:
629 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGM(cgm)
630 { }
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000631
Steve Naroff2c8a08e2009-03-31 16:53:37 +0000632 virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *SL);
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000633
634 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
635 const ObjCContainerDecl *CD=0);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000636
637 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
638
639 /// GetOrEmitProtocol - Get the protocol object for the given
640 /// declaration, emitting it if necessary. The return value has type
641 /// ProtocolPtrTy.
642 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
643
644 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
645 /// object for the given declaration, emitting it if needed. These
646 /// forward references will be filled in with empty bodies if no
647 /// definition is seen. The return value has type ProtocolPtrTy.
648 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000649};
650
651class CGObjCMac : public CGObjCCommonMac {
652private:
653 ObjCTypesHelper ObjCTypes;
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000654 /// EmitImageInfo - Emit the image info marker used to encode some module
655 /// level information.
656 void EmitImageInfo();
657
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000658 /// EmitModuleInfo - Another marker encoding module level
659 /// information.
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000660 void EmitModuleInfo();
661
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000662 /// EmitModuleSymols - Emit module symbols, the list of defined
663 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000664 llvm::Constant *EmitModuleSymbols();
665
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000666 /// FinishModule - Write out global data structures at the end of
667 /// processing a translation unit.
668 void FinishModule();
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000669
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000670 /// EmitClassExtension - Generate the class extension structure used
671 /// to store the weak ivar layout and properties. The return value
672 /// has type ClassExtensionPtrTy.
673 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
674
675 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
676 /// for the given class.
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000677 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000678 const ObjCInterfaceDecl *ID);
679
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000680 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000681 QualType ResultType,
682 Selector Sel,
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000683 llvm::Value *Arg0,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000684 QualType Arg0Ty,
685 bool IsSuper,
686 const CallArgList &CallArgs);
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000687
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000688 /// EmitIvarList - Emit the ivar list for the given
689 /// implementation. If ForClass is true the list of class ivars
690 /// (i.e. metaclass ivars) is emitted, otherwise the list of
691 /// interface ivars will be emitted. The return value has type
692 /// IvarListPtrTy.
693 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +0000694 bool ForClass);
695
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000696 /// EmitMetaClass - Emit a forward reference to the class structure
697 /// for the metaclass of the given interface. The return value has
698 /// type ClassPtrTy.
699 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
700
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000701 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000702 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000703 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
704 llvm::Constant *Protocols,
Daniel Dunbar12996f52008-08-26 21:51:14 +0000705 const llvm::Type *InterfaceTy,
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000706 const ConstantVector &Methods);
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000707
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000708 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000709
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000710 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000711
712 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar6b57d432008-08-26 08:29:31 +0000713 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000714 llvm::Constant *EmitMethodList(const std::string &Name,
715 const char *Section,
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000716 const ConstantVector &Methods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000717
718 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000719 /// method declarations.
720 /// - TypeName: The name for the type containing the methods.
721 /// - IsProtocol: True iff these methods are for a protocol.
722 /// - ClassMethds: True iff these are class methods.
723 /// - Required: When true, only "required" methods are
724 /// listed. Similarly, when false only "optional" methods are
725 /// listed. For classes this should always be true.
726 /// - begin, end: The method list to output.
727 ///
728 /// The return value has type MethodDescriptionListPtrTy.
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000729 llvm::Constant *EmitMethodDescList(const std::string &Name,
730 const char *Section,
731 const ConstantVector &Methods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000732
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000733 /// GetOrEmitProtocol - Get the protocol object for the given
734 /// declaration, emitting it if necessary. The return value has type
735 /// ProtocolPtrTy.
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000736 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000737
738 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
739 /// object for the given declaration, emitting it if needed. These
740 /// forward references will be filled in with empty bodies if no
741 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000742 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000743
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000744 /// EmitProtocolExtension - Generate the protocol extension
745 /// structure used to store optional instance and class methods, and
746 /// protocol properties. The return value has type
747 /// ProtocolExtensionPtrTy.
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000748 llvm::Constant *
749 EmitProtocolExtension(const ObjCProtocolDecl *PD,
750 const ConstantVector &OptInstanceMethods,
751 const ConstantVector &OptClassMethods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000752
753 /// EmitProtocolList - Generate the list of referenced
754 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar67e778b2008-08-21 21:57:41 +0000755 llvm::Constant *EmitProtocolList(const std::string &Name,
756 ObjCProtocolDecl::protocol_iterator begin,
757 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000758
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000759 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
760 /// for the given selector.
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000761 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000762
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000763 public:
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000764 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000765
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000766 virtual llvm::Function *ModuleInitFunction();
767
Daniel Dunbara04840b2008-08-23 03:46:30 +0000768 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000769 QualType ResultType,
770 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000771 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000772 bool IsClassMessage,
773 const CallArgList &CallArgs);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000774
Daniel Dunbara04840b2008-08-23 03:46:30 +0000775 virtual CodeGen::RValue
776 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000777 QualType ResultType,
778 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000779 const ObjCInterfaceDecl *Class,
Fariborz Jahanian17636fa2009-02-28 20:07:56 +0000780 bool isCategoryImpl,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000781 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000782 bool IsClassMessage,
783 const CallArgList &CallArgs);
Daniel Dunbar434627a2008-08-16 00:25:02 +0000784
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000785 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000786 const ObjCInterfaceDecl *ID);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000787
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000788 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000789
Daniel Dunbarac93e472008-08-15 22:20:32 +0000790 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000791
Daniel Dunbarac93e472008-08-15 22:20:32 +0000792 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000793
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000794 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000795 const ObjCProtocolDecl *PD);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000796
Chris Lattneraea1aee2009-03-22 21:03:39 +0000797 virtual llvm::Constant *GetPropertyGetFunction();
798 virtual llvm::Constant *GetPropertySetFunction();
799 virtual llvm::Constant *EnumerationMutationFunction();
Anders Carlssonb01a2112008-09-09 10:04:29 +0000800
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +0000801 virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
802 const Stmt &S);
Anders Carlssonb01a2112008-09-09 10:04:29 +0000803 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
804 const ObjCAtThrowStmt &S);
Fariborz Jahanian252d87f2008-11-18 22:37:34 +0000805 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian3305ad32008-11-18 21:45:40 +0000806 llvm::Value *AddrWeakObj);
Fariborz Jahanian252d87f2008-11-18 22:37:34 +0000807 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
808 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian17958902008-11-19 00:59:10 +0000809 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
810 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanianf310b592008-11-20 19:23:36 +0000811 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
812 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian17958902008-11-19 00:59:10 +0000813 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
814 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian4337afe2009-02-02 20:02:29 +0000815
Fariborz Jahanianc912eb72009-02-03 19:03:09 +0000816 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
817 QualType ObjectTy,
818 llvm::Value *BaseValue,
819 const ObjCIvarDecl *Ivar,
Fariborz Jahanianc912eb72009-02-03 19:03:09 +0000820 unsigned CVRQualifiers);
Fariborz Jahanian27cc6662009-02-10 19:02:04 +0000821 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
822 ObjCInterfaceDecl *Interface,
823 const ObjCIvarDecl *Ivar);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000824};
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000825
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000826class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000827private:
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000828 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000829 llvm::GlobalVariable* ObjCEmptyCacheVar;
830 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbarc0318b22009-03-02 06:08:11 +0000831
Daniel Dunbar3c190812009-04-18 08:51:00 +0000832 /// SuperClassReferences - uniqued super class references.
833 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
834
Fariborz Jahanianf3a44012009-02-06 20:09:23 +0000835 /// MetaClassReferences - uniqued meta class references.
836 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbar9c285e72009-03-01 04:46:24 +0000837
838 /// EHTypeReferences - uniqued class ehtype references.
839 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbarc0318b22009-03-02 06:08:11 +0000840
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000841 /// FinishNonFragileABIModule - Write out global data structures at the end of
842 /// processing a translation unit.
843 void FinishNonFragileABIModule();
Daniel Dunbarc2129532009-04-08 04:21:03 +0000844
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +0000845 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
846 unsigned InstanceStart,
847 unsigned InstanceSize,
848 const ObjCImplementationDecl *ID);
Fariborz Jahanian06726462009-01-24 21:21:53 +0000849 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
850 llvm::Constant *IsAGV,
851 llvm::Constant *SuperClassGV,
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +0000852 llvm::Constant *ClassRoGV,
853 bool HiddenVisibility);
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000854
855 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
856
Fariborz Jahanian151747b2009-01-30 00:46:37 +0000857 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
858
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000859 /// EmitMethodList - Emit the method list for the given
860 /// implementation. The return value has type MethodListnfABITy.
861 llvm::Constant *EmitMethodList(const std::string &Name,
862 const char *Section,
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +0000863 const ConstantVector &Methods);
864 /// EmitIvarList - Emit the ivar list for the given
865 /// implementation. If ForClass is true the list of class ivars
866 /// (i.e. metaclass ivars) is emitted, otherwise the list of
867 /// interface ivars will be emitted. The return value has type
868 /// IvarListnfABIPtrTy.
869 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +0000870
Fariborz Jahaniancc00f922009-02-10 20:21:06 +0000871 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian150f7732009-01-28 01:36:42 +0000872 const ObjCIvarDecl *Ivar,
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +0000873 unsigned long int offset);
874
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000875 /// GetOrEmitProtocol - Get the protocol object for the given
876 /// declaration, emitting it if necessary. The return value has type
877 /// ProtocolPtrTy.
878 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
879
880 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
881 /// object for the given declaration, emitting it if needed. These
882 /// forward references will be filled in with empty bodies if no
883 /// definition is seen. The return value has type ProtocolPtrTy.
884 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
885
886 /// EmitProtocolList - Generate the list of referenced
887 /// protocols. The return value has type ProtocolListPtrTy.
888 llvm::Constant *EmitProtocolList(const std::string &Name,
889 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian7e881162009-02-04 00:22:57 +0000890 ObjCProtocolDecl::protocol_iterator end);
891
892 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
893 QualType ResultType,
894 Selector Sel,
Fariborz Jahanianf52110f2009-02-04 20:42:28 +0000895 llvm::Value *Receiver,
Fariborz Jahanian7e881162009-02-04 00:22:57 +0000896 QualType Arg0Ty,
897 bool IsSuper,
898 const CallArgList &CallArgs);
Daniel Dunbarabbda222009-03-01 04:40:10 +0000899
900 /// GetClassGlobal - Return the global variable for the Objective-C
901 /// class of the given name.
Fariborz Jahanianab438842009-04-14 18:41:56 +0000902 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
903
Fariborz Jahanian917c0402009-02-05 20:41:40 +0000904 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
Daniel Dunbar3c190812009-04-18 08:51:00 +0000905 /// for the given class reference.
Fariborz Jahanian917c0402009-02-05 20:41:40 +0000906 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar3c190812009-04-18 08:51:00 +0000907 const ObjCInterfaceDecl *ID);
908
909 /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
910 /// for the given super class reference.
911 llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
912 const ObjCInterfaceDecl *ID);
Fariborz Jahanianf3a44012009-02-06 20:09:23 +0000913
914 /// EmitMetaClassRef - Return a Value * of the address of _class_t
915 /// meta-data
916 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
917 const ObjCInterfaceDecl *ID);
918
Fariborz Jahaniancc00f922009-02-10 20:21:06 +0000919 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
920 /// the given ivar.
921 ///
Daniel Dunbar07d204a2009-04-19 00:31:15 +0000922 llvm::GlobalVariable * ObjCIvarOffsetVariable(
Fariborz Jahaniana09a5142009-02-12 18:51:23 +0000923 const ObjCInterfaceDecl *ID,
Fariborz Jahaniancc00f922009-02-10 20:21:06 +0000924 const ObjCIvarDecl *Ivar);
Fariborz Jahanian917c0402009-02-05 20:41:40 +0000925
Fariborz Jahanianebb82c62009-02-11 20:51:17 +0000926 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
927 /// for the given selector.
928 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
Daniel Dunbar9c285e72009-03-01 04:46:24 +0000929
Daniel Dunbarc2129532009-04-08 04:21:03 +0000930 /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
Daniel Dunbar9c285e72009-03-01 04:46:24 +0000931 /// interface. The return value has type EHTypePtrTy.
Daniel Dunbarc2129532009-04-08 04:21:03 +0000932 llvm::Value *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
933 bool ForDefinition);
Daniel Dunbara2d275d2009-04-07 05:48:37 +0000934
935 const char *getMetaclassSymbolPrefix() const {
936 return "OBJC_METACLASS_$_";
937 }
Daniel Dunbarc0318b22009-03-02 06:08:11 +0000938
Daniel Dunbara2d275d2009-04-07 05:48:37 +0000939 const char *getClassSymbolPrefix() const {
940 return "OBJC_CLASS_$_";
941 }
942
Daniel Dunbarecb5d402009-04-19 23:41:48 +0000943 void GetClassSizeInfo(const ObjCInterfaceDecl *OID,
944 uint32_t &InstanceStart,
945 uint32_t &InstanceSize);
946
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000947public:
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000948 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000949 // FIXME. All stubs for now!
950 virtual llvm::Function *ModuleInitFunction();
951
952 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
953 QualType ResultType,
954 Selector Sel,
955 llvm::Value *Receiver,
956 bool IsClassMessage,
Fariborz Jahanian7e881162009-02-04 00:22:57 +0000957 const CallArgList &CallArgs);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000958
959 virtual CodeGen::RValue
960 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
961 QualType ResultType,
962 Selector Sel,
963 const ObjCInterfaceDecl *Class,
Fariborz Jahanian17636fa2009-02-28 20:07:56 +0000964 bool isCategoryImpl,
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000965 llvm::Value *Receiver,
966 bool IsClassMessage,
Fariborz Jahanianf3a44012009-02-06 20:09:23 +0000967 const CallArgList &CallArgs);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000968
969 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian917c0402009-02-05 20:41:40 +0000970 const ObjCInterfaceDecl *ID);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000971
972 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel)
Fariborz Jahanianebb82c62009-02-11 20:51:17 +0000973 { return EmitSelector(Builder, Sel); }
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000974
Fariborz Jahanianfe49a092009-01-26 18:32:24 +0000975 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000976
977 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000978 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian5d13ab12009-01-30 18:58:59 +0000979 const ObjCProtocolDecl *PD);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000980
Chris Lattneraea1aee2009-03-22 21:03:39 +0000981 virtual llvm::Constant *GetPropertyGetFunction() {
Fariborz Jahanian27cc6662009-02-10 19:02:04 +0000982 return ObjCTypes.GetPropertyFn;
983 }
Chris Lattneraea1aee2009-03-22 21:03:39 +0000984 virtual llvm::Constant *GetPropertySetFunction() {
Fariborz Jahanian27cc6662009-02-10 19:02:04 +0000985 return ObjCTypes.SetPropertyFn;
986 }
Chris Lattneraea1aee2009-03-22 21:03:39 +0000987 virtual llvm::Constant *EnumerationMutationFunction() {
Daniel Dunbar978d2be2009-02-16 18:48:45 +0000988 return ObjCTypes.EnumerationMutationFn;
989 }
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000990
991 virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar75de89f2009-02-24 07:47:38 +0000992 const Stmt &S);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000993 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlsson1cf75362009-02-16 22:59:18 +0000994 const ObjCAtThrowStmt &S);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000995 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian5eefb432009-02-16 22:52:32 +0000996 llvm::Value *AddrWeakObj);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000997 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian5eefb432009-02-16 22:52:32 +0000998 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000999 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00001000 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00001001 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00001002 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00001003 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00001004 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00001005 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
1006 QualType ObjectTy,
1007 llvm::Value *BaseValue,
1008 const ObjCIvarDecl *Ivar,
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00001009 unsigned CVRQualifiers);
Fariborz Jahanian27cc6662009-02-10 19:02:04 +00001010 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
1011 ObjCInterfaceDecl *Interface,
1012 const ObjCIvarDecl *Ivar);
Fariborz Jahanian48543f52009-01-21 22:04:16 +00001013};
1014
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001015} // end anonymous namespace
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00001016
1017/* *** Helper Functions *** */
1018
1019/// getConstantGEP() - Help routine to construct simple GEPs.
1020static llvm::Constant *getConstantGEP(llvm::Constant *C,
1021 unsigned idx0,
1022 unsigned idx1) {
1023 llvm::Value *Idxs[] = {
1024 llvm::ConstantInt::get(llvm::Type::Int32Ty, idx0),
1025 llvm::ConstantInt::get(llvm::Type::Int32Ty, idx1)
1026 };
1027 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
1028}
1029
Daniel Dunbarc2129532009-04-08 04:21:03 +00001030/// hasObjCExceptionAttribute - Return true if this class or any super
1031/// class has the __objc_exception__ attribute.
1032static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *OID) {
Daniel Dunbar78582862009-04-13 21:08:27 +00001033 if (OID->hasAttr<ObjCExceptionAttr>())
Daniel Dunbarc2129532009-04-08 04:21:03 +00001034 return true;
1035 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
1036 return hasObjCExceptionAttribute(Super);
1037 return false;
1038}
1039
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00001040/* *** CGObjCMac Public Interface *** */
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001041
Fariborz Jahanian48543f52009-01-21 22:04:16 +00001042CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
1043 ObjCTypes(cgm)
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00001044{
Fariborz Jahanian48543f52009-01-21 22:04:16 +00001045 ObjCABI = 1;
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00001046 EmitImageInfo();
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001047}
1048
Daniel Dunbar434627a2008-08-16 00:25:02 +00001049/// GetClass - Return a reference to the class for the given interface
1050/// decl.
Daniel Dunbard916e6e2008-11-01 01:53:16 +00001051llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001052 const ObjCInterfaceDecl *ID) {
1053 return EmitClassRef(Builder, ID);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001054}
1055
1056/// GetSelector - Return the pointer to the unique'd string for this selector.
Daniel Dunbard916e6e2008-11-01 01:53:16 +00001057llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) {
Daniel Dunbar5eec6142008-08-12 03:39:23 +00001058 return EmitSelector(Builder, Sel);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001059}
1060
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00001061/// Generate a constant CFString object.
1062/*
1063 struct __builtin_CFString {
1064 const int *isa; // point to __CFConstantStringClassReference
1065 int flags;
1066 const char *str;
1067 long length;
1068 };
1069*/
1070
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00001071llvm::Constant *CGObjCCommonMac::GenerateConstantString(
Steve Naroff2c8a08e2009-03-31 16:53:37 +00001072 const ObjCStringLiteral *SL) {
Steve Naroff9a744e52009-04-01 13:55:36 +00001073 return CGM.GetAddrOfConstantCFString(SL->getString());
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001074}
1075
1076/// Generates a message send where the super is the receiver. This is
1077/// a message send to self with special delivery semantics indicating
1078/// which class's method should be called.
Daniel Dunbara04840b2008-08-23 03:46:30 +00001079CodeGen::RValue
1080CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +00001081 QualType ResultType,
1082 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001083 const ObjCInterfaceDecl *Class,
Fariborz Jahanian17636fa2009-02-28 20:07:56 +00001084 bool isCategoryImpl,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001085 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +00001086 bool IsClassMessage,
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +00001087 const CodeGen::CallArgList &CallArgs) {
Daniel Dunbar15245e52008-08-23 04:28:29 +00001088 // Create and init a super structure; this is a (receiver, class)
1089 // pair we will pass to objc_msgSendSuper.
1090 llvm::Value *ObjCSuper =
1091 CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
1092 llvm::Value *ReceiverAsObject =
1093 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
1094 CGF.Builder.CreateStore(ReceiverAsObject,
1095 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar15245e52008-08-23 04:28:29 +00001096
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001097 // If this is a class message the metaclass is passed as the target.
1098 llvm::Value *Target;
1099 if (IsClassMessage) {
Fariborz Jahanian17636fa2009-02-28 20:07:56 +00001100 if (isCategoryImpl) {
1101 // Message sent to 'super' in a class method defined in a category
1102 // implementation requires an odd treatment.
1103 // If we are in a class method, we must retrieve the
1104 // _metaclass_ for the current class, pointed at by
1105 // the class's "isa" pointer. The following assumes that
1106 // isa" is the first ivar in a class (which it must be).
1107 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1108 Target = CGF.Builder.CreateStructGEP(Target, 0);
1109 Target = CGF.Builder.CreateLoad(Target);
1110 }
1111 else {
1112 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
1113 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
1114 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
1115 Target = Super;
1116 }
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001117 } else {
1118 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
1119 }
Daniel Dunbar0ed60b02008-08-30 03:02:31 +00001120 // FIXME: We shouldn't need to do this cast, rectify the ASTContext
1121 // and ObjCTypes types.
1122 const llvm::Type *ClassTy =
1123 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001124 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001125 CGF.Builder.CreateStore(Target,
1126 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
1127
Daniel Dunbardd851282008-08-30 05:35:15 +00001128 return EmitMessageSend(CGF, ResultType, Sel,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +00001129 ObjCSuper, ObjCTypes.SuperPtrCTy,
1130 true, CallArgs);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001131}
Daniel Dunbar87062ff2008-08-23 09:25:55 +00001132
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001133/// Generate code for a message send expression.
Daniel Dunbara04840b2008-08-23 03:46:30 +00001134CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +00001135 QualType ResultType,
1136 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001137 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +00001138 bool IsClassMessage,
1139 const CallArgList &CallArgs) {
Daniel Dunbar87062ff2008-08-23 09:25:55 +00001140 llvm::Value *Arg0 =
1141 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
Daniel Dunbardd851282008-08-30 05:35:15 +00001142 return EmitMessageSend(CGF, ResultType, Sel,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +00001143 Arg0, CGF.getContext().getObjCIdType(),
1144 false, CallArgs);
Daniel Dunbar87062ff2008-08-23 09:25:55 +00001145}
1146
1147CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +00001148 QualType ResultType,
1149 Selector Sel,
Daniel Dunbar87062ff2008-08-23 09:25:55 +00001150 llvm::Value *Arg0,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +00001151 QualType Arg0Ty,
1152 bool IsSuper,
1153 const CallArgList &CallArgs) {
1154 CallArgList ActualArgs;
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +00001155 ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
1156 ActualArgs.push_back(std::make_pair(RValue::get(EmitSelector(CGF.Builder,
1157 Sel)),
Daniel Dunbar0ed60b02008-08-30 03:02:31 +00001158 CGF.getContext().getObjCSelType()));
1159 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbarac93e472008-08-15 22:20:32 +00001160
Daniel Dunbar34bda882009-02-02 23:23:47 +00001161 CodeGenTypes &Types = CGM.getTypes();
1162 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
1163 const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo, false);
Daniel Dunbaraecef4c2008-10-17 03:24:53 +00001164
1165 llvm::Constant *Fn;
Daniel Dunbar6ee022b2009-02-02 22:03:45 +00001166 if (CGM.ReturnTypeUsesSret(FnInfo)) {
Daniel Dunbaraecef4c2008-10-17 03:24:53 +00001167 Fn = ObjCTypes.getSendStretFn(IsSuper);
1168 } else if (ResultType->isFloatingType()) {
1169 // FIXME: Sadly, this is wrong. This actually depends on the
1170 // architecture. This happens to be right for x86-32 though.
1171 Fn = ObjCTypes.getSendFpretFn(IsSuper);
1172 } else {
1173 Fn = ObjCTypes.getSendFn(IsSuper);
1174 }
Daniel Dunbara9976a22008-09-10 07:00:50 +00001175 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
Daniel Dunbar6ee022b2009-02-02 22:03:45 +00001176 return CGF.EmitCall(FnInfo, Fn, ActualArgs);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001177}
1178
Daniel Dunbard916e6e2008-11-01 01:53:16 +00001179llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar84bb85f2008-08-13 00:59:25 +00001180 const ObjCProtocolDecl *PD) {
Daniel Dunbarb3518152008-09-04 04:33:15 +00001181 // FIXME: I don't understand why gcc generates this, or where it is
1182 // resolved. Investigate. Its also wasteful to look this up over and
1183 // over.
1184 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1185
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001186 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
1187 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001188}
1189
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00001190void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001191 // FIXME: We shouldn't need this, the protocol decl should contain
1192 // enough information to tell us whether this was a declaration or a
1193 // definition.
1194 DefinedProtocols.insert(PD->getIdentifier());
1195
1196 // If we have generated a forward reference to this protocol, emit
1197 // it now. Otherwise do nothing, the protocol objects are lazily
1198 // emitted.
1199 if (Protocols.count(PD->getIdentifier()))
1200 GetOrEmitProtocol(PD);
1201}
1202
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00001203llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001204 if (DefinedProtocols.count(PD->getIdentifier()))
1205 return GetOrEmitProtocol(PD);
1206 return GetOrEmitProtocolRef(PD);
1207}
1208
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001209/*
1210 // APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1211 struct _objc_protocol {
1212 struct _objc_protocol_extension *isa;
1213 char *protocol_name;
1214 struct _objc_protocol_list *protocol_list;
1215 struct _objc__method_prototype_list *instance_methods;
1216 struct _objc__method_prototype_list *class_methods
1217 };
1218
1219 See EmitProtocolExtension().
1220*/
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001221llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1222 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1223
1224 // Early exit if a defining object has already been generated.
1225 if (Entry && Entry->hasInitializer())
1226 return Entry;
1227
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001228 // FIXME: I don't understand why gcc generates this, or where it is
1229 // resolved. Investigate. Its also wasteful to look this up over and
1230 // over.
1231 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1232
Chris Lattnerd120b9e2008-11-24 03:54:41 +00001233 const char *ProtocolName = PD->getNameAsCString();
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001234
1235 // Construct method lists.
1236 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1237 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Douglas Gregorc55b0b02009-04-09 21:40:53 +00001238 for (ObjCProtocolDecl::instmeth_iterator
1239 i = PD->instmeth_begin(CGM.getContext()),
1240 e = PD->instmeth_end(CGM.getContext()); i != e; ++i) {
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001241 ObjCMethodDecl *MD = *i;
1242 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1243 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1244 OptInstanceMethods.push_back(C);
1245 } else {
1246 InstanceMethods.push_back(C);
1247 }
1248 }
1249
Douglas Gregorc55b0b02009-04-09 21:40:53 +00001250 for (ObjCProtocolDecl::classmeth_iterator
1251 i = PD->classmeth_begin(CGM.getContext()),
1252 e = PD->classmeth_end(CGM.getContext()); i != e; ++i) {
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001253 ObjCMethodDecl *MD = *i;
1254 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1255 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1256 OptClassMethods.push_back(C);
1257 } else {
1258 ClassMethods.push_back(C);
1259 }
1260 }
1261
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001262 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001263 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001264 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001265 Values[2] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001266 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getNameAsString(),
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001267 PD->protocol_begin(),
1268 PD->protocol_end());
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001269 Values[3] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001270 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_"
1271 + PD->getNameAsString(),
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001272 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1273 InstanceMethods);
1274 Values[4] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001275 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_"
1276 + PD->getNameAsString(),
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001277 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1278 ClassMethods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001279 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
1280 Values);
1281
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001282 if (Entry) {
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001283 // Already created, fix the linkage and update the initializer.
1284 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001285 Entry->setInitializer(Init);
1286 } else {
1287 Entry =
1288 new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false,
1289 llvm::GlobalValue::InternalLinkage,
1290 Init,
1291 std::string("\01L_OBJC_PROTOCOL_")+ProtocolName,
1292 &CGM.getModule());
1293 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar56756c32009-03-09 22:18:41 +00001294 Entry->setAlignment(4);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001295 UsedGlobals.push_back(Entry);
1296 // FIXME: Is this necessary? Why only for protocol?
1297 Entry->setAlignment(4);
1298 }
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001299
1300 return Entry;
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001301}
1302
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001303llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001304 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1305
1306 if (!Entry) {
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001307 // We use the initializer as a marker of whether this is a forward
1308 // reference or not. At module finalization we add the empty
1309 // contents for protocols which were referenced but never defined.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001310 Entry =
1311 new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false,
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001312 llvm::GlobalValue::ExternalLinkage,
1313 0,
Chris Lattner271d4c22008-11-24 05:29:24 +00001314 "\01L_OBJC_PROTOCOL_" + PD->getNameAsString(),
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001315 &CGM.getModule());
1316 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
Daniel Dunbar56756c32009-03-09 22:18:41 +00001317 Entry->setAlignment(4);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001318 UsedGlobals.push_back(Entry);
1319 // FIXME: Is this necessary? Why only for protocol?
1320 Entry->setAlignment(4);
1321 }
1322
1323 return Entry;
1324}
1325
1326/*
1327 struct _objc_protocol_extension {
1328 uint32_t size;
1329 struct objc_method_description_list *optional_instance_methods;
1330 struct objc_method_description_list *optional_class_methods;
1331 struct objc_property_list *instance_properties;
1332 };
1333*/
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001334llvm::Constant *
1335CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1336 const ConstantVector &OptInstanceMethods,
1337 const ConstantVector &OptClassMethods) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001338 uint64_t Size =
Daniel Dunbard8439f22009-01-12 21:08:18 +00001339 CGM.getTargetData().getTypePaddedSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001340 std::vector<llvm::Constant*> Values(4);
1341 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001342 Values[1] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001343 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
1344 + PD->getNameAsString(),
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001345 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1346 OptInstanceMethods);
1347 Values[2] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001348 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_"
1349 + PD->getNameAsString(),
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001350 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1351 OptClassMethods);
Chris Lattner271d4c22008-11-24 05:29:24 +00001352 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" +
1353 PD->getNameAsString(),
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00001354 0, PD, ObjCTypes);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001355
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001356 // Return null if no extension bits are used.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001357 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
1358 Values[3]->isNullValue())
1359 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
1360
1361 llvm::Constant *Init =
1362 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001363
Daniel Dunbar90d88f92009-03-09 21:49:58 +00001364 // No special section, but goes in llvm.used
1365 return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getNameAsString(),
1366 Init,
1367 0, 0, true);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001368}
1369
1370/*
1371 struct objc_protocol_list {
1372 struct objc_protocol_list *next;
1373 long count;
1374 Protocol *list[];
1375 };
1376*/
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001377llvm::Constant *
1378CGObjCMac::EmitProtocolList(const std::string &Name,
1379 ObjCProtocolDecl::protocol_iterator begin,
1380 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001381 std::vector<llvm::Constant*> ProtocolRefs;
1382
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001383 for (; begin != end; ++begin)
1384 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001385
1386 // Just return null for empty protocol lists
1387 if (ProtocolRefs.empty())
1388 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1389
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001390 // This list is null terminated.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001391 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
1392
1393 std::vector<llvm::Constant*> Values(3);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001394 // This field is only used by the runtime.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001395 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1396 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
1397 Values[2] =
1398 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1399 ProtocolRefs.size()),
1400 ProtocolRefs);
1401
1402 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1403 llvm::GlobalVariable *GV =
Daniel Dunbar90d88f92009-03-09 21:49:58 +00001404 CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar56756c32009-03-09 22:18:41 +00001405 4, false);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001406 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
1407}
1408
1409/*
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001410 struct _objc_property {
1411 const char * const name;
1412 const char * const attributes;
1413 };
1414
1415 struct _objc_property_list {
1416 uint32_t entsize; // sizeof (struct _objc_property)
1417 uint32_t prop_count;
1418 struct _objc_property[prop_count];
1419 };
1420*/
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00001421llvm::Constant *CGObjCCommonMac::EmitPropertyList(const std::string &Name,
1422 const Decl *Container,
1423 const ObjCContainerDecl *OCD,
1424 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001425 std::vector<llvm::Constant*> Properties, Prop(2);
Douglas Gregorc55b0b02009-04-09 21:40:53 +00001426 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(CGM.getContext()),
1427 E = OCD->prop_end(CGM.getContext()); I != E; ++I) {
Steve Naroffdcf1e842009-01-11 12:47:58 +00001428 const ObjCPropertyDecl *PD = *I;
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001429 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbar698d6f32008-08-28 04:38:10 +00001430 Prop[1] = GetPropertyTypeString(PD, Container);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001431 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
1432 Prop));
1433 }
1434
1435 // Return null for empty list.
1436 if (Properties.empty())
1437 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1438
1439 unsigned PropertySize =
Daniel Dunbard8439f22009-01-12 21:08:18 +00001440 CGM.getTargetData().getTypePaddedSize(ObjCTypes.PropertyTy);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001441 std::vector<llvm::Constant*> Values(3);
1442 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
1443 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
1444 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
1445 Properties.size());
1446 Values[2] = llvm::ConstantArray::get(AT, Properties);
1447 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1448
Daniel Dunbar90d88f92009-03-09 21:49:58 +00001449 llvm::GlobalVariable *GV =
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00001450 CreateMetadataVar(Name, Init,
1451 (ObjCABI == 2) ? "__DATA, __objc_const" :
1452 "__OBJC,__property,regular,no_dead_strip",
1453 (ObjCABI == 2) ? 8 : 4,
1454 true);
Daniel Dunbar90d88f92009-03-09 21:49:58 +00001455 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001456}
1457
1458/*
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001459 struct objc_method_description_list {
1460 int count;
1461 struct objc_method_description list[];
1462 };
1463*/
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001464llvm::Constant *
1465CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
1466 std::vector<llvm::Constant*> Desc(2);
1467 Desc[0] = llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1468 ObjCTypes.SelectorPtrTy);
1469 Desc[1] = GetMethodVarType(MD);
1470 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
1471 Desc);
1472}
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001473
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001474llvm::Constant *CGObjCMac::EmitMethodDescList(const std::string &Name,
1475 const char *Section,
1476 const ConstantVector &Methods) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001477 // Return null for empty list.
1478 if (Methods.empty())
1479 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
1480
1481 std::vector<llvm::Constant*> Values(2);
1482 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
1483 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
1484 Methods.size());
1485 Values[1] = llvm::ConstantArray::get(AT, Methods);
1486 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1487
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00001488 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001489 return llvm::ConstantExpr::getBitCast(GV,
1490 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001491}
1492
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001493/*
1494 struct _objc_category {
1495 char *category_name;
1496 char *class_name;
1497 struct _objc_method_list *instance_methods;
1498 struct _objc_method_list *class_methods;
1499 struct _objc_protocol_list *protocols;
1500 uint32_t size; // <rdar://4585769>
1501 struct _objc_property_list *instance_properties;
1502 };
1503 */
Daniel Dunbarac93e472008-08-15 22:20:32 +00001504void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Daniel Dunbard8439f22009-01-12 21:08:18 +00001505 unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.CategoryTy);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001506
Daniel Dunbar0cd49032008-08-26 23:03:11 +00001507 // FIXME: This is poor design, the OCD should have a pointer to the
1508 // category decl. Additionally, note that Category can be null for
1509 // the @implementation w/o an @interface case. Sema should just
1510 // create one for us as it does for @implementation so everyone else
1511 // can live life under a clear blue sky.
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001512 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar0cd49032008-08-26 23:03:11 +00001513 const ObjCCategoryDecl *Category =
1514 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Chris Lattner271d4c22008-11-24 05:29:24 +00001515 std::string ExtName(Interface->getNameAsString() + "_" +
1516 OCD->getNameAsString());
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001517
Daniel Dunbar12996f52008-08-26 21:51:14 +00001518 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1519 for (ObjCCategoryImplDecl::instmeth_iterator i = OCD->instmeth_begin(),
1520 e = OCD->instmeth_end(); i != e; ++i) {
1521 // Instance methods should always be defined.
1522 InstanceMethods.push_back(GetMethodConstant(*i));
1523 }
1524 for (ObjCCategoryImplDecl::classmeth_iterator i = OCD->classmeth_begin(),
1525 e = OCD->classmeth_end(); i != e; ++i) {
1526 // Class methods should always be defined.
1527 ClassMethods.push_back(GetMethodConstant(*i));
1528 }
1529
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001530 std::vector<llvm::Constant*> Values(7);
1531 Values[0] = GetClassName(OCD->getIdentifier());
1532 Values[1] = GetClassName(Interface->getIdentifier());
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001533 Values[2] =
1534 EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") +
1535 ExtName,
1536 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +00001537 InstanceMethods);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001538 Values[3] =
1539 EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName,
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00001540 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +00001541 ClassMethods);
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001542 if (Category) {
1543 Values[4] =
1544 EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName,
1545 Category->protocol_begin(),
1546 Category->protocol_end());
1547 } else {
1548 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1549 }
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001550 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar0cd49032008-08-26 23:03:11 +00001551
1552 // If there is no category @interface then there can be no properties.
1553 if (Category) {
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00001554 Values[6] = EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_") + ExtName,
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00001555 OCD, Category, ObjCTypes);
Daniel Dunbar0cd49032008-08-26 23:03:11 +00001556 } else {
1557 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1558 }
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001559
1560 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
1561 Values);
1562
1563 llvm::GlobalVariable *GV =
Daniel Dunbar90d88f92009-03-09 21:49:58 +00001564 CreateMetadataVar(std::string("\01L_OBJC_CATEGORY_")+ExtName, Init,
1565 "__OBJC,__category,regular,no_dead_strip",
Daniel Dunbar56756c32009-03-09 22:18:41 +00001566 4, true);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001567 DefinedCategories.push_back(GV);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001568}
1569
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001570// FIXME: Get from somewhere?
1571enum ClassFlags {
1572 eClassFlags_Factory = 0x00001,
1573 eClassFlags_Meta = 0x00002,
1574 // <rdr://5142207>
1575 eClassFlags_HasCXXStructors = 0x02000,
1576 eClassFlags_Hidden = 0x20000,
1577 eClassFlags_ABI2_Hidden = 0x00010,
1578 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
1579};
1580
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001581/*
1582 struct _objc_class {
1583 Class isa;
1584 Class super_class;
1585 const char *name;
1586 long version;
1587 long info;
1588 long instance_size;
1589 struct _objc_ivar_list *ivars;
1590 struct _objc_method_list *methods;
1591 struct _objc_cache *cache;
1592 struct _objc_protocol_list *protocols;
1593 // Objective-C 1.0 extensions (<rdr://4585769>)
1594 const char *ivar_layout;
1595 struct _objc_class_ext *ext;
1596 };
1597
1598 See EmitClassExtension();
1599 */
1600void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001601 DefinedSymbols.insert(ID->getIdentifier());
1602
Chris Lattnerd120b9e2008-11-24 03:54:41 +00001603 std::string ClassName = ID->getNameAsString();
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001604 // FIXME: Gross
1605 ObjCInterfaceDecl *Interface =
1606 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001607 llvm::Constant *Protocols =
Chris Lattner271d4c22008-11-24 05:29:24 +00001608 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getNameAsString(),
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001609 Interface->protocol_begin(),
1610 Interface->protocol_end());
Chris Lattner9fe470d2009-04-19 06:02:28 +00001611 const llvm::Type *InterfaceTy;
1612 if (Interface->isForwardDecl())
1613 InterfaceTy = llvm::StructType::get(NULL, NULL);
1614 else
1615 InterfaceTy =
Chris Lattner46ee0f32009-04-01 06:23:52 +00001616 CGM.getTypes().ConvertType(CGM.getContext().getObjCInterfaceType(Interface));
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001617 unsigned Flags = eClassFlags_Factory;
Daniel Dunbard8439f22009-01-12 21:08:18 +00001618 unsigned Size = CGM.getTargetData().getTypePaddedSize(InterfaceTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001619
1620 // FIXME: Set CXX-structors flag.
Daniel Dunbar8394fda2009-04-14 06:00:08 +00001621 if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001622 Flags |= eClassFlags_Hidden;
1623
Daniel Dunbar12996f52008-08-26 21:51:14 +00001624 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1625 for (ObjCImplementationDecl::instmeth_iterator i = ID->instmeth_begin(),
1626 e = ID->instmeth_end(); i != e; ++i) {
1627 // Instance methods should always be defined.
1628 InstanceMethods.push_back(GetMethodConstant(*i));
1629 }
1630 for (ObjCImplementationDecl::classmeth_iterator i = ID->classmeth_begin(),
1631 e = ID->classmeth_end(); i != e; ++i) {
1632 // Class methods should always be defined.
1633 ClassMethods.push_back(GetMethodConstant(*i));
1634 }
1635
1636 for (ObjCImplementationDecl::propimpl_iterator i = ID->propimpl_begin(),
1637 e = ID->propimpl_end(); i != e; ++i) {
1638 ObjCPropertyImplDecl *PID = *i;
1639
1640 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
1641 ObjCPropertyDecl *PD = PID->getPropertyDecl();
1642
1643 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
1644 if (llvm::Constant *C = GetMethodConstant(MD))
1645 InstanceMethods.push_back(C);
1646 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
1647 if (llvm::Constant *C = GetMethodConstant(MD))
1648 InstanceMethods.push_back(C);
1649 }
1650 }
1651
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001652 std::vector<llvm::Constant*> Values(12);
Daniel Dunbar12996f52008-08-26 21:51:14 +00001653 Values[ 0] = EmitMetaClass(ID, Protocols, InterfaceTy, ClassMethods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001654 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001655 // Record a reference to the super class.
1656 LazySymbols.insert(Super->getIdentifier());
1657
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001658 Values[ 1] =
1659 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
1660 ObjCTypes.ClassPtrTy);
1661 } else {
1662 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
1663 }
1664 Values[ 2] = GetClassName(ID->getIdentifier());
1665 // Version is always 0.
1666 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
1667 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
1668 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00001669 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001670 Values[ 7] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001671 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getNameAsString(),
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001672 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +00001673 InstanceMethods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001674 // cache is always NULL.
1675 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
1676 Values[ 9] = Protocols;
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001677 // FIXME: Set ivar_layout
Fariborz Jahanian738ee712009-03-25 22:36:49 +00001678 // Values[10] = BuildIvarLayout(ID, true);
1679 Values[10] = GetIvarLayoutName(0, ObjCTypes);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001680 Values[11] = EmitClassExtension(ID);
1681 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
1682 Values);
1683
1684 llvm::GlobalVariable *GV =
Daniel Dunbar90d88f92009-03-09 21:49:58 +00001685 CreateMetadataVar(std::string("\01L_OBJC_CLASS_")+ClassName, Init,
1686 "__OBJC,__class,regular,no_dead_strip",
Daniel Dunbar56756c32009-03-09 22:18:41 +00001687 4, true);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001688 DefinedClasses.push_back(GV);
1689}
1690
1691llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
1692 llvm::Constant *Protocols,
Daniel Dunbar12996f52008-08-26 21:51:14 +00001693 const llvm::Type *InterfaceTy,
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001694 const ConstantVector &Methods) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001695 unsigned Flags = eClassFlags_Meta;
Daniel Dunbard8439f22009-01-12 21:08:18 +00001696 unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.ClassTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001697
Daniel Dunbar8394fda2009-04-14 06:00:08 +00001698 if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001699 Flags |= eClassFlags_Hidden;
1700
1701 std::vector<llvm::Constant*> Values(12);
1702 // The isa for the metaclass is the root of the hierarchy.
1703 const ObjCInterfaceDecl *Root = ID->getClassInterface();
1704 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
1705 Root = Super;
1706 Values[ 0] =
1707 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
1708 ObjCTypes.ClassPtrTy);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001709 // The super class for the metaclass is emitted as the name of the
1710 // super class. The runtime fixes this up to point to the
1711 // *metaclass* for the super class.
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001712 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
1713 Values[ 1] =
1714 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
1715 ObjCTypes.ClassPtrTy);
1716 } else {
1717 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
1718 }
1719 Values[ 2] = GetClassName(ID->getIdentifier());
1720 // Version is always 0.
1721 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
1722 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
1723 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00001724 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001725 Values[ 7] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001726 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00001727 "__OBJC,__cls_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +00001728 Methods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001729 // cache is always NULL.
1730 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
1731 Values[ 9] = Protocols;
1732 // ivar_layout for metaclass is always NULL.
1733 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
1734 // The class extension is always unused for metaclasses.
1735 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
1736 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
1737 Values);
1738
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001739 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattnerd120b9e2008-11-24 03:54:41 +00001740 Name += ID->getNameAsCString();
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001741
1742 // Check for a forward reference.
1743 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
1744 if (GV) {
1745 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
1746 "Forward metaclass reference has incorrect type.");
1747 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
1748 GV->setInitializer(Init);
1749 } else {
1750 GV = new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1751 llvm::GlobalValue::InternalLinkage,
1752 Init, Name,
1753 &CGM.getModule());
1754 }
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001755 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
Daniel Dunbar56756c32009-03-09 22:18:41 +00001756 GV->setAlignment(4);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001757 UsedGlobals.push_back(GV);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001758
1759 return GV;
1760}
1761
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001762llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattner271d4c22008-11-24 05:29:24 +00001763 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001764
1765 // FIXME: Should we look these up somewhere other than the
1766 // module. Its a bit silly since we only generate these while
1767 // processing an implementation, so exactly one pointer would work
1768 // if know when we entered/exitted an implementation block.
1769
1770 // Check for an existing forward reference.
Fariborz Jahanian5fe09f72009-01-07 20:11:22 +00001771 // Previously, metaclass with internal linkage may have been defined.
1772 // pass 'true' as 2nd argument so it is returned.
1773 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true)) {
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001774 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
1775 "Forward metaclass reference has incorrect type.");
1776 return GV;
1777 } else {
1778 // Generate as an external reference to keep a consistent
1779 // module. This will be patched up when we emit the metaclass.
1780 return new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1781 llvm::GlobalValue::ExternalLinkage,
1782 0,
1783 Name,
1784 &CGM.getModule());
1785 }
1786}
1787
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001788/*
1789 struct objc_class_ext {
1790 uint32_t size;
1791 const char *weak_ivar_layout;
1792 struct _objc_property_list *properties;
1793 };
1794*/
1795llvm::Constant *
1796CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
1797 uint64_t Size =
Daniel Dunbard8439f22009-01-12 21:08:18 +00001798 CGM.getTargetData().getTypePaddedSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001799
1800 std::vector<llvm::Constant*> Values(3);
1801 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001802 // FIXME: Output weak_ivar_layout string.
Fariborz Jahanian738ee712009-03-25 22:36:49 +00001803 // Values[1] = BuildIvarLayout(ID, false);
Fariborz Jahanian7345eba2009-03-05 19:17:31 +00001804 Values[1] = GetIvarLayoutName(0, ObjCTypes);
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00001805 Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00001806 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001807
1808 // Return null if no extension bits are used.
1809 if (Values[1]->isNullValue() && Values[2]->isNullValue())
1810 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
1811
1812 llvm::Constant *Init =
1813 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
Daniel Dunbar90d88f92009-03-09 21:49:58 +00001814 return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getNameAsString(),
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00001815 Init, "__OBJC,__class_ext,regular,no_dead_strip",
1816 4, true);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001817}
1818
Fariborz Jahaniana09a5142009-02-12 18:51:23 +00001819/// getInterfaceDeclForIvar - Get the interface declaration node where
1820/// this ivar is declared in.
1821/// FIXME. Ideally, this info should be in the ivar node. But currently
1822/// it is not and prevailing wisdom is that ASTs should not have more
1823/// info than is absolutely needed, even though this info reflects the
1824/// source language.
1825///
1826static const ObjCInterfaceDecl *getInterfaceDeclForIvar(
1827 const ObjCInterfaceDecl *OI,
Douglas Gregorc55b0b02009-04-09 21:40:53 +00001828 const ObjCIvarDecl *IVD,
1829 ASTContext &Context) {
Fariborz Jahaniana09a5142009-02-12 18:51:23 +00001830 if (!OI)
1831 return 0;
1832 assert(isa<ObjCInterfaceDecl>(OI) && "OI is not an interface");
1833 for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
1834 E = OI->ivar_end(); I != E; ++I)
1835 if ((*I)->getIdentifier() == IVD->getIdentifier())
1836 return OI;
Fariborz Jahanian13c22d72009-03-31 17:00:52 +00001837 // look into properties.
Douglas Gregorc55b0b02009-04-09 21:40:53 +00001838 for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(Context),
1839 E = OI->prop_end(Context); I != E; ++I) {
Fariborz Jahanian13c22d72009-03-31 17:00:52 +00001840 ObjCPropertyDecl *PDecl = (*I);
1841 if (ObjCIvarDecl *IV = PDecl->getPropertyIvarDecl())
1842 if (IV->getIdentifier() == IVD->getIdentifier())
1843 return OI;
1844 }
Douglas Gregorc55b0b02009-04-09 21:40:53 +00001845 return getInterfaceDeclForIvar(OI->getSuperClass(), IVD, Context);
Fariborz Jahaniana09a5142009-02-12 18:51:23 +00001846}
1847
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001848/*
1849 struct objc_ivar {
1850 char *ivar_name;
1851 char *ivar_type;
1852 int ivar_offset;
1853 };
1854
1855 struct objc_ivar_list {
1856 int ivar_count;
1857 struct objc_ivar list[count];
1858 };
1859 */
1860llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00001861 bool ForClass) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001862 std::vector<llvm::Constant*> Ivars, Ivar(3);
1863
1864 // When emitting the root class GCC emits ivar entries for the
1865 // actual class structure. It is not clear if we need to follow this
1866 // behavior; for now lets try and get away with not doing it. If so,
1867 // the cleanest solution would be to make up an ObjCInterfaceDecl
1868 // for the class.
1869 if (ForClass)
1870 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00001871
1872 ObjCInterfaceDecl *OID =
1873 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Fariborz Jahanian6d49ab62009-03-11 21:42:00 +00001874 const llvm::StructLayout *Layout = GetInterfaceDeclStructLayout(OID);
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00001875
Daniel Dunbar356f0742009-04-20 06:54:31 +00001876 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
1877 GetNamedIvarList(OID, OIvars);
1878
1879 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
1880 ObjCIvarDecl *IVD = OIvars[i];
1881 const FieldDecl *Field = OID->lookupFieldDeclForIvar(CGM.getContext(), IVD);
Daniel Dunbar356f0742009-04-20 06:54:31 +00001882 Ivar[0] = GetMethodVarName(Field->getIdentifier());
Devang Patel593a07a2009-03-04 18:21:39 +00001883 Ivar[1] = GetMethodVarType(Field);
Daniel Dunbar72878722009-04-20 20:18:54 +00001884 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
1885 GetIvarBaseOffset(Layout, Field));
Daniel Dunbarc9197cd2008-10-17 20:21:44 +00001886 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001887 }
1888
1889 // Return null for empty list.
1890 if (Ivars.empty())
1891 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
1892
1893 std::vector<llvm::Constant*> Values(2);
1894 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
1895 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
1896 Ivars.size());
1897 Values[1] = llvm::ConstantArray::get(AT, Ivars);
1898 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1899
Daniel Dunbar90d88f92009-03-09 21:49:58 +00001900 llvm::GlobalVariable *GV;
1901 if (ForClass)
1902 GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getNameAsString(),
Daniel Dunbar56756c32009-03-09 22:18:41 +00001903 Init, "__OBJC,__class_vars,regular,no_dead_strip",
1904 4, true);
Daniel Dunbar90d88f92009-03-09 21:49:58 +00001905 else
1906 GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_"
1907 + ID->getNameAsString(),
1908 Init, "__OBJC,__instance_vars,regular,no_dead_strip",
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00001909 4, true);
1910 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001911}
1912
1913/*
1914 struct objc_method {
1915 SEL method_name;
1916 char *method_types;
1917 void *method;
1918 };
1919
1920 struct objc_method_list {
1921 struct objc_method_list *obsolete;
1922 int count;
1923 struct objc_method methods_list[count];
1924 };
1925*/
Daniel Dunbar12996f52008-08-26 21:51:14 +00001926
1927/// GetMethodConstant - Return a struct objc_method constant for the
1928/// given method if it has been defined. The result is null if the
1929/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001930llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Daniel Dunbar12996f52008-08-26 21:51:14 +00001931 // FIXME: Use DenseMap::lookup
1932 llvm::Function *Fn = MethodDefinitions[MD];
1933 if (!Fn)
1934 return 0;
1935
1936 std::vector<llvm::Constant*> Method(3);
1937 Method[0] =
1938 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1939 ObjCTypes.SelectorPtrTy);
1940 Method[1] = GetMethodVarType(MD);
1941 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
1942 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
1943}
1944
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001945llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
1946 const char *Section,
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001947 const ConstantVector &Methods) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001948 // Return null for empty list.
1949 if (Methods.empty())
1950 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
1951
1952 std::vector<llvm::Constant*> Values(3);
1953 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
1954 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
1955 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
1956 Methods.size());
1957 Values[2] = llvm::ConstantArray::get(AT, Methods);
1958 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1959
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00001960 llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001961 return llvm::ConstantExpr::getBitCast(GV,
1962 ObjCTypes.MethodListPtrTy);
Daniel Dunbarace33292008-08-16 03:19:19 +00001963}
1964
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00001965llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar9fc15a82009-02-02 21:43:58 +00001966 const ObjCContainerDecl *CD) {
Daniel Dunbarace33292008-08-16 03:19:19 +00001967 std::string Name;
Fariborz Jahanian0adaa8a2009-01-10 21:06:09 +00001968 GetNameForMethod(OMD, CD, Name);
Daniel Dunbarace33292008-08-16 03:19:19 +00001969
Daniel Dunbar34bda882009-02-02 23:23:47 +00001970 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar3ad1f072008-09-10 04:01:49 +00001971 const llvm::FunctionType *MethodTy =
Daniel Dunbar34bda882009-02-02 23:23:47 +00001972 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbarace33292008-08-16 03:19:19 +00001973 llvm::Function *Method =
Daniel Dunbar3ad1f072008-09-10 04:01:49 +00001974 llvm::Function::Create(MethodTy,
Daniel Dunbarace33292008-08-16 03:19:19 +00001975 llvm::GlobalValue::InternalLinkage,
1976 Name,
1977 &CGM.getModule());
Daniel Dunbar12996f52008-08-26 21:51:14 +00001978 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarace33292008-08-16 03:19:19 +00001979
Daniel Dunbarace33292008-08-16 03:19:19 +00001980 return Method;
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001981}
1982
Fariborz Jahaniand65949b2009-03-08 20:18:37 +00001983uint64_t CGObjCCommonMac::GetIvarBaseOffset(const llvm::StructLayout *Layout,
Chris Lattnerd391dab2009-03-31 08:33:16 +00001984 const FieldDecl *Field) {
Fariborz Jahanian40a94a92009-03-09 20:44:22 +00001985 if (!Field->isBitField())
Daniel Dunbar1cfb5192009-04-19 02:03:42 +00001986 return Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
1987
Fariborz Jahanian40a94a92009-03-09 20:44:22 +00001988 // FIXME. Must be a better way of getting a bitfield base offset.
Daniel Dunbar1cfb5192009-04-19 02:03:42 +00001989 CodeGenTypes::BitFieldInfo BFI = CGM.getTypes().getBitFieldInfo(Field);
1990 // FIXME: The "field no" for bitfields is something completely
1991 // different; it is the offset in multiples of the base type size!
1992 uint64_t Offset = CGM.getTypes().getLLVMFieldNo(Field);
1993 const llvm::Type *Ty =
1994 CGM.getTypes().ConvertTypeForMemRecursive(Field->getType());
1995 Offset *= CGM.getTypes().getTargetData().getTypePaddedSizeInBits(Ty);
1996 return (Offset + BFI.Begin) / 8;
Fariborz Jahaniand65949b2009-03-08 20:18:37 +00001997}
1998
Daniel Dunbar1cfb5192009-04-19 02:03:42 +00001999/// GetFieldBaseOffset - return the field's byte offset.
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002000uint64_t CGObjCCommonMac::GetFieldBaseOffset(const ObjCInterfaceDecl *OI,
2001 const llvm::StructLayout *Layout,
Chris Lattnerd391dab2009-03-31 08:33:16 +00002002 const FieldDecl *Field) {
Fariborz Jahanian31614742009-04-20 22:03:45 +00002003 // Is this a c struct?
2004 if (!OI)
2005 return Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(Field));
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002006 const ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field);
Chris Lattnerd391dab2009-03-31 08:33:16 +00002007 const FieldDecl *FD = OI->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
2008 return GetIvarBaseOffset(Layout, FD);
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002009}
2010
Daniel Dunbarc4594f22009-03-09 20:09:19 +00002011llvm::GlobalVariable *
2012CGObjCCommonMac::CreateMetadataVar(const std::string &Name,
2013 llvm::Constant *Init,
2014 const char *Section,
Daniel Dunbareddddd22009-03-09 20:50:13 +00002015 unsigned Align,
2016 bool AddToUsed) {
Daniel Dunbarc4594f22009-03-09 20:09:19 +00002017 const llvm::Type *Ty = Init->getType();
2018 llvm::GlobalVariable *GV =
2019 new llvm::GlobalVariable(Ty, false,
2020 llvm::GlobalValue::InternalLinkage,
2021 Init,
2022 Name,
2023 &CGM.getModule());
2024 if (Section)
2025 GV->setSection(Section);
Daniel Dunbareddddd22009-03-09 20:50:13 +00002026 if (Align)
2027 GV->setAlignment(Align);
2028 if (AddToUsed)
Daniel Dunbarc4594f22009-03-09 20:09:19 +00002029 UsedGlobals.push_back(GV);
2030 return GV;
2031}
2032
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00002033llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002034 // Abuse this interface function as a place to finalize.
2035 FinishModule();
2036
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00002037 return NULL;
2038}
2039
Chris Lattneraea1aee2009-03-22 21:03:39 +00002040llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
Daniel Dunbarf7103722008-09-24 03:38:44 +00002041 return ObjCTypes.GetPropertyFn;
2042}
2043
Chris Lattneraea1aee2009-03-22 21:03:39 +00002044llvm::Constant *CGObjCMac::GetPropertySetFunction() {
Daniel Dunbarf7103722008-09-24 03:38:44 +00002045 return ObjCTypes.SetPropertyFn;
2046}
2047
Chris Lattneraea1aee2009-03-22 21:03:39 +00002048llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
Anders Carlsson58d16242008-08-31 04:05:03 +00002049 return ObjCTypes.EnumerationMutationFn;
2050}
2051
Daniel Dunbar83544842008-09-28 01:03:14 +00002052/*
2053
2054Objective-C setjmp-longjmp (sjlj) Exception Handling
2055--
2056
2057The basic framework for a @try-catch-finally is as follows:
2058{
2059 objc_exception_data d;
2060 id _rethrow = null;
Anders Carlsson8559de12009-02-07 21:26:04 +00002061 bool _call_try_exit = true;
2062
Daniel Dunbar83544842008-09-28 01:03:14 +00002063 objc_exception_try_enter(&d);
2064 if (!setjmp(d.jmp_buf)) {
2065 ... try body ...
2066 } else {
2067 // exception path
2068 id _caught = objc_exception_extract(&d);
2069
2070 // enter new try scope for handlers
2071 if (!setjmp(d.jmp_buf)) {
2072 ... match exception and execute catch blocks ...
2073
2074 // fell off end, rethrow.
2075 _rethrow = _caught;
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002076 ... jump-through-finally to finally_rethrow ...
Daniel Dunbar83544842008-09-28 01:03:14 +00002077 } else {
2078 // exception in catch block
2079 _rethrow = objc_exception_extract(&d);
Anders Carlsson8559de12009-02-07 21:26:04 +00002080 _call_try_exit = false;
2081 ... jump-through-finally to finally_rethrow ...
Daniel Dunbar83544842008-09-28 01:03:14 +00002082 }
2083 }
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002084 ... jump-through-finally to finally_end ...
Daniel Dunbar83544842008-09-28 01:03:14 +00002085
2086finally:
Anders Carlsson8559de12009-02-07 21:26:04 +00002087 if (_call_try_exit)
2088 objc_exception_try_exit(&d);
2089
Daniel Dunbar83544842008-09-28 01:03:14 +00002090 ... finally block ....
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002091 ... dispatch to finally destination ...
2092
2093finally_rethrow:
2094 objc_exception_throw(_rethrow);
2095
2096finally_end:
Daniel Dunbar83544842008-09-28 01:03:14 +00002097}
2098
2099This framework differs slightly from the one gcc uses, in that gcc
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002100uses _rethrow to determine if objc_exception_try_exit should be called
2101and if the object should be rethrown. This breaks in the face of
2102throwing nil and introduces unnecessary branches.
Daniel Dunbar83544842008-09-28 01:03:14 +00002103
2104We specialize this framework for a few particular circumstances:
2105
2106 - If there are no catch blocks, then we avoid emitting the second
2107 exception handling context.
2108
2109 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
2110 e)) we avoid emitting the code to rethrow an uncaught exception.
2111
2112 - FIXME: If there is no @finally block we can do a few more
2113 simplifications.
2114
2115Rethrows and Jumps-Through-Finally
2116--
2117
2118Support for implicit rethrows and jumping through the finally block is
2119handled by storing the current exception-handling context in
2120ObjCEHStack.
2121
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002122In order to implement proper @finally semantics, we support one basic
2123mechanism for jumping through the finally block to an arbitrary
2124destination. Constructs which generate exits from a @try or @catch
2125block use this mechanism to implement the proper semantics by chaining
2126jumps, as necessary.
2127
2128This mechanism works like the one used for indirect goto: we
2129arbitrarily assign an ID to each destination and store the ID for the
2130destination in a variable prior to entering the finally block. At the
2131end of the finally block we simply create a switch to the proper
2132destination.
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00002133
2134Code gen for @synchronized(expr) stmt;
2135Effectively generating code for:
2136objc_sync_enter(expr);
2137@try stmt @finally { objc_sync_exit(expr); }
Daniel Dunbar83544842008-09-28 01:03:14 +00002138*/
2139
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00002140void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
2141 const Stmt &S) {
2142 bool isTry = isa<ObjCAtTryStmt>(S);
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002143 // Create various blocks we refer to for handling @finally.
Daniel Dunbar72f96552008-11-11 02:29:29 +00002144 llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
Anders Carlsson8559de12009-02-07 21:26:04 +00002145 llvm::BasicBlock *FinallyExit = CGF.createBasicBlock("finally.exit");
Daniel Dunbar72f96552008-11-11 02:29:29 +00002146 llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit");
2147 llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
2148 llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
Daniel Dunbar34416d62009-02-24 01:43:46 +00002149
2150 // For @synchronized, call objc_sync_enter(sync.expr). The
2151 // evaluation of the expression must occur before we enter the
2152 // @synchronized. We can safely avoid a temp here because jumps into
2153 // @synchronized are illegal & this will dominate uses.
2154 llvm::Value *SyncArg = 0;
2155 if (!isTry) {
2156 SyncArg =
2157 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2158 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
Chris Lattner23e24652009-04-06 16:53:45 +00002159 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg);
Daniel Dunbar34416d62009-02-24 01:43:46 +00002160 }
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002161
2162 // Push an EH context entry, used for handling rethrows and jumps
2163 // through finally.
Anders Carlsson00ffb962009-02-09 20:38:58 +00002164 CGF.PushCleanupBlock(FinallyBlock);
2165
Anders Carlssonecd81832009-02-07 21:37:21 +00002166 CGF.ObjCEHValueStack.push_back(0);
2167
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002168 // Allocate memory for the exception data and rethrow pointer.
Anders Carlssonfca6c292008-09-09 17:59:25 +00002169 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2170 "exceptiondata.ptr");
Daniel Dunbar35b777f2008-10-29 22:36:39 +00002171 llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy,
2172 "_rethrow");
Anders Carlsson8559de12009-02-07 21:26:04 +00002173 llvm::Value *CallTryExitPtr = CGF.CreateTempAlloca(llvm::Type::Int1Ty,
2174 "_call_try_exit");
2175 CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(), CallTryExitPtr);
2176
Anders Carlssonfca6c292008-09-09 17:59:25 +00002177 // Enter a new try block and call setjmp.
Chris Lattnere05d4cb2009-04-22 02:26:14 +00002178 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002179 llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0,
2180 "jmpbufarray");
2181 JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp");
Chris Lattnere05d4cb2009-04-22 02:26:14 +00002182 llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(),
Anders Carlssonfca6c292008-09-09 17:59:25 +00002183 JmpBufPtr, "result");
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002184
Daniel Dunbar72f96552008-11-11 02:29:29 +00002185 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2186 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
Daniel Dunbarbe56f012008-10-02 17:05:36 +00002187 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"),
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002188 TryHandler, TryBlock);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002189
2190 // Emit the @try block.
2191 CGF.EmitBlock(TryBlock);
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00002192 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
2193 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
Anders Carlsson00ffb962009-02-09 20:38:58 +00002194 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002195
2196 // Emit the "exception in @try" block.
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002197 CGF.EmitBlock(TryHandler);
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002198
2199 // Retrieve the exception object. We may emit multiple blocks but
2200 // nothing can cross this so the value is already in SSA form.
Chris Lattnere05d4cb2009-04-22 02:26:14 +00002201 llvm::Value *Caught =
2202 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2203 ExceptionData, "caught");
Anders Carlssonecd81832009-02-07 21:37:21 +00002204 CGF.ObjCEHValueStack.back() = Caught;
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00002205 if (!isTry)
2206 {
2207 CGF.Builder.CreateStore(Caught, RethrowPtr);
Anders Carlsson8559de12009-02-07 21:26:04 +00002208 CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr);
Anders Carlsson00ffb962009-02-09 20:38:58 +00002209 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00002210 }
2211 else if (const ObjCAtCatchStmt* CatchStmt =
2212 cast<ObjCAtTryStmt>(S).getCatchStmts())
2213 {
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002214 // Enter a new exception try block (in case a @catch block throws
2215 // an exception).
Chris Lattnere05d4cb2009-04-22 02:26:14 +00002216 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData);
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002217
Chris Lattnere05d4cb2009-04-22 02:26:14 +00002218 llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(),
Anders Carlssonfca6c292008-09-09 17:59:25 +00002219 JmpBufPtr, "result");
Daniel Dunbarbe56f012008-10-02 17:05:36 +00002220 llvm::Value *Threw = CGF.Builder.CreateIsNotNull(SetJmpResult, "threw");
Anders Carlssonfca6c292008-09-09 17:59:25 +00002221
Daniel Dunbar72f96552008-11-11 02:29:29 +00002222 llvm::BasicBlock *CatchBlock = CGF.createBasicBlock("catch");
2223 llvm::BasicBlock *CatchHandler = CGF.createBasicBlock("catch.handler");
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002224 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002225
2226 CGF.EmitBlock(CatchBlock);
2227
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002228 // Handle catch list. As a special case we check if everything is
2229 // matched and avoid generating code for falling off the end if
2230 // so.
2231 bool AllMatched = false;
Anders Carlssonfca6c292008-09-09 17:59:25 +00002232 for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
Daniel Dunbar72f96552008-11-11 02:29:29 +00002233 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch");
Anders Carlssonfca6c292008-09-09 17:59:25 +00002234
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002235 const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Daniel Dunbar7a68b452008-09-27 07:36:24 +00002236 const PointerType *PT = 0;
2237
Anders Carlssonfca6c292008-09-09 17:59:25 +00002238 // catch(...) always matches.
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002239 if (!CatchParam) {
2240 AllMatched = true;
2241 } else {
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002242 PT = CatchParam->getType()->getAsPointerType();
Anders Carlssonfca6c292008-09-09 17:59:25 +00002243
Daniel Dunbard04c9352008-09-27 22:21:14 +00002244 // catch(id e) always matches.
2245 // FIXME: For the time being we also match id<X>; this should
2246 // be rejected by Sema instead.
Steve Naroff17c03822009-02-12 17:52:19 +00002247 if ((PT && CGF.getContext().isObjCIdStructType(PT->getPointeeType())) ||
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002248 CatchParam->getType()->isObjCQualifiedIdType())
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002249 AllMatched = true;
Anders Carlssonfca6c292008-09-09 17:59:25 +00002250 }
2251
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002252 if (AllMatched) {
Anders Carlsson75d86732008-09-11 09:15:33 +00002253 if (CatchParam) {
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002254 CGF.EmitLocalBlockVarDecl(*CatchParam);
Daniel Dunbar5aa22bc2008-11-11 23:11:34 +00002255 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002256 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson75d86732008-09-11 09:15:33 +00002257 }
Anders Carlsson1f4acc32008-09-11 08:21:54 +00002258
Anders Carlsson75d86732008-09-11 09:15:33 +00002259 CGF.EmitStmt(CatchStmt->getCatchBody());
Anders Carlsson00ffb962009-02-09 20:38:58 +00002260 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002261 break;
2262 }
2263
Daniel Dunbar7a68b452008-09-27 07:36:24 +00002264 assert(PT && "Unexpected non-pointer type in @catch");
2265 QualType T = PT->getPointeeType();
Anders Carlssona4519172008-09-11 06:35:14 +00002266 const ObjCInterfaceType *ObjCType = T->getAsObjCInterfaceType();
Anders Carlssonfca6c292008-09-09 17:59:25 +00002267 assert(ObjCType && "Catch parameter must have Objective-C type!");
2268
2269 // Check if the @catch block matches the exception object.
2270 llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl());
2271
Chris Lattnere05d4cb2009-04-22 02:26:14 +00002272 llvm::Value *Match =
2273 CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
2274 Class, Caught, "match");
Anders Carlssonfca6c292008-09-09 17:59:25 +00002275
Daniel Dunbar72f96552008-11-11 02:29:29 +00002276 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("matched");
Anders Carlssonfca6c292008-09-09 17:59:25 +00002277
Daniel Dunbarbe56f012008-10-02 17:05:36 +00002278 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002279 MatchedBlock, NextCatchBlock);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002280
2281 // Emit the @catch block.
2282 CGF.EmitBlock(MatchedBlock);
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002283 CGF.EmitLocalBlockVarDecl(*CatchParam);
Daniel Dunbar5aa22bc2008-11-11 23:11:34 +00002284 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar83544842008-09-28 01:03:14 +00002285
2286 llvm::Value *Tmp =
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002287 CGF.Builder.CreateBitCast(Caught, CGF.ConvertType(CatchParam->getType()),
Daniel Dunbar83544842008-09-28 01:03:14 +00002288 "tmp");
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002289 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson75d86732008-09-11 09:15:33 +00002290
2291 CGF.EmitStmt(CatchStmt->getCatchBody());
Anders Carlsson00ffb962009-02-09 20:38:58 +00002292 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002293
2294 CGF.EmitBlock(NextCatchBlock);
2295 }
2296
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002297 if (!AllMatched) {
2298 // None of the handlers caught the exception, so store it to be
2299 // rethrown at the end of the @finally block.
2300 CGF.Builder.CreateStore(Caught, RethrowPtr);
Anders Carlsson00ffb962009-02-09 20:38:58 +00002301 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002302 }
2303
2304 // Emit the exception handler for the @catch blocks.
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002305 CGF.EmitBlock(CatchHandler);
Chris Lattnere05d4cb2009-04-22 02:26:14 +00002306 CGF.Builder.CreateStore(
2307 CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
2308 ExceptionData),
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002309 RethrowPtr);
Anders Carlsson8559de12009-02-07 21:26:04 +00002310 CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr);
Anders Carlsson00ffb962009-02-09 20:38:58 +00002311 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002312 } else {
Anders Carlssonfca6c292008-09-09 17:59:25 +00002313 CGF.Builder.CreateStore(Caught, RethrowPtr);
Anders Carlsson8559de12009-02-07 21:26:04 +00002314 CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr);
Anders Carlsson00ffb962009-02-09 20:38:58 +00002315 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002316 }
2317
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002318 // Pop the exception-handling stack entry. It is important to do
2319 // this now, because the code in the @finally block is not in this
2320 // context.
Anders Carlsson00ffb962009-02-09 20:38:58 +00002321 CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
2322
Anders Carlssonecd81832009-02-07 21:37:21 +00002323 CGF.ObjCEHValueStack.pop_back();
2324
Anders Carlssonfca6c292008-09-09 17:59:25 +00002325 // Emit the @finally block.
2326 CGF.EmitBlock(FinallyBlock);
Anders Carlsson8559de12009-02-07 21:26:04 +00002327 llvm::Value* CallTryExit = CGF.Builder.CreateLoad(CallTryExitPtr, "tmp");
2328
2329 CGF.Builder.CreateCondBr(CallTryExit, FinallyExit, FinallyNoExit);
2330
2331 CGF.EmitBlock(FinallyExit);
Chris Lattnere05d4cb2009-04-22 02:26:14 +00002332 CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData);
Daniel Dunbar7a68b452008-09-27 07:36:24 +00002333
2334 CGF.EmitBlock(FinallyNoExit);
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00002335 if (isTry) {
2336 if (const ObjCAtFinallyStmt* FinallyStmt =
2337 cast<ObjCAtTryStmt>(S).getFinallyStmt())
2338 CGF.EmitStmt(FinallyStmt->getFinallyBody());
Daniel Dunbar34416d62009-02-24 01:43:46 +00002339 } else {
2340 // Emit objc_sync_exit(expr); as finally's sole statement for
2341 // @synchronized.
2342 CGF.Builder.CreateCall(ObjCTypes.SyncExitFn, SyncArg);
Fariborz Jahanian3895d922008-11-21 19:21:53 +00002343 }
Anders Carlssonfca6c292008-09-09 17:59:25 +00002344
Anders Carlsson00ffb962009-02-09 20:38:58 +00002345 // Emit the switch block
2346 if (Info.SwitchBlock)
2347 CGF.EmitBlock(Info.SwitchBlock);
2348 if (Info.EndBlock)
2349 CGF.EmitBlock(Info.EndBlock);
2350
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002351 CGF.EmitBlock(FinallyRethrow);
2352 CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn,
2353 CGF.Builder.CreateLoad(RethrowPtr));
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002354 CGF.Builder.CreateUnreachable();
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002355
2356 CGF.EmitBlock(FinallyEnd);
Anders Carlssonb01a2112008-09-09 10:04:29 +00002357}
2358
2359void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002360 const ObjCAtThrowStmt &S) {
Anders Carlsson05d7be72008-09-09 16:16:55 +00002361 llvm::Value *ExceptionAsObject;
2362
2363 if (const Expr *ThrowExpr = S.getThrowExpr()) {
2364 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
2365 ExceptionAsObject =
2366 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
2367 } else {
Anders Carlssonecd81832009-02-07 21:37:21 +00002368 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar83544842008-09-28 01:03:14 +00002369 "Unexpected rethrow outside @catch block.");
Anders Carlssonecd81832009-02-07 21:37:21 +00002370 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlsson05d7be72008-09-09 16:16:55 +00002371 }
2372
2373 CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn, ExceptionAsObject);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002374 CGF.Builder.CreateUnreachable();
Daniel Dunbar5aa22bc2008-11-11 23:11:34 +00002375
2376 // Clear the insertion point to indicate we are in unreachable code.
2377 CGF.Builder.ClearInsertionPoint();
Anders Carlssonb01a2112008-09-09 10:04:29 +00002378}
2379
Fariborz Jahanian252d87f2008-11-18 22:37:34 +00002380/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanian3305ad32008-11-18 21:45:40 +00002381/// object: objc_read_weak (id *src)
2382///
Fariborz Jahanian252d87f2008-11-18 22:37:34 +00002383llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian3305ad32008-11-18 21:45:40 +00002384 llvm::Value *AddrWeakObj)
2385{
Eli Friedmanf8466232009-03-07 03:57:15 +00002386 const llvm::Type* DestTy =
2387 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
Fariborz Jahaniand2f661a2008-11-19 17:34:06 +00002388 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian3305ad32008-11-18 21:45:40 +00002389 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.GcReadWeakFn,
Fariborz Jahanian252d87f2008-11-18 22:37:34 +00002390 AddrWeakObj, "weakread");
Eli Friedmanf8466232009-03-07 03:57:15 +00002391 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian3305ad32008-11-18 21:45:40 +00002392 return read_weak;
2393}
2394
Fariborz Jahanian252d87f2008-11-18 22:37:34 +00002395/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
2396/// objc_assign_weak (id src, id *dst)
2397///
2398void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
2399 llvm::Value *src, llvm::Value *dst)
2400{
Fariborz Jahanianad51ca02009-03-23 19:10:40 +00002401 const llvm::Type * SrcTy = src->getType();
2402 if (!isa<llvm::PointerType>(SrcTy)) {
2403 unsigned Size = CGM.getTargetData().getTypePaddedSize(SrcTy);
2404 assert(Size <= 8 && "does not support size > 8");
2405 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2406 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian664da982009-03-13 00:42:52 +00002407 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2408 }
Fariborz Jahaniand2f661a2008-11-19 17:34:06 +00002409 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2410 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner293c1d32009-04-17 22:12:36 +00002411 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian252d87f2008-11-18 22:37:34 +00002412 src, dst, "weakassign");
2413 return;
2414}
2415
Fariborz Jahanian17958902008-11-19 00:59:10 +00002416/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
2417/// objc_assign_global (id src, id *dst)
2418///
2419void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
2420 llvm::Value *src, llvm::Value *dst)
2421{
Fariborz Jahanianad51ca02009-03-23 19:10:40 +00002422 const llvm::Type * SrcTy = src->getType();
2423 if (!isa<llvm::PointerType>(SrcTy)) {
2424 unsigned Size = CGM.getTargetData().getTypePaddedSize(SrcTy);
2425 assert(Size <= 8 && "does not support size > 8");
2426 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2427 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian664da982009-03-13 00:42:52 +00002428 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2429 }
Fariborz Jahaniand2f661a2008-11-19 17:34:06 +00002430 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2431 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian17958902008-11-19 00:59:10 +00002432 CGF.Builder.CreateCall2(ObjCTypes.GcAssignGlobalFn,
2433 src, dst, "globalassign");
2434 return;
2435}
2436
Fariborz Jahanianf310b592008-11-20 19:23:36 +00002437/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
2438/// objc_assign_ivar (id src, id *dst)
2439///
2440void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
2441 llvm::Value *src, llvm::Value *dst)
2442{
Fariborz Jahanianad51ca02009-03-23 19:10:40 +00002443 const llvm::Type * SrcTy = src->getType();
2444 if (!isa<llvm::PointerType>(SrcTy)) {
2445 unsigned Size = CGM.getTargetData().getTypePaddedSize(SrcTy);
2446 assert(Size <= 8 && "does not support size > 8");
2447 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2448 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian664da982009-03-13 00:42:52 +00002449 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2450 }
Fariborz Jahanianf310b592008-11-20 19:23:36 +00002451 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2452 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2453 CGF.Builder.CreateCall2(ObjCTypes.GcAssignIvarFn,
2454 src, dst, "assignivar");
2455 return;
2456}
2457
Fariborz Jahanian17958902008-11-19 00:59:10 +00002458/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
2459/// objc_assign_strongCast (id src, id *dst)
2460///
2461void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
2462 llvm::Value *src, llvm::Value *dst)
2463{
Fariborz Jahanianad51ca02009-03-23 19:10:40 +00002464 const llvm::Type * SrcTy = src->getType();
2465 if (!isa<llvm::PointerType>(SrcTy)) {
2466 unsigned Size = CGM.getTargetData().getTypePaddedSize(SrcTy);
2467 assert(Size <= 8 && "does not support size > 8");
2468 src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
2469 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
Fariborz Jahanian664da982009-03-13 00:42:52 +00002470 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
2471 }
Fariborz Jahaniand2f661a2008-11-19 17:34:06 +00002472 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2473 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian17958902008-11-19 00:59:10 +00002474 CGF.Builder.CreateCall2(ObjCTypes.GcAssignStrongCastFn,
2475 src, dst, "weakassign");
2476 return;
2477}
2478
Fariborz Jahanian4337afe2009-02-02 20:02:29 +00002479/// EmitObjCValueForIvar - Code Gen for ivar reference.
2480///
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00002481LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
2482 QualType ObjectTy,
2483 llvm::Value *BaseValue,
2484 const ObjCIvarDecl *Ivar,
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00002485 unsigned CVRQualifiers) {
Daniel Dunbarf5254bd2009-04-21 01:19:28 +00002486 const ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl();
2487 const FieldDecl *Field = ID->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00002488 if (Ivar->isBitField())
2489 return CGF.EmitLValueForBitfield(BaseValue, const_cast<FieldDecl *>(Field),
2490 CVRQualifiers);
Fariborz Jahanian4337afe2009-02-02 20:02:29 +00002491 // TODO: Add a special case for isa (index 0)
2492 unsigned Index = CGM.getTypes().getLLVMFieldNo(Field);
2493 llvm::Value *V = CGF.Builder.CreateStructGEP(BaseValue, Index, "tmp");
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00002494 LValue LV = LValue::MakeAddr(V,
Fariborz Jahanianbbd4ca92009-02-19 23:36:06 +00002495 Ivar->getType().getCVRQualifiers()|CVRQualifiers,
2496 CGM.getContext().getObjCGCAttrKind(Ivar->getType()));
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00002497 LValue::SetObjCIvar(LV, true);
2498 return LV;
Fariborz Jahanian4337afe2009-02-02 20:02:29 +00002499}
2500
Fariborz Jahanian27cc6662009-02-10 19:02:04 +00002501llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
2502 ObjCInterfaceDecl *Interface,
2503 const ObjCIvarDecl *Ivar) {
Fariborz Jahanian6d49ab62009-03-11 21:42:00 +00002504 const llvm::StructLayout *Layout = GetInterfaceDeclStructLayout(Interface);
Daniel Dunbarf0587c62009-04-20 00:37:55 +00002505 const FieldDecl *Field =
2506 Interface->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
Fariborz Jahaniand65949b2009-03-08 20:18:37 +00002507 uint64_t Offset = GetIvarBaseOffset(Layout, Field);
Fariborz Jahanian27cc6662009-02-10 19:02:04 +00002508 return llvm::ConstantInt::get(
2509 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
2510 Offset);
2511}
2512
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002513/* *** Private Interface *** */
2514
2515/// EmitImageInfo - Emit the image info marker used to encode some module
2516/// level information.
2517///
2518/// See: <rdr://4810609&4810587&4810587>
2519/// struct IMAGE_INFO {
2520/// unsigned version;
2521/// unsigned flags;
2522/// };
2523enum ImageInfoFlags {
Daniel Dunbarb79f5a92009-04-20 07:11:47 +00002524 eImageInfo_FixAndContinue = (1 << 0), // FIXME: Not sure what
2525 // this implies.
2526 eImageInfo_GarbageCollected = (1 << 1),
2527 eImageInfo_GCOnly = (1 << 2),
2528 eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
2529
2530 // A flag indicating that the module has no instances of an
2531 // @synthesize of a superclass variable. <rdar://problem/6803242>
2532 eImageInfo_CorrectedSynthesize = (1 << 4)
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002533};
2534
2535void CGObjCMac::EmitImageInfo() {
2536 unsigned version = 0; // Version is unused?
2537 unsigned flags = 0;
2538
2539 // FIXME: Fix and continue?
2540 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
2541 flags |= eImageInfo_GarbageCollected;
2542 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
2543 flags |= eImageInfo_GCOnly;
Daniel Dunbarb79f5a92009-04-20 07:11:47 +00002544
2545 // We never allow @synthesize of a superclass property.
2546 flags |= eImageInfo_CorrectedSynthesize;
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002547
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002548 // Emitted as int[2];
2549 llvm::Constant *values[2] = {
2550 llvm::ConstantInt::get(llvm::Type::Int32Ty, version),
2551 llvm::ConstantInt::get(llvm::Type::Int32Ty, flags)
2552 };
2553 llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::Int32Ty, 2);
Daniel Dunbar90d88f92009-03-09 21:49:58 +00002554
2555 const char *Section;
2556 if (ObjCABI == 1)
2557 Section = "__OBJC, __image_info,regular";
2558 else
2559 Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002560 llvm::GlobalVariable *GV =
Daniel Dunbar90d88f92009-03-09 21:49:58 +00002561 CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
2562 llvm::ConstantArray::get(AT, values, 2),
2563 Section,
2564 0,
2565 true);
2566 GV->setConstant(true);
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002567}
2568
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002569
2570// struct objc_module {
2571// unsigned long version;
2572// unsigned long size;
2573// const char *name;
2574// Symtab symtab;
2575// };
2576
2577// FIXME: Get from somewhere
2578static const int ModuleVersion = 7;
2579
2580void CGObjCMac::EmitModuleInfo() {
Daniel Dunbard8439f22009-01-12 21:08:18 +00002581 uint64_t Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.ModuleTy);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002582
2583 std::vector<llvm::Constant*> Values(4);
2584 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
2585 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbarac93e472008-08-15 22:20:32 +00002586 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002587 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002588 Values[3] = EmitModuleSymbols();
Daniel Dunbar90d88f92009-03-09 21:49:58 +00002589 CreateMetadataVar("\01L_OBJC_MODULES",
2590 llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
2591 "__OBJC,__module_info,regular,no_dead_strip",
Daniel Dunbar56756c32009-03-09 22:18:41 +00002592 4, true);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002593}
2594
2595llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002596 unsigned NumClasses = DefinedClasses.size();
2597 unsigned NumCategories = DefinedCategories.size();
2598
Daniel Dunbar8ede0052008-08-25 06:02:07 +00002599 // Return null if no symbols were defined.
2600 if (!NumClasses && !NumCategories)
2601 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
2602
2603 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002604 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2605 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
2606 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
2607 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
2608
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00002609 // The runtime expects exactly the list of defined classes followed
2610 // by the list of defined categories, in a single array.
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002611 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00002612 for (unsigned i=0; i<NumClasses; i++)
2613 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
2614 ObjCTypes.Int8PtrTy);
2615 for (unsigned i=0; i<NumCategories; i++)
2616 Symbols[NumClasses + i] =
2617 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
2618 ObjCTypes.Int8PtrTy);
2619
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002620 Values[4] =
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00002621 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002622 NumClasses + NumCategories),
2623 Symbols);
2624
2625 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
2626
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002627 llvm::GlobalVariable *GV =
Daniel Dunbar90d88f92009-03-09 21:49:58 +00002628 CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
2629 "__OBJC,__symbols,regular,no_dead_strip",
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00002630 4, true);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002631 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
2632}
2633
Daniel Dunbard916e6e2008-11-01 01:53:16 +00002634llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002635 const ObjCInterfaceDecl *ID) {
Daniel Dunbar8ede0052008-08-25 06:02:07 +00002636 LazySymbols.insert(ID->getIdentifier());
2637
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002638 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
2639
2640 if (!Entry) {
2641 llvm::Constant *Casted =
2642 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
2643 ObjCTypes.ClassPtrTy);
2644 Entry =
Daniel Dunbar90d88f92009-03-09 21:49:58 +00002645 CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
2646 "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00002647 4, true);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002648 }
2649
2650 return Builder.CreateLoad(Entry, false, "tmp");
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002651}
2652
Daniel Dunbard916e6e2008-11-01 01:53:16 +00002653llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) {
Daniel Dunbar5eec6142008-08-12 03:39:23 +00002654 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
2655
2656 if (!Entry) {
2657 llvm::Constant *Casted =
2658 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
2659 ObjCTypes.SelectorPtrTy);
2660 Entry =
Daniel Dunbar90d88f92009-03-09 21:49:58 +00002661 CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
2662 "__OBJC,__message_refs,literal_pointers,no_dead_strip",
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00002663 4, true);
Daniel Dunbar5eec6142008-08-12 03:39:23 +00002664 }
2665
2666 return Builder.CreateLoad(Entry, false, "tmp");
2667}
2668
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00002669llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002670 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002671
Daniel Dunbar90d88f92009-03-09 21:49:58 +00002672 if (!Entry)
2673 Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
2674 llvm::ConstantArray::get(Ident->getName()),
2675 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarfbfd92a2009-04-14 23:14:47 +00002676 1, true);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002677
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002678 return getConstantGEP(Entry, 0, 0);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002679}
2680
Fariborz Jahanian6d49ab62009-03-11 21:42:00 +00002681/// GetInterfaceDeclStructLayout - Get layout for ivars of given
2682/// interface declaration.
2683const llvm::StructLayout *CGObjCCommonMac::GetInterfaceDeclStructLayout(
2684 const ObjCInterfaceDecl *OID) const {
Daniel Dunbardbc8af72009-04-21 21:41:56 +00002685 assert(!OID->isForwardDecl() && "Invalid interface decl!");
Daniel Dunbar72878722009-04-20 20:18:54 +00002686 QualType T =
2687 CGM.getContext().getObjCInterfaceType(const_cast<ObjCInterfaceDecl*>(OID));
2688 const llvm::StructType *InterfaceTy =
2689 cast<llvm::StructType>(CGM.getTypes().ConvertType(T));
2690 return CGM.getTargetData().getStructLayout(InterfaceTy);
Fariborz Jahanian6d49ab62009-03-11 21:42:00 +00002691}
2692
Fariborz Jahanian7345eba2009-03-05 19:17:31 +00002693/// GetIvarLayoutName - Returns a unique constant for the given
2694/// ivar layout bitmap.
2695llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
2696 const ObjCCommonTypesHelper &ObjCTypes) {
2697 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
2698}
2699
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002700void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCInterfaceDecl *OI,
2701 const llvm::StructLayout *Layout,
Fariborz Jahanian37931062009-03-10 16:22:08 +00002702 const RecordDecl *RD,
Chris Lattner9329cf52009-03-31 08:48:01 +00002703 const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
Fariborz Jahanian01b3e342009-03-05 22:39:55 +00002704 unsigned int BytePos, bool ForStrongLayout,
2705 int &Index, int &SkIndex, bool &HasUnion) {
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002706 bool IsUnion = (RD && RD->isUnion());
2707 uint64_t MaxUnionIvarSize = 0;
2708 uint64_t MaxSkippedUnionIvarSize = 0;
2709 FieldDecl *MaxField = 0;
2710 FieldDecl *MaxSkippedField = 0;
Fariborz Jahanian7e052812009-04-21 18:33:06 +00002711 FieldDecl *LastFieldBitfield = 0;
2712
Chris Lattner9329cf52009-03-31 08:48:01 +00002713 unsigned base = 0;
Fariborz Jahanian37931062009-03-10 16:22:08 +00002714 if (RecFields.empty())
2715 return;
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002716 if (IsUnion)
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002717 base = BytePos + GetFieldBaseOffset(OI, Layout, RecFields[0]);
Chris Lattner9329cf52009-03-31 08:48:01 +00002718 unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
2719 unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
2720
2721 llvm::SmallVector<FieldDecl*, 16> TmpRecFields;
2722
2723 for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
Fariborz Jahanian37931062009-03-10 16:22:08 +00002724 FieldDecl *Field = RecFields[i];
2725 // Skip over unnamed or bitfields
Fariborz Jahanian7e052812009-04-21 18:33:06 +00002726 if (!Field->getIdentifier() || Field->isBitField()) {
2727 LastFieldBitfield = Field;
Fariborz Jahanian37931062009-03-10 16:22:08 +00002728 continue;
Fariborz Jahanian7e052812009-04-21 18:33:06 +00002729 }
2730 LastFieldBitfield = 0;
Fariborz Jahanian37931062009-03-10 16:22:08 +00002731 QualType FQT = Field->getType();
Fariborz Jahanian738ee712009-03-25 22:36:49 +00002732 if (FQT->isRecordType() || FQT->isUnionType()) {
Fariborz Jahanian37931062009-03-10 16:22:08 +00002733 if (FQT->isUnionType())
2734 HasUnion = true;
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002735 else
2736 assert(FQT->isRecordType() &&
2737 "only union/record is supported for ivar layout bitmap");
2738
Fariborz Jahanian37931062009-03-10 16:22:08 +00002739 const RecordType *RT = FQT->getAsRecordType();
2740 const RecordDecl *RD = RT->getDecl();
Daniel Dunbarecb5d402009-04-19 23:41:48 +00002741 // FIXME - Find a more efficient way of passing records down.
Douglas Gregorc55b0b02009-04-09 21:40:53 +00002742 TmpRecFields.append(RD->field_begin(CGM.getContext()),
2743 RD->field_end(CGM.getContext()));
Fariborz Jahanian31614742009-04-20 22:03:45 +00002744 const llvm::Type *Ty = CGM.getTypes().ConvertType(FQT);
2745 const llvm::StructLayout *RecLayout =
2746 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
2747
2748 BuildAggrIvarLayout(0, RecLayout, RD, TmpRecFields,
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002749 BytePos + GetFieldBaseOffset(OI, Layout, Field),
Fariborz Jahanian37931062009-03-10 16:22:08 +00002750 ForStrongLayout, Index, SkIndex,
2751 HasUnion);
Chris Lattner9329cf52009-03-31 08:48:01 +00002752 TmpRecFields.clear();
Fariborz Jahanian37931062009-03-10 16:22:08 +00002753 continue;
2754 }
Chris Lattner9329cf52009-03-31 08:48:01 +00002755
2756 if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002757 const ConstantArrayType *CArray =
2758 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7e052812009-04-21 18:33:06 +00002759 uint64_t ElCount = CArray->getSize().getZExtValue();
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002760 assert(CArray && "only array with know element size is supported");
2761 FQT = CArray->getElementType();
Fariborz Jahanian738ee712009-03-25 22:36:49 +00002762 while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
2763 const ConstantArrayType *CArray =
2764 dyn_cast_or_null<ConstantArrayType>(Array);
Fariborz Jahanian7e052812009-04-21 18:33:06 +00002765 ElCount *= CArray->getSize().getZExtValue();
Fariborz Jahanian738ee712009-03-25 22:36:49 +00002766 FQT = CArray->getElementType();
2767 }
2768
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002769 assert(!FQT->isUnionType() &&
2770 "layout for array of unions not supported");
2771 if (FQT->isRecordType()) {
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002772 int OldIndex = Index;
2773 int OldSkIndex = SkIndex;
2774
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002775 // FIXME - Use a common routine with the above!
2776 const RecordType *RT = FQT->getAsRecordType();
2777 const RecordDecl *RD = RT->getDecl();
2778 // FIXME - Find a more efficiant way of passing records down.
Douglas Gregorc55b0b02009-04-09 21:40:53 +00002779 TmpRecFields.append(RD->field_begin(CGM.getContext()),
2780 RD->field_end(CGM.getContext()));
Fariborz Jahanian31614742009-04-20 22:03:45 +00002781 const llvm::Type *Ty = CGM.getTypes().ConvertType(FQT);
2782 const llvm::StructLayout *RecLayout =
2783 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
Chris Lattner9329cf52009-03-31 08:48:01 +00002784
Fariborz Jahanian31614742009-04-20 22:03:45 +00002785 BuildAggrIvarLayout(0, RecLayout, RD,
Chris Lattner9329cf52009-03-31 08:48:01 +00002786 TmpRecFields,
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002787 BytePos + GetFieldBaseOffset(OI, Layout, Field),
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002788 ForStrongLayout, Index, SkIndex,
2789 HasUnion);
Chris Lattner9329cf52009-03-31 08:48:01 +00002790 TmpRecFields.clear();
2791
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002792 // Replicate layout information for each array element. Note that
2793 // one element is already done.
2794 uint64_t ElIx = 1;
2795 for (int FirstIndex = Index, FirstSkIndex = SkIndex;
2796 ElIx < ElCount; ElIx++) {
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002797 uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002798 for (int i = OldIndex+1; i <= FirstIndex; ++i)
2799 {
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002800 GC_IVAR gcivar;
2801 gcivar.ivar_bytepos = IvarsInfo[i].ivar_bytepos + Size*ElIx;
2802 gcivar.ivar_size = IvarsInfo[i].ivar_size;
2803 IvarsInfo.push_back(gcivar); ++Index;
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002804 }
2805
Chris Lattner9329cf52009-03-31 08:48:01 +00002806 for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i) {
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002807 GC_IVAR skivar;
2808 skivar.ivar_bytepos = SkipIvars[i].ivar_bytepos + Size*ElIx;
2809 skivar.ivar_size = SkipIvars[i].ivar_size;
2810 SkipIvars.push_back(skivar); ++SkIndex;
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002811 }
2812 }
2813 continue;
2814 }
Fariborz Jahanian37931062009-03-10 16:22:08 +00002815 }
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002816 // At this point, we are done with Record/Union and array there of.
2817 // For other arrays we are down to its element type.
2818 QualType::GCAttrTypes GCAttr = QualType::GCNone;
2819 do {
2820 if (FQT.isObjCGCStrong() || FQT.isObjCGCWeak()) {
2821 GCAttr = FQT.isObjCGCStrong() ? QualType::Strong : QualType::Weak;
2822 break;
2823 }
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002824 else if (CGM.getContext().isObjCObjectPointerType(FQT)) {
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002825 GCAttr = QualType::Strong;
2826 break;
2827 }
2828 else if (const PointerType *PT = FQT->getAsPointerType()) {
2829 FQT = PT->getPointeeType();
2830 }
2831 else {
2832 break;
2833 }
2834 } while (true);
Chris Lattner9329cf52009-03-31 08:48:01 +00002835
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002836 if ((ForStrongLayout && GCAttr == QualType::Strong)
2837 || (!ForStrongLayout && GCAttr == QualType::Weak)) {
2838 if (IsUnion)
2839 {
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002840 uint64_t UnionIvarSize = CGM.getContext().getTypeSize(Field->getType())
2841 / WordSizeInBits;
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002842 if (UnionIvarSize > MaxUnionIvarSize)
2843 {
2844 MaxUnionIvarSize = UnionIvarSize;
2845 MaxField = Field;
2846 }
2847 }
2848 else
2849 {
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002850 GC_IVAR gcivar;
2851 gcivar.ivar_bytepos = BytePos + GetFieldBaseOffset(OI, Layout, Field);
2852 gcivar.ivar_size = CGM.getContext().getTypeSize(Field->getType()) /
2853 WordSizeInBits;
2854 IvarsInfo.push_back(gcivar); ++Index;
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002855 }
2856 }
2857 else if ((ForStrongLayout &&
2858 (GCAttr == QualType::GCNone || GCAttr == QualType::Weak))
2859 || (!ForStrongLayout && GCAttr != QualType::Weak)) {
2860 if (IsUnion)
2861 {
2862 uint64_t UnionIvarSize = CGM.getContext().getTypeSize(Field->getType());
2863 if (UnionIvarSize > MaxSkippedUnionIvarSize)
2864 {
2865 MaxSkippedUnionIvarSize = UnionIvarSize;
2866 MaxSkippedField = Field;
2867 }
2868 }
2869 else
2870 {
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002871 GC_IVAR skivar;
2872 skivar.ivar_bytepos = BytePos + GetFieldBaseOffset(OI, Layout, Field);
2873 skivar.ivar_size = CGM.getContext().getTypeSize(Field->getType()) /
Fariborz Jahanian7e052812009-04-21 18:33:06 +00002874 ByteSizeInBits;
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002875 SkipIvars.push_back(skivar); ++SkIndex;
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002876 }
2877 }
2878 }
Fariborz Jahanian7e052812009-04-21 18:33:06 +00002879 if (LastFieldBitfield) {
2880 // Last field was a bitfield. Must update skip info.
2881 GC_IVAR skivar;
2882 skivar.ivar_bytepos = BytePos + GetFieldBaseOffset(OI, Layout,
2883 LastFieldBitfield);
2884 Expr *BitWidth = LastFieldBitfield->getBitWidth();
2885 uint64_t BitFieldSize =
2886 BitWidth->getIntegerConstantExprValue(CGM.getContext()).getZExtValue();
2887 skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
2888 + ((BitFieldSize % ByteSizeInBits) != 0);
2889 SkipIvars.push_back(skivar); ++SkIndex;
2890 }
2891
Chris Lattner9329cf52009-03-31 08:48:01 +00002892 if (MaxField) {
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002893 GC_IVAR gcivar;
2894 gcivar.ivar_bytepos = BytePos + GetFieldBaseOffset(OI, Layout, MaxField);
2895 gcivar.ivar_size = MaxUnionIvarSize;
2896 IvarsInfo.push_back(gcivar); ++Index;
Fariborz Jahanian7c0c17b2009-03-11 00:07:04 +00002897 }
Chris Lattner9329cf52009-03-31 08:48:01 +00002898
2899 if (MaxSkippedField) {
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002900 GC_IVAR skivar;
2901 skivar.ivar_bytepos = BytePos +
2902 GetFieldBaseOffset(OI, Layout, MaxSkippedField);
2903 skivar.ivar_size = MaxSkippedUnionIvarSize;
2904 SkipIvars.push_back(skivar); ++SkIndex;
Fariborz Jahanian37931062009-03-10 16:22:08 +00002905 }
Fariborz Jahanian01b3e342009-03-05 22:39:55 +00002906}
2907
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00002908static int
Chris Lattner9329cf52009-03-31 08:48:01 +00002909IvarBytePosCompare(const void *a, const void *b)
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00002910{
2911 unsigned int sa = ((CGObjCCommonMac::GC_IVAR *)a)->ivar_bytepos;
2912 unsigned int sb = ((CGObjCCommonMac::GC_IVAR *)b)->ivar_bytepos;
2913
2914 if (sa < sb)
2915 return -1;
2916 if (sa > sb)
2917 return 1;
2918 return 0;
2919}
2920
Fariborz Jahanian01b3e342009-03-05 22:39:55 +00002921/// BuildIvarLayout - Builds ivar layout bitmap for the class
2922/// implementation for the __strong or __weak case.
2923/// The layout map displays which words in ivar list must be skipped
2924/// and which must be scanned by GC (see below). String is built of bytes.
2925/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
2926/// of words to skip and right nibble is count of words to scan. So, each
2927/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
2928/// represented by a 0x00 byte which also ends the string.
2929/// 1. when ForStrongLayout is true, following ivars are scanned:
2930/// - id, Class
2931/// - object *
2932/// - __strong anything
2933///
2934/// 2. When ForStrongLayout is false, following ivars are scanned:
2935/// - __weak anything
2936///
Fariborz Jahanian37931062009-03-10 16:22:08 +00002937llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002938 const ObjCImplementationDecl *OMD,
2939 bool ForStrongLayout) {
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00002940 int Index = -1;
2941 int SkIndex = -1;
Fariborz Jahanian01b3e342009-03-05 22:39:55 +00002942 bool hasUnion = false;
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00002943 int SkipScan;
2944 unsigned int WordsToScan, WordsToSkip;
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002945 const llvm::Type *PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
2946 if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
2947 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahanian01b3e342009-03-05 22:39:55 +00002948
Chris Lattner9329cf52009-03-31 08:48:01 +00002949 llvm::SmallVector<FieldDecl*, 32> RecFields;
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002950 const ObjCInterfaceDecl *OI = OMD->getClassInterface();
Fariborz Jahanian01b3e342009-03-05 22:39:55 +00002951 CGM.getContext().CollectObjCIvars(OI, RecFields);
2952 if (RecFields.empty())
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002953 return llvm::Constant::getNullValue(PtrTy);
Chris Lattner9329cf52009-03-31 08:48:01 +00002954
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002955 SkipIvars.clear();
2956 IvarsInfo.clear();
Fariborz Jahanian6d49ab62009-03-11 21:42:00 +00002957
2958 const llvm::StructLayout *Layout = GetInterfaceDeclStructLayout(OI);
Chris Lattner9329cf52009-03-31 08:48:01 +00002959 BuildAggrIvarLayout(OI, Layout, 0, RecFields, 0, ForStrongLayout,
2960 Index, SkIndex, hasUnion);
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00002961 if (Index == -1)
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002962 return llvm::Constant::getNullValue(PtrTy);
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00002963
2964 // Sort on byte position in case we encounterred a union nested in
2965 // the ivar list.
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002966 if (hasUnion && !IvarsInfo.empty())
2967 qsort(&IvarsInfo[0], Index+1, sizeof(GC_IVAR), IvarBytePosCompare);
2968 if (hasUnion && !SkipIvars.empty())
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00002969 qsort(&SkipIvars[0], Index+1, sizeof(GC_IVAR), IvarBytePosCompare);
2970
2971 // Build the string of skip/scan nibbles
2972 SkipScan = -1;
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002973 SkipScanIvars.clear();
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00002974 unsigned int WordSize =
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002975 CGM.getTypes().getTargetData().getTypePaddedSize(PtrTy);
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00002976 if (IvarsInfo[0].ivar_bytepos == 0) {
2977 WordsToSkip = 0;
2978 WordsToScan = IvarsInfo[0].ivar_size;
2979 }
2980 else {
2981 WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
2982 WordsToScan = IvarsInfo[0].ivar_size;
2983 }
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00002984 for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++)
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00002985 {
2986 unsigned int TailPrevGCObjC =
2987 IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
2988 if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC)
2989 {
2990 // consecutive 'scanned' object pointers.
2991 WordsToScan += IvarsInfo[i].ivar_size;
2992 }
2993 else
2994 {
2995 // Skip over 'gc'able object pointer which lay over each other.
2996 if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
2997 continue;
2998 // Must skip over 1 or more words. We save current skip/scan values
2999 // and start a new pair.
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00003000 SKIP_SCAN SkScan;
3001 SkScan.skip = WordsToSkip;
3002 SkScan.scan = WordsToScan;
3003 SkipScanIvars.push_back(SkScan); ++SkipScan;
3004
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00003005 // Skip the hole.
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00003006 SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
3007 SkScan.scan = 0;
3008 SkipScanIvars.push_back(SkScan); ++SkipScan;
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00003009 WordsToSkip = 0;
3010 WordsToScan = IvarsInfo[i].ivar_size;
3011 }
3012 }
3013 if (WordsToScan > 0)
3014 {
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00003015 SKIP_SCAN SkScan;
3016 SkScan.skip = WordsToSkip;
3017 SkScan.scan = WordsToScan;
3018 SkipScanIvars.push_back(SkScan); ++SkipScan;
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00003019 }
3020
3021 bool BytesSkipped = false;
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00003022 if (!SkipIvars.empty())
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00003023 {
3024 int LastByteSkipped =
3025 SkipIvars[SkIndex].ivar_bytepos + SkipIvars[SkIndex].ivar_size;
3026 int LastByteScanned =
3027 IvarsInfo[Index].ivar_bytepos + IvarsInfo[Index].ivar_size * WordSize;
3028 BytesSkipped = (LastByteSkipped > LastByteScanned);
3029 // Compute number of bytes to skip at the tail end of the last ivar scanned.
3030 if (BytesSkipped)
3031 {
3032 unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00003033 SKIP_SCAN SkScan;
3034 SkScan.skip = TotalWords - (LastByteScanned/WordSize);
3035 SkScan.scan = 0;
3036 SkipScanIvars.push_back(SkScan); ++SkipScan;
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00003037 }
3038 }
3039 // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
3040 // as 0xMN.
3041 for (int i = 0; i <= SkipScan; i++)
3042 {
3043 if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
3044 && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
3045 // 0xM0 followed by 0x0N detected.
3046 SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
3047 for (int j = i+1; j < SkipScan; j++)
3048 SkipScanIvars[j] = SkipScanIvars[j+1];
3049 --SkipScan;
3050 }
3051 }
3052
3053 // Generate the string.
3054 std::string BitMap;
3055 for (int i = 0; i <= SkipScan; i++)
3056 {
3057 unsigned char byte;
3058 unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
3059 unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
3060 unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
3061 unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
3062
3063 if (skip_small > 0 || skip_big > 0)
3064 BytesSkipped = true;
3065 // first skip big.
3066 for (unsigned int ix = 0; ix < skip_big; ix++)
3067 BitMap += (unsigned char)(0xf0);
3068
3069 // next (skip small, scan)
3070 if (skip_small)
3071 {
3072 byte = skip_small << 4;
3073 if (scan_big > 0)
3074 {
3075 byte |= 0xf;
3076 --scan_big;
3077 }
3078 else if (scan_small)
3079 {
3080 byte |= scan_small;
3081 scan_small = 0;
3082 }
3083 BitMap += byte;
3084 }
3085 // next scan big
3086 for (unsigned int ix = 0; ix < scan_big; ix++)
3087 BitMap += (unsigned char)(0x0f);
3088 // last scan small
3089 if (scan_small)
3090 {
3091 byte = scan_small;
3092 BitMap += byte;
3093 }
3094 }
3095 // null terminate string.
Fariborz Jahanian738ee712009-03-25 22:36:49 +00003096 unsigned char zero = 0;
3097 BitMap += zero;
Fariborz Jahanian31614742009-04-20 22:03:45 +00003098
3099 if (CGM.getLangOptions().ObjCGCBitmapPrint) {
3100 printf("\n%s ivar layout for class '%s': ",
3101 ForStrongLayout ? "strong" : "weak",
3102 OMD->getClassInterface()->getNameAsCString());
3103 const unsigned char *s = (unsigned char*)BitMap.c_str();
3104 for (unsigned i = 0; i < BitMap.size(); i++)
3105 if (!(s[i] & 0xf0))
3106 printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
3107 else
3108 printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
3109 printf("\n");
3110 }
3111
Fariborz Jahaniandf1d9032009-03-11 20:59:05 +00003112 // if ivar_layout bitmap is all 1 bits (nothing skipped) then use NULL as
3113 // final layout.
3114 if (ForStrongLayout && !BytesSkipped)
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00003115 return llvm::Constant::getNullValue(PtrTy);
3116 llvm::GlobalVariable * Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
3117 llvm::ConstantArray::get(BitMap.c_str()),
3118 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarfbfd92a2009-04-14 23:14:47 +00003119 1, true);
Fariborz Jahanian31614742009-04-20 22:03:45 +00003120 return getConstantGEP(Entry, 0, 0);
Fariborz Jahanian01b3e342009-03-05 22:39:55 +00003121}
3122
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00003123llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbar5eec6142008-08-12 03:39:23 +00003124 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
3125
Daniel Dunbar90d88f92009-03-09 21:49:58 +00003126 // FIXME: Avoid std::string copying.
3127 if (!Entry)
3128 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
3129 llvm::ConstantArray::get(Sel.getAsString()),
3130 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarfbfd92a2009-04-14 23:14:47 +00003131 1, true);
Daniel Dunbar5eec6142008-08-12 03:39:23 +00003132
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003133 return getConstantGEP(Entry, 0, 0);
3134}
3135
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003136// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00003137llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003138 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
3139}
3140
3141// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00003142llvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003143 return GetMethodVarName(&CGM.getContext().Idents.get(Name));
3144}
3145
Daniel Dunbar356f0742009-04-20 06:54:31 +00003146llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
Devang Patel593a07a2009-03-04 18:21:39 +00003147 std::string TypeStr;
3148 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
3149
3150 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003151
Daniel Dunbar90d88f92009-03-09 21:49:58 +00003152 if (!Entry)
3153 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
3154 llvm::ConstantArray::get(TypeStr),
3155 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarfbfd92a2009-04-14 23:14:47 +00003156 1, true);
Daniel Dunbar90d88f92009-03-09 21:49:58 +00003157
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003158 return getConstantGEP(Entry, 0, 0);
Daniel Dunbar5eec6142008-08-12 03:39:23 +00003159}
3160
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00003161llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003162 std::string TypeStr;
Daniel Dunbar12996f52008-08-26 21:51:14 +00003163 CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
3164 TypeStr);
Devang Patel593a07a2009-03-04 18:21:39 +00003165
3166 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
3167
Daniel Dunbarfbfd92a2009-04-14 23:14:47 +00003168 if (!Entry)
3169 Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
3170 llvm::ConstantArray::get(TypeStr),
3171 "__TEXT,__cstring,cstring_literals",
3172 1, true);
Devang Patel593a07a2009-03-04 18:21:39 +00003173
3174 return getConstantGEP(Entry, 0, 0);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003175}
3176
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00003177// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00003178llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00003179 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
3180
Daniel Dunbar90d88f92009-03-09 21:49:58 +00003181 if (!Entry)
3182 Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
3183 llvm::ConstantArray::get(Ident->getName()),
3184 "__TEXT,__cstring,cstring_literals",
Daniel Dunbarfbfd92a2009-04-14 23:14:47 +00003185 1, true);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00003186
3187 return getConstantGEP(Entry, 0, 0);
3188}
3189
3190// FIXME: Merge into a single cstring creation function.
Daniel Dunbar698d6f32008-08-28 04:38:10 +00003191// FIXME: This Decl should be more precise.
Daniel Dunbar90d88f92009-03-09 21:49:58 +00003192llvm::Constant *
3193 CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
3194 const Decl *Container) {
Daniel Dunbar698d6f32008-08-28 04:38:10 +00003195 std::string TypeStr;
3196 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00003197 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
3198}
3199
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00003200void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
3201 const ObjCContainerDecl *CD,
3202 std::string &NameOut) {
Daniel Dunbara2d275d2009-04-07 05:48:37 +00003203 NameOut = '\01';
3204 NameOut += (D->isInstanceMethod() ? '-' : '+');
Chris Lattner3a8f2942008-11-24 03:33:13 +00003205 NameOut += '[';
Fariborz Jahanian0adaa8a2009-01-10 21:06:09 +00003206 assert (CD && "Missing container decl in GetNameForMethod");
3207 NameOut += CD->getNameAsString();
Fariborz Jahanian6e4b7372009-04-16 18:34:20 +00003208 if (const ObjCCategoryImplDecl *CID =
3209 dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) {
3210 NameOut += '(';
3211 NameOut += CID->getNameAsString();
3212 NameOut+= ')';
3213 }
Chris Lattner3a8f2942008-11-24 03:33:13 +00003214 NameOut += ' ';
3215 NameOut += D->getSelector().getAsString();
3216 NameOut += ']';
Daniel Dunbarace33292008-08-16 03:19:19 +00003217}
3218
Daniel Dunbar1be1df32008-08-11 21:35:06 +00003219void CGObjCMac::FinishModule() {
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00003220 EmitModuleInfo();
3221
Daniel Dunbar35b777f2008-10-29 22:36:39 +00003222 // Emit the dummy bodies for any protocols which were referenced but
3223 // never defined.
3224 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
3225 i = Protocols.begin(), e = Protocols.end(); i != e; ++i) {
3226 if (i->second->hasInitializer())
3227 continue;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00003228
Daniel Dunbar35b777f2008-10-29 22:36:39 +00003229 std::vector<llvm::Constant*> Values(5);
3230 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
3231 Values[1] = GetClassName(i->first);
3232 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
3233 Values[3] = Values[4] =
3234 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
3235 i->second->setLinkage(llvm::GlobalValue::InternalLinkage);
3236 i->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
3237 Values));
3238 }
3239
3240 std::vector<llvm::Constant*> Used;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00003241 for (std::vector<llvm::GlobalVariable*>::iterator i = UsedGlobals.begin(),
Daniel Dunbar1be1df32008-08-11 21:35:06 +00003242 e = UsedGlobals.end(); i != e; ++i) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003243 Used.push_back(llvm::ConstantExpr::getBitCast(*i, ObjCTypes.Int8PtrTy));
Daniel Dunbar1be1df32008-08-11 21:35:06 +00003244 }
3245
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003246 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Used.size());
Daniel Dunbar1be1df32008-08-11 21:35:06 +00003247 llvm::GlobalValue *GV =
3248 new llvm::GlobalVariable(AT, false,
3249 llvm::GlobalValue::AppendingLinkage,
3250 llvm::ConstantArray::get(AT, Used),
3251 "llvm.used",
3252 &CGM.getModule());
3253
3254 GV->setSection("llvm.metadata");
Daniel Dunbar8ede0052008-08-25 06:02:07 +00003255
3256 // Add assembler directives to add lazy undefined symbol references
3257 // for classes which are referenced but not defined. This is
3258 // important for correct linker interaction.
3259
3260 // FIXME: Uh, this isn't particularly portable.
3261 std::stringstream s;
Anders Carlsson63f98352008-12-10 02:21:04 +00003262
3263 if (!CGM.getModule().getModuleInlineAsm().empty())
3264 s << "\n";
3265
Daniel Dunbar8ede0052008-08-25 06:02:07 +00003266 for (std::set<IdentifierInfo*>::iterator i = LazySymbols.begin(),
3267 e = LazySymbols.end(); i != e; ++i) {
3268 s << "\t.lazy_reference .objc_class_name_" << (*i)->getName() << "\n";
3269 }
3270 for (std::set<IdentifierInfo*>::iterator i = DefinedSymbols.begin(),
3271 e = DefinedSymbols.end(); i != e; ++i) {
Daniel Dunbar698d6f32008-08-28 04:38:10 +00003272 s << "\t.objc_class_name_" << (*i)->getName() << "=0\n"
Daniel Dunbar8ede0052008-08-25 06:02:07 +00003273 << "\t.globl .objc_class_name_" << (*i)->getName() << "\n";
3274 }
Anders Carlsson63f98352008-12-10 02:21:04 +00003275
Daniel Dunbar8ede0052008-08-25 06:02:07 +00003276 CGM.getModule().appendModuleInlineAsm(s.str());
Daniel Dunbar1be1df32008-08-11 21:35:06 +00003277}
3278
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003279CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003280 : CGObjCCommonMac(cgm),
3281 ObjCTypes(cgm)
3282{
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003283 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003284 ObjCABI = 2;
3285}
3286
Daniel Dunbar1be1df32008-08-11 21:35:06 +00003287/* *** */
3288
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003289ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
3290: CGM(cgm)
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00003291{
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00003292 CodeGen::CodeGenTypes &Types = CGM.getTypes();
3293 ASTContext &Ctx = CGM.getContext();
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003294
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003295 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003296 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00003297 LongTy = Types.ConvertType(Ctx.LongTy);
Fariborz Jahanianad51ca02009-03-23 19:10:40 +00003298 LongLongTy = Types.ConvertType(Ctx.LongLongTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003299 Int8PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
3300
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00003301 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Fariborz Jahanianc192d4d2008-11-18 20:18:11 +00003302 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00003303 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003304
3305 // FIXME: It would be nice to unify this with the opaque type, so
3306 // that the IR comes out a bit cleaner.
3307 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
3308 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003309
3310 // I'm not sure I like this. The implicit coordination is a bit
3311 // gross. We should solve this in a reasonable fashion because this
3312 // is a pretty common task (match some runtime data structure with
3313 // an LLVM data structure).
3314
3315 // FIXME: This is leaked.
3316 // FIXME: Merge with rewriter code?
3317
3318 // struct _objc_super {
3319 // id self;
3320 // Class cls;
3321 // }
3322 RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
3323 SourceLocation(),
3324 &Ctx.Idents.get("_objc_super"));
Douglas Gregorc55b0b02009-04-09 21:40:53 +00003325 RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
3326 Ctx.getObjCIdType(), 0, false));
3327 RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
3328 Ctx.getObjCClassType(), 0, false));
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003329 RD->completeDefinition(Ctx);
3330
3331 SuperCTy = Ctx.getTagDeclType(RD);
3332 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
3333
3334 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003335 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
3336
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003337 // struct _prop_t {
3338 // char *name;
3339 // char *attributes;
3340 // }
3341 PropertyTy = llvm::StructType::get(Int8PtrTy,
3342 Int8PtrTy,
3343 NULL);
3344 CGM.getModule().addTypeName("struct._prop_t",
3345 PropertyTy);
3346
3347 // struct _prop_list_t {
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003348 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003349 // uint32_t count_of_properties;
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003350 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003351 // }
3352 PropertyListTy = llvm::StructType::get(IntTy,
3353 IntTy,
3354 llvm::ArrayType::get(PropertyTy, 0),
3355 NULL);
3356 CGM.getModule().addTypeName("struct._prop_list_t",
3357 PropertyListTy);
3358 // struct _prop_list_t *
3359 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
3360
3361 // struct _objc_method {
3362 // SEL _cmd;
3363 // char *method_type;
3364 // char *_imp;
3365 // }
3366 MethodTy = llvm::StructType::get(SelectorPtrTy,
3367 Int8PtrTy,
3368 Int8PtrTy,
3369 NULL);
3370 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003371
3372 // struct _objc_cache *
3373 CacheTy = llvm::OpaqueType::get();
3374 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
3375 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003376
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003377 // Property manipulation functions.
Daniel Dunbardac29922009-02-04 00:44:42 +00003378
3379 QualType IdType = Ctx.getObjCIdType();
3380 QualType SelType = Ctx.getObjCSelType();
3381 llvm::SmallVector<QualType,16> Params;
3382 const llvm::FunctionType *FTy;
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003383
3384 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
Daniel Dunbardac29922009-02-04 00:44:42 +00003385 Params.push_back(IdType);
3386 Params.push_back(SelType);
3387 Params.push_back(Ctx.LongTy);
3388 Params.push_back(Ctx.BoolTy);
3389 FTy = Types.GetFunctionType(Types.getFunctionInfo(IdType, Params),
3390 false);
3391 GetPropertyFn = CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003392
3393 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
3394 Params.clear();
Daniel Dunbardac29922009-02-04 00:44:42 +00003395 Params.push_back(IdType);
3396 Params.push_back(SelType);
3397 Params.push_back(Ctx.LongTy);
3398 Params.push_back(IdType);
3399 Params.push_back(Ctx.BoolTy);
3400 Params.push_back(Ctx.BoolTy);
3401 FTy = Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
3402 SetPropertyFn = CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
3403
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003404 // Enumeration mutation.
Daniel Dunbardac29922009-02-04 00:44:42 +00003405
3406 // void objc_enumerationMutation (id)
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003407 Params.clear();
Daniel Dunbardac29922009-02-04 00:44:42 +00003408 Params.push_back(IdType);
3409 FTy = Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
3410 EnumerationMutationFn = CGM.CreateRuntimeFunction(FTy,
3411 "objc_enumerationMutation");
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003412
3413 // gc's API
3414 // id objc_read_weak (id *)
3415 Params.clear();
Daniel Dunbardac29922009-02-04 00:44:42 +00003416 Params.push_back(Ctx.getPointerType(IdType));
3417 FTy = Types.GetFunctionType(Types.getFunctionInfo(IdType, Params), false);
3418 GcReadWeakFn = CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
3419
Chris Lattner293c1d32009-04-17 22:12:36 +00003420 // id objc_assign_global (id, id *)
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003421 Params.clear();
Daniel Dunbardac29922009-02-04 00:44:42 +00003422 Params.push_back(IdType);
3423 Params.push_back(Ctx.getPointerType(IdType));
3424
3425 FTy = Types.GetFunctionType(Types.getFunctionInfo(IdType, Params), false);
Daniel Dunbardac29922009-02-04 00:44:42 +00003426 GcAssignGlobalFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
3427 GcAssignIvarFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
3428 GcAssignStrongCastFn =
3429 CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
Anders Carlsson1cf75362009-02-16 22:59:18 +00003430
3431 // void objc_exception_throw(id)
3432 Params.clear();
3433 Params.push_back(IdType);
3434
3435 FTy = Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
Anders Carlsson1cf75362009-02-16 22:59:18 +00003436 ExceptionThrowFn =
3437 CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
Daniel Dunbar34416d62009-02-24 01:43:46 +00003438
3439 // synchronized APIs
Daniel Dunbar34416d62009-02-24 01:43:46 +00003440 // void objc_sync_exit (id)
3441 Params.clear();
3442 Params.push_back(IdType);
3443
3444 FTy = Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
Daniel Dunbar34416d62009-02-24 01:43:46 +00003445 SyncExitFn = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003446}
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00003447
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003448ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
3449 : ObjCCommonTypesHelper(cgm)
3450{
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003451 // struct _objc_method_description {
3452 // SEL name;
3453 // char *types;
3454 // }
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003455 MethodDescriptionTy =
3456 llvm::StructType::get(SelectorPtrTy,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003457 Int8PtrTy,
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003458 NULL);
3459 CGM.getModule().addTypeName("struct._objc_method_description",
3460 MethodDescriptionTy);
3461
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003462 // struct _objc_method_description_list {
3463 // int count;
3464 // struct _objc_method_description[1];
3465 // }
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003466 MethodDescriptionListTy =
3467 llvm::StructType::get(IntTy,
3468 llvm::ArrayType::get(MethodDescriptionTy, 0),
3469 NULL);
3470 CGM.getModule().addTypeName("struct._objc_method_description_list",
3471 MethodDescriptionListTy);
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003472
3473 // struct _objc_method_description_list *
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003474 MethodDescriptionListPtrTy =
3475 llvm::PointerType::getUnqual(MethodDescriptionListTy);
3476
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003477 // Protocol description structures
3478
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003479 // struct _objc_protocol_extension {
3480 // uint32_t size; // sizeof(struct _objc_protocol_extension)
3481 // struct _objc_method_description_list *optional_instance_methods;
3482 // struct _objc_method_description_list *optional_class_methods;
3483 // struct _objc_property_list *instance_properties;
3484 // }
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003485 ProtocolExtensionTy =
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003486 llvm::StructType::get(IntTy,
3487 MethodDescriptionListPtrTy,
3488 MethodDescriptionListPtrTy,
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003489 PropertyListPtrTy,
3490 NULL);
3491 CGM.getModule().addTypeName("struct._objc_protocol_extension",
3492 ProtocolExtensionTy);
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003493
3494 // struct _objc_protocol_extension *
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003495 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
3496
Daniel Dunbar35b777f2008-10-29 22:36:39 +00003497 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003498
3499 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get();
3500 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get();
3501
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003502 const llvm::Type *T =
3503 llvm::StructType::get(llvm::PointerType::getUnqual(ProtocolListTyHolder),
3504 LongTy,
3505 llvm::ArrayType::get(ProtocolTyHolder, 0),
3506 NULL);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003507 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
3508
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003509 // struct _objc_protocol {
3510 // struct _objc_protocol_extension *isa;
3511 // char *protocol_name;
3512 // struct _objc_protocol **_objc_protocol_list;
3513 // struct _objc_method_description_list *instance_methods;
3514 // struct _objc_method_description_list *class_methods;
3515 // }
3516 T = llvm::StructType::get(ProtocolExtensionPtrTy,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003517 Int8PtrTy,
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003518 llvm::PointerType::getUnqual(ProtocolListTyHolder),
3519 MethodDescriptionListPtrTy,
3520 MethodDescriptionListPtrTy,
3521 NULL);
3522 cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
3523
3524 ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
3525 CGM.getModule().addTypeName("struct._objc_protocol_list",
3526 ProtocolListTy);
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003527 // struct _objc_protocol_list *
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003528 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
3529
3530 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003531 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003532 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003533
3534 // Class description structures
3535
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003536 // struct _objc_ivar {
3537 // char *ivar_name;
3538 // char *ivar_type;
3539 // int ivar_offset;
3540 // }
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003541 IvarTy = llvm::StructType::get(Int8PtrTy,
3542 Int8PtrTy,
3543 IntTy,
3544 NULL);
3545 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
3546
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003547 // struct _objc_ivar_list *
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003548 IvarListTy = llvm::OpaqueType::get();
3549 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
3550 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
3551
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003552 // struct _objc_method_list *
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003553 MethodListTy = llvm::OpaqueType::get();
3554 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
3555 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
3556
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003557 // struct _objc_class_extension *
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003558 ClassExtensionTy =
3559 llvm::StructType::get(IntTy,
3560 Int8PtrTy,
3561 PropertyListPtrTy,
3562 NULL);
3563 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
3564 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
3565
3566 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get();
3567
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003568 // struct _objc_class {
3569 // Class isa;
3570 // Class super_class;
3571 // char *name;
3572 // long version;
3573 // long info;
3574 // long instance_size;
3575 // struct _objc_ivar_list *ivars;
3576 // struct _objc_method_list *methods;
3577 // struct _objc_cache *cache;
3578 // struct _objc_protocol_list *protocols;
3579 // char *ivar_layout;
3580 // struct _objc_class_ext *ext;
3581 // };
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003582 T = llvm::StructType::get(llvm::PointerType::getUnqual(ClassTyHolder),
3583 llvm::PointerType::getUnqual(ClassTyHolder),
3584 Int8PtrTy,
3585 LongTy,
3586 LongTy,
3587 LongTy,
3588 IvarListPtrTy,
3589 MethodListPtrTy,
3590 CachePtrTy,
3591 ProtocolListPtrTy,
3592 Int8PtrTy,
3593 ClassExtensionPtrTy,
3594 NULL);
3595 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
3596
3597 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
3598 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
3599 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
3600
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003601 // struct _objc_category {
3602 // char *category_name;
3603 // char *class_name;
3604 // struct _objc_method_list *instance_method;
3605 // struct _objc_method_list *class_method;
3606 // uint32_t size; // sizeof(struct _objc_category)
3607 // struct _objc_property_list *instance_properties;// category's @property
3608 // }
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00003609 CategoryTy = llvm::StructType::get(Int8PtrTy,
3610 Int8PtrTy,
3611 MethodListPtrTy,
3612 MethodListPtrTy,
3613 ProtocolListPtrTy,
3614 IntTy,
3615 PropertyListPtrTy,
3616 NULL);
3617 CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
3618
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003619 // Global metadata structures
3620
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003621 // struct _objc_symtab {
3622 // long sel_ref_cnt;
3623 // SEL *refs;
3624 // short cls_def_cnt;
3625 // short cat_def_cnt;
3626 // char *defs[cls_def_cnt + cat_def_cnt];
3627 // }
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003628 SymtabTy = llvm::StructType::get(LongTy,
3629 SelectorPtrTy,
3630 ShortTy,
3631 ShortTy,
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00003632 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003633 NULL);
3634 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
3635 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
3636
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003637 // struct _objc_module {
3638 // long version;
3639 // long size; // sizeof(struct _objc_module)
3640 // char *name;
3641 // struct _objc_symtab* symtab;
3642 // }
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003643 ModuleTy =
3644 llvm::StructType::get(LongTy,
3645 LongTy,
3646 Int8PtrTy,
3647 SymtabPtrTy,
3648 NULL);
3649 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003650
Anders Carlsson58d16242008-08-31 04:05:03 +00003651
Anders Carlsson9acb0a42008-09-09 10:10:21 +00003652 // FIXME: This is the size of the setjmp buffer and should be
3653 // target specific. 18 is what's used on 32-bit X86.
3654 uint64_t SetJmpBufferSize = 18;
3655
3656 // Exceptions
3657 const llvm::Type *StackPtrTy =
Daniel Dunbar1c5e4632008-09-27 06:32:25 +00003658 llvm::ArrayType::get(llvm::PointerType::getUnqual(llvm::Type::Int8Ty), 4);
Anders Carlsson9acb0a42008-09-09 10:10:21 +00003659
3660 ExceptionDataTy =
3661 llvm::StructType::get(llvm::ArrayType::get(llvm::Type::Int32Ty,
3662 SetJmpBufferSize),
3663 StackPtrTy, NULL);
3664 CGM.getModule().addTypeName("struct._objc_exception_data",
3665 ExceptionDataTy);
3666
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00003667}
3668
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003669ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003670: ObjCCommonTypesHelper(cgm)
3671{
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003672 // struct _method_list_t {
3673 // uint32_t entsize; // sizeof(struct _objc_method)
3674 // uint32_t method_count;
3675 // struct _objc_method method_list[method_count];
3676 // }
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003677 MethodListnfABITy = llvm::StructType::get(IntTy,
3678 IntTy,
3679 llvm::ArrayType::get(MethodTy, 0),
3680 NULL);
3681 CGM.getModule().addTypeName("struct.__method_list_t",
3682 MethodListnfABITy);
3683 // struct method_list_t *
3684 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003685
3686 // struct _protocol_t {
3687 // id isa; // NULL
3688 // const char * const protocol_name;
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003689 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003690 // const struct method_list_t * const instance_methods;
3691 // const struct method_list_t * const class_methods;
3692 // const struct method_list_t *optionalInstanceMethods;
3693 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003694 // const struct _prop_list_t * properties;
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003695 // const uint32_t size; // sizeof(struct _protocol_t)
3696 // const uint32_t flags; // = 0
3697 // }
3698
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003699 // Holder for struct _protocol_list_t *
3700 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get();
3701
3702 ProtocolnfABITy = llvm::StructType::get(ObjectPtrTy,
3703 Int8PtrTy,
3704 llvm::PointerType::getUnqual(
3705 ProtocolListTyHolder),
3706 MethodListnfABIPtrTy,
3707 MethodListnfABIPtrTy,
3708 MethodListnfABIPtrTy,
3709 MethodListnfABIPtrTy,
3710 PropertyListPtrTy,
3711 IntTy,
3712 IntTy,
3713 NULL);
3714 CGM.getModule().addTypeName("struct._protocol_t",
3715 ProtocolnfABITy);
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00003716
3717 // struct _protocol_t*
3718 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003719
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00003720 // struct _protocol_list_t {
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003721 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00003722 // struct _protocol_t *[protocol_count];
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003723 // }
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003724 ProtocolListnfABITy = llvm::StructType::get(LongTy,
3725 llvm::ArrayType::get(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00003726 ProtocolnfABIPtrTy, 0),
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003727 NULL);
3728 CGM.getModule().addTypeName("struct._objc_protocol_list",
3729 ProtocolListnfABITy);
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00003730 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
3731 ProtocolListnfABITy);
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003732
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003733 // struct _objc_protocol_list*
3734 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003735
3736 // struct _ivar_t {
3737 // unsigned long int *offset; // pointer to ivar offset location
3738 // char *name;
3739 // char *type;
3740 // uint32_t alignment;
3741 // uint32_t size;
3742 // }
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003743 IvarnfABITy = llvm::StructType::get(llvm::PointerType::getUnqual(LongTy),
3744 Int8PtrTy,
3745 Int8PtrTy,
3746 IntTy,
3747 IntTy,
3748 NULL);
3749 CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
3750
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003751 // struct _ivar_list_t {
3752 // uint32 entsize; // sizeof(struct _ivar_t)
3753 // uint32 count;
3754 // struct _iver_t list[count];
3755 // }
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003756 IvarListnfABITy = llvm::StructType::get(IntTy,
3757 IntTy,
3758 llvm::ArrayType::get(
3759 IvarnfABITy, 0),
3760 NULL);
3761 CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
3762
3763 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003764
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003765 // struct _class_ro_t {
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003766 // uint32_t const flags;
3767 // uint32_t const instanceStart;
3768 // uint32_t const instanceSize;
3769 // uint32_t const reserved; // only when building for 64bit targets
3770 // const uint8_t * const ivarLayout;
3771 // const char *const name;
3772 // const struct _method_list_t * const baseMethods;
3773 // const struct _objc_protocol_list *const baseProtocols;
3774 // const struct _ivar_list_t *const ivars;
3775 // const uint8_t * const weakIvarLayout;
3776 // const struct _prop_list_t * const properties;
3777 // }
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003778
3779 // FIXME. Add 'reserved' field in 64bit abi mode!
3780 ClassRonfABITy = llvm::StructType::get(IntTy,
3781 IntTy,
3782 IntTy,
3783 Int8PtrTy,
3784 Int8PtrTy,
3785 MethodListnfABIPtrTy,
3786 ProtocolListnfABIPtrTy,
3787 IvarListnfABIPtrTy,
3788 Int8PtrTy,
3789 PropertyListPtrTy,
3790 NULL);
3791 CGM.getModule().addTypeName("struct._class_ro_t",
3792 ClassRonfABITy);
3793
3794 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
3795 std::vector<const llvm::Type*> Params;
3796 Params.push_back(ObjectPtrTy);
3797 Params.push_back(SelectorPtrTy);
3798 ImpnfABITy = llvm::PointerType::getUnqual(
3799 llvm::FunctionType::get(ObjectPtrTy, Params, false));
3800
3801 // struct _class_t {
3802 // struct _class_t *isa;
3803 // struct _class_t * const superclass;
3804 // void *cache;
3805 // IMP *vtable;
3806 // struct class_ro_t *ro;
3807 // }
3808
3809 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get();
3810 ClassnfABITy = llvm::StructType::get(llvm::PointerType::getUnqual(ClassTyHolder),
3811 llvm::PointerType::getUnqual(ClassTyHolder),
3812 CachePtrTy,
3813 llvm::PointerType::getUnqual(ImpnfABITy),
3814 llvm::PointerType::getUnqual(
3815 ClassRonfABITy),
3816 NULL);
3817 CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
3818
3819 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
3820 ClassnfABITy);
3821
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003822 // LLVM for struct _class_t *
3823 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
3824
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003825 // struct _category_t {
3826 // const char * const name;
3827 // struct _class_t *const cls;
3828 // const struct _method_list_t * const instance_methods;
3829 // const struct _method_list_t * const class_methods;
3830 // const struct _protocol_list_t * const protocols;
3831 // const struct _prop_list_t * const properties;
Fariborz Jahanianb9459b72009-01-23 17:41:22 +00003832 // }
3833 CategorynfABITy = llvm::StructType::get(Int8PtrTy,
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003834 ClassnfABIPtrTy,
Fariborz Jahanianb9459b72009-01-23 17:41:22 +00003835 MethodListnfABIPtrTy,
3836 MethodListnfABIPtrTy,
3837 ProtocolListnfABIPtrTy,
3838 PropertyListPtrTy,
3839 NULL);
3840 CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003841
3842 // New types for nonfragile abi messaging.
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00003843 CodeGen::CodeGenTypes &Types = CGM.getTypes();
3844 ASTContext &Ctx = CGM.getContext();
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003845
3846 // MessageRefTy - LLVM for:
3847 // struct _message_ref_t {
3848 // IMP messenger;
3849 // SEL name;
3850 // };
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00003851
3852 // First the clang type for struct _message_ref_t
3853 RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
3854 SourceLocation(),
3855 &Ctx.Idents.get("_message_ref_t"));
Douglas Gregorc55b0b02009-04-09 21:40:53 +00003856 RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
3857 Ctx.VoidPtrTy, 0, false));
3858 RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
3859 Ctx.getObjCSelType(), 0, false));
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00003860 RD->completeDefinition(Ctx);
3861
3862 MessageRefCTy = Ctx.getTagDeclType(RD);
3863 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
3864 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003865
3866 // MessageRefPtrTy - LLVM for struct _message_ref_t*
3867 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
3868
3869 // SuperMessageRefTy - LLVM for:
3870 // struct _super_message_ref_t {
3871 // SUPER_IMP messenger;
3872 // SEL name;
3873 // };
3874 SuperMessageRefTy = llvm::StructType::get(ImpnfABITy,
3875 SelectorPtrTy,
3876 NULL);
3877 CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
3878
3879 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
3880 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
3881
3882 // id objc_msgSend_fixup (id, struct message_ref_t*, ...)
3883 Params.clear();
3884 Params.push_back(ObjectPtrTy);
3885 Params.push_back(MessageRefPtrTy);
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00003886 MessengerTy = llvm::FunctionType::get(ObjectPtrTy,
3887 Params,
3888 true);
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003889 MessageSendFixupFn =
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00003890 CGM.CreateRuntimeFunction(MessengerTy,
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003891 "objc_msgSend_fixup");
3892
3893 // id objc_msgSend_fpret_fixup (id, struct message_ref_t*, ...)
3894 MessageSendFpretFixupFn =
3895 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3896 Params,
3897 true),
3898 "objc_msgSend_fpret_fixup");
3899
3900 // id objc_msgSend_stret_fixup (id, struct message_ref_t*, ...)
3901 MessageSendStretFixupFn =
3902 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3903 Params,
3904 true),
3905 "objc_msgSend_stret_fixup");
3906
3907 // id objc_msgSendId_fixup (id, struct message_ref_t*, ...)
3908 MessageSendIdFixupFn =
3909 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3910 Params,
3911 true),
3912 "objc_msgSendId_fixup");
3913
3914
3915 // id objc_msgSendId_stret_fixup (id, struct message_ref_t*, ...)
3916 MessageSendIdStretFixupFn =
3917 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3918 Params,
3919 true),
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00003920 "objc_msgSendId_stret_fixup");
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003921
3922 // id objc_msgSendSuper2_fixup (struct objc_super *,
3923 // struct _super_message_ref_t*, ...)
3924 Params.clear();
3925 Params.push_back(SuperPtrTy);
3926 Params.push_back(SuperMessageRefPtrTy);
3927 MessageSendSuper2FixupFn =
3928 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3929 Params,
3930 true),
3931 "objc_msgSendSuper2_fixup");
3932
3933
3934 // id objc_msgSendSuper2_stret_fixup (struct objc_super *,
3935 // struct _super_message_ref_t*, ...)
3936 MessageSendSuper2StretFixupFn =
3937 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3938 Params,
3939 true),
3940 "objc_msgSendSuper2_stret_fixup");
Daniel Dunbar75de89f2009-02-24 07:47:38 +00003941
3942 Params.clear();
Daniel Dunbar9c285e72009-03-01 04:46:24 +00003943
3944 // struct objc_typeinfo {
3945 // const void** vtable; // objc_ehtype_vtable + 2
3946 // const char* name; // c++ typeinfo string
3947 // Class cls;
3948 // };
3949 EHTypeTy = llvm::StructType::get(llvm::PointerType::getUnqual(Int8PtrTy),
3950 Int8PtrTy,
3951 ClassnfABIPtrTy,
3952 NULL);
Daniel Dunbarc0318b22009-03-02 06:08:11 +00003953 CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
Daniel Dunbar9c285e72009-03-01 04:46:24 +00003954 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00003955}
3956
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003957llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
3958 FinishNonFragileABIModule();
3959
3960 return NULL;
3961}
3962
3963void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
3964 // nonfragile abi has no module definition.
Fariborz Jahanian11c93dd2009-01-30 20:55:31 +00003965
3966 // Build list of all implemented classe addresses in array
3967 // L_OBJC_LABEL_CLASS_$.
3968 // FIXME. Also generate in L_OBJC_LABEL_NONLAZY_CLASS_$
3969 // list of 'nonlazy' implementations (defined as those with a +load{}
3970 // method!!).
3971 unsigned NumClasses = DefinedClasses.size();
3972 if (NumClasses) {
3973 std::vector<llvm::Constant*> Symbols(NumClasses);
3974 for (unsigned i=0; i<NumClasses; i++)
3975 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
3976 ObjCTypes.Int8PtrTy);
3977 llvm::Constant* Init =
3978 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3979 NumClasses),
3980 Symbols);
3981
3982 llvm::GlobalVariable *GV =
3983 new llvm::GlobalVariable(Init->getType(), false,
3984 llvm::GlobalValue::InternalLinkage,
3985 Init,
3986 "\01L_OBJC_LABEL_CLASS_$",
3987 &CGM.getModule());
Daniel Dunbar56756c32009-03-09 22:18:41 +00003988 GV->setAlignment(8);
Fariborz Jahanian11c93dd2009-01-30 20:55:31 +00003989 GV->setSection("__DATA, __objc_classlist, regular, no_dead_strip");
3990 UsedGlobals.push_back(GV);
3991 }
3992
3993 // Build list of all implemented category addresses in array
3994 // L_OBJC_LABEL_CATEGORY_$.
3995 // FIXME. Also generate in L_OBJC_LABEL_NONLAZY_CATEGORY_$
3996 // list of 'nonlazy' category implementations (defined as those with a +load{}
3997 // method!!).
3998 unsigned NumCategory = DefinedCategories.size();
3999 if (NumCategory) {
4000 std::vector<llvm::Constant*> Symbols(NumCategory);
4001 for (unsigned i=0; i<NumCategory; i++)
4002 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedCategories[i],
4003 ObjCTypes.Int8PtrTy);
4004 llvm::Constant* Init =
4005 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
4006 NumCategory),
4007 Symbols);
4008
4009 llvm::GlobalVariable *GV =
4010 new llvm::GlobalVariable(Init->getType(), false,
4011 llvm::GlobalValue::InternalLinkage,
4012 Init,
4013 "\01L_OBJC_LABEL_CATEGORY_$",
4014 &CGM.getModule());
Daniel Dunbar56756c32009-03-09 22:18:41 +00004015 GV->setAlignment(8);
Fariborz Jahanian11c93dd2009-01-30 20:55:31 +00004016 GV->setSection("__DATA, __objc_catlist, regular, no_dead_strip");
4017 UsedGlobals.push_back(GV);
4018 }
4019
Fariborz Jahanian5b2f5502009-01-30 22:07:48 +00004020 // static int L_OBJC_IMAGE_INFO[2] = { 0, flags };
4021 // FIXME. flags can be 0 | 1 | 2 | 6. For now just use 0
4022 std::vector<llvm::Constant*> Values(2);
4023 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, 0);
Fariborz Jahanian4d7933a2009-02-24 21:08:09 +00004024 unsigned int flags = 0;
Fariborz Jahanian27f58962009-02-24 23:34:44 +00004025 // FIXME: Fix and continue?
4026 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
4027 flags |= eImageInfo_GarbageCollected;
4028 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
4029 flags |= eImageInfo_GCOnly;
Fariborz Jahanian4d7933a2009-02-24 21:08:09 +00004030 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
Fariborz Jahanian5b2f5502009-01-30 22:07:48 +00004031 llvm::Constant* Init = llvm::ConstantArray::get(
4032 llvm::ArrayType::get(ObjCTypes.IntTy, 2),
4033 Values);
4034 llvm::GlobalVariable *IMGV =
4035 new llvm::GlobalVariable(Init->getType(), false,
4036 llvm::GlobalValue::InternalLinkage,
4037 Init,
4038 "\01L_OBJC_IMAGE_INFO",
4039 &CGM.getModule());
4040 IMGV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip");
4041 UsedGlobals.push_back(IMGV);
4042
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004043 std::vector<llvm::Constant*> Used;
Fariborz Jahanianab438842009-04-14 18:41:56 +00004044
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004045 for (std::vector<llvm::GlobalVariable*>::iterator i = UsedGlobals.begin(),
4046 e = UsedGlobals.end(); i != e; ++i) {
4047 Used.push_back(llvm::ConstantExpr::getBitCast(*i, ObjCTypes.Int8PtrTy));
4048 }
Fariborz Jahanianab438842009-04-14 18:41:56 +00004049
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004050 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Used.size());
4051 llvm::GlobalValue *GV =
4052 new llvm::GlobalVariable(AT, false,
4053 llvm::GlobalValue::AppendingLinkage,
4054 llvm::ConstantArray::get(AT, Used),
4055 "llvm.used",
4056 &CGM.getModule());
4057
4058 GV->setSection("llvm.metadata");
4059
4060}
4061
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004062// Metadata flags
4063enum MetaDataDlags {
4064 CLS = 0x0,
4065 CLS_META = 0x1,
4066 CLS_ROOT = 0x2,
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004067 OBJC2_CLS_HIDDEN = 0x10,
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004068 CLS_EXCEPTION = 0x20
4069};
4070/// BuildClassRoTInitializer - generate meta-data for:
4071/// struct _class_ro_t {
4072/// uint32_t const flags;
4073/// uint32_t const instanceStart;
4074/// uint32_t const instanceSize;
4075/// uint32_t const reserved; // only when building for 64bit targets
4076/// const uint8_t * const ivarLayout;
4077/// const char *const name;
4078/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004079/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004080/// const struct _ivar_list_t *const ivars;
4081/// const uint8_t * const weakIvarLayout;
4082/// const struct _prop_list_t * const properties;
4083/// }
4084///
4085llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
4086 unsigned flags,
4087 unsigned InstanceStart,
4088 unsigned InstanceSize,
4089 const ObjCImplementationDecl *ID) {
4090 std::string ClassName = ID->getNameAsString();
4091 std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
4092 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
4093 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
4094 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
4095 // FIXME. For 64bit targets add 0 here.
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004096 // FIXME. ivarLayout is currently null!
Fariborz Jahanian7e052812009-04-21 18:33:06 +00004097 // Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4098 // : BuildIvarLayout(ID, true);
Fariborz Jahanian7345eba2009-03-05 19:17:31 +00004099 Values[ 3] = GetIvarLayoutName(0, ObjCTypes);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004100 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004101 // const struct _method_list_t * const baseMethods;
4102 std::vector<llvm::Constant*> Methods;
4103 std::string MethodListName("\01l_OBJC_$_");
4104 if (flags & CLS_META) {
4105 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
4106 for (ObjCImplementationDecl::classmeth_iterator i = ID->classmeth_begin(),
4107 e = ID->classmeth_end(); i != e; ++i) {
4108 // Class methods should always be defined.
4109 Methods.push_back(GetMethodConstant(*i));
4110 }
4111 } else {
4112 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
4113 for (ObjCImplementationDecl::instmeth_iterator i = ID->instmeth_begin(),
4114 e = ID->instmeth_end(); i != e; ++i) {
4115 // Instance methods should always be defined.
4116 Methods.push_back(GetMethodConstant(*i));
4117 }
Fariborz Jahanian78355ec2009-01-28 22:46:49 +00004118 for (ObjCImplementationDecl::propimpl_iterator i = ID->propimpl_begin(),
4119 e = ID->propimpl_end(); i != e; ++i) {
4120 ObjCPropertyImplDecl *PID = *i;
4121
4122 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
4123 ObjCPropertyDecl *PD = PID->getPropertyDecl();
4124
4125 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
4126 if (llvm::Constant *C = GetMethodConstant(MD))
4127 Methods.push_back(C);
4128 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
4129 if (llvm::Constant *C = GetMethodConstant(MD))
4130 Methods.push_back(C);
4131 }
4132 }
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004133 }
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004134 Values[ 5] = EmitMethodList(MethodListName,
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004135 "__DATA, __objc_const", Methods);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004136
4137 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4138 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
4139 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
4140 + OID->getNameAsString(),
4141 OID->protocol_begin(),
4142 OID->protocol_end());
4143
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004144 if (flags & CLS_META)
4145 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
4146 else
4147 Values[ 7] = EmitIvarList(ID);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004148 // FIXME. weakIvarLayout is currently null.
Fariborz Jahanian7e052812009-04-21 18:33:06 +00004149 // Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
4150 // : BuildIvarLayout(ID, false);
Fariborz Jahaniand0e808a2009-03-12 22:50:49 +00004151 Values[ 8] = GetIvarLayoutName(0, ObjCTypes);
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00004152 if (flags & CLS_META)
4153 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
4154 else
4155 Values[ 9] =
4156 EmitPropertyList(
4157 "\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
4158 ID, ID->getClassInterface(), ObjCTypes);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004159 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
4160 Values);
4161 llvm::GlobalVariable *CLASS_RO_GV =
4162 new llvm::GlobalVariable(ObjCTypes.ClassRonfABITy, false,
4163 llvm::GlobalValue::InternalLinkage,
4164 Init,
4165 (flags & CLS_META) ?
4166 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
4167 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName,
4168 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004169 CLASS_RO_GV->setAlignment(
4170 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004171 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004172 return CLASS_RO_GV;
Fariborz Jahanianc98c87b2009-01-26 22:58:07 +00004173
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004174}
4175
4176/// BuildClassMetaData - This routine defines that to-level meta-data
4177/// for the given ClassName for:
4178/// struct _class_t {
4179/// struct _class_t *isa;
4180/// struct _class_t * const superclass;
4181/// void *cache;
4182/// IMP *vtable;
4183/// struct class_ro_t *ro;
4184/// }
4185///
Fariborz Jahanian06726462009-01-24 21:21:53 +00004186llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
4187 std::string &ClassName,
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004188 llvm::Constant *IsAGV,
4189 llvm::Constant *SuperClassGV,
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00004190 llvm::Constant *ClassRoGV,
4191 bool HiddenVisibility) {
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004192 std::vector<llvm::Constant*> Values(5);
4193 Values[0] = IsAGV;
Fariborz Jahanian06726462009-01-24 21:21:53 +00004194 Values[1] = SuperClassGV
4195 ? SuperClassGV
4196 : llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004197 Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
4198 Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
4199 Values[4] = ClassRoGV; // &CLASS_RO_GV
4200 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
4201 Values);
Daniel Dunbarabbda222009-03-01 04:40:10 +00004202 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
4203 GV->setInitializer(Init);
Fariborz Jahanian7c891592009-01-31 01:07:39 +00004204 GV->setSection("__DATA, __objc_data");
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004205 GV->setAlignment(
4206 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00004207 if (HiddenVisibility)
4208 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian06726462009-01-24 21:21:53 +00004209 return GV;
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004210}
4211
Daniel Dunbar72878722009-04-20 20:18:54 +00004212/// countInheritedIvars - count number of ivars in class and its super class(s)
4213///
4214static int countInheritedIvars(const ObjCInterfaceDecl *OI,
4215 ASTContext &Context) {
4216 int count = 0;
4217 if (!OI)
4218 return 0;
4219 const ObjCInterfaceDecl *SuperClass = OI->getSuperClass();
4220 if (SuperClass)
4221 count += countInheritedIvars(SuperClass, Context);
4222 for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
4223 E = OI->ivar_end(); I != E; ++I)
4224 ++count;
4225 // look into properties.
4226 for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(Context),
4227 E = OI->prop_end(Context); I != E; ++I) {
4228 if ((*I)->getPropertyIvarDecl())
4229 ++count;
4230 }
4231 return count;
4232}
4233
Daniel Dunbarecb5d402009-04-19 23:41:48 +00004234void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCInterfaceDecl *OID,
4235 uint32_t &InstanceStart,
4236 uint32_t &InstanceSize) {
Daniel Dunbardbc8af72009-04-21 21:41:56 +00004237 assert(!OID->isForwardDecl() && "Invalid interface decl!");
Daniel Dunbarecb5d402009-04-19 23:41:48 +00004238 const llvm::StructLayout *Layout = GetInterfaceDeclStructLayout(OID);
4239
Daniel Dunbarde585722009-04-20 07:18:49 +00004240 int countSuperClassIvars = countInheritedIvars(OID->getSuperClass(),
4241 CGM.getContext());
4242 const RecordDecl *RD = CGM.getContext().addRecordToClass(OID);
4243 RecordDecl::field_iterator firstField = RD->field_begin(CGM.getContext());
4244 RecordDecl::field_iterator lastField = RD->field_end(CGM.getContext());
4245 while (countSuperClassIvars-- > 0) {
4246 lastField = firstField;
4247 ++firstField;
4248 }
Daniel Dunbarecb5d402009-04-19 23:41:48 +00004249
4250 for (RecordDecl::field_iterator e = RD->field_end(CGM.getContext()),
4251 ifield = firstField; ifield != e; ++ifield)
4252 lastField = ifield;
4253
4254 InstanceStart = InstanceSize = 0;
4255 if (lastField != RD->field_end(CGM.getContext())) {
4256 FieldDecl *Field = *lastField;
4257 const llvm::Type *FieldTy =
4258 CGM.getTypes().ConvertTypeForMem(Field->getType());
4259 unsigned Size = CGM.getTargetData().getTypePaddedSize(FieldTy);
4260 InstanceSize = GetIvarBaseOffset(Layout, Field) + Size;
4261 if (firstField == RD->field_end(CGM.getContext()))
4262 InstanceStart = InstanceSize;
4263 else {
4264 Field = *firstField;
4265 InstanceStart = GetIvarBaseOffset(Layout, Field);
4266 }
4267 }
4268}
4269
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004270void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
4271 std::string ClassName = ID->getNameAsString();
4272 if (!ObjCEmptyCacheVar) {
4273 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004274 ObjCTypes.CacheTy,
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004275 false,
4276 llvm::GlobalValue::ExternalLinkage,
4277 0,
Daniel Dunbara2d275d2009-04-07 05:48:37 +00004278 "_objc_empty_cache",
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004279 &CGM.getModule());
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004280
4281 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004282 ObjCTypes.ImpnfABITy,
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004283 false,
4284 llvm::GlobalValue::ExternalLinkage,
4285 0,
Daniel Dunbara2d275d2009-04-07 05:48:37 +00004286 "_objc_empty_vtable",
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004287 &CGM.getModule());
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004288 }
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004289 assert(ID->getClassInterface() &&
4290 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Daniel Dunbar72878722009-04-20 20:18:54 +00004291 // FIXME: Is this correct (that meta class size is never computed)?
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004292 uint32_t InstanceStart =
4293 CGM.getTargetData().getTypePaddedSize(ObjCTypes.ClassnfABITy);
4294 uint32_t InstanceSize = InstanceStart;
4295 uint32_t flags = CLS_META;
Daniel Dunbara2d275d2009-04-07 05:48:37 +00004296 std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
4297 std::string ObjCClassName(getClassSymbolPrefix());
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004298
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004299 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004300
Daniel Dunbar8394fda2009-04-14 06:00:08 +00004301 bool classIsHidden =
4302 CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden;
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00004303 if (classIsHidden)
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004304 flags |= OBJC2_CLS_HIDDEN;
4305 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004306 // class is root
4307 flags |= CLS_ROOT;
Daniel Dunbarabbda222009-03-01 04:40:10 +00004308 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
Fariborz Jahanianab438842009-04-14 18:41:56 +00004309 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004310 } else {
Fariborz Jahanian06726462009-01-24 21:21:53 +00004311 // Has a root. Current class is not a root.
Fariborz Jahanian514c63b2009-02-26 18:23:47 +00004312 const ObjCInterfaceDecl *Root = ID->getClassInterface();
4313 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
4314 Root = Super;
Fariborz Jahanianab438842009-04-14 18:41:56 +00004315 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Fariborz Jahanian514c63b2009-02-26 18:23:47 +00004316 // work on super class metadata symbol.
4317 std::string SuperClassName =
4318 ObjCMetaClassName + ID->getClassInterface()->getSuperClass()->getNameAsString();
Fariborz Jahanianab438842009-04-14 18:41:56 +00004319 SuperClassGV = GetClassGlobal(SuperClassName);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00004320 }
4321 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
4322 InstanceStart,
4323 InstanceSize,ID);
Fariborz Jahanian06726462009-01-24 21:21:53 +00004324 std::string TClassName = ObjCMetaClassName + ClassName;
4325 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00004326 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
4327 classIsHidden);
Daniel Dunbara2d275d2009-04-07 05:48:37 +00004328
Fariborz Jahanian06726462009-01-24 21:21:53 +00004329 // Metadata for the class
4330 flags = CLS;
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00004331 if (classIsHidden)
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004332 flags |= OBJC2_CLS_HIDDEN;
Daniel Dunbarc2129532009-04-08 04:21:03 +00004333
4334 if (hasObjCExceptionAttribute(ID->getClassInterface()))
4335 flags |= CLS_EXCEPTION;
4336
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004337 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian06726462009-01-24 21:21:53 +00004338 flags |= CLS_ROOT;
4339 SuperClassGV = 0;
Chris Lattner9fe470d2009-04-19 06:02:28 +00004340 } else {
Fariborz Jahanian06726462009-01-24 21:21:53 +00004341 // Has a root. Current class is not a root.
Fariborz Jahanian514c63b2009-02-26 18:23:47 +00004342 std::string RootClassName =
Fariborz Jahanian06726462009-01-24 21:21:53 +00004343 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarabbda222009-03-01 04:40:10 +00004344 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Fariborz Jahanian06726462009-01-24 21:21:53 +00004345 }
Daniel Dunbarecb5d402009-04-19 23:41:48 +00004346 GetClassSizeInfo(ID->getClassInterface(), InstanceStart, InstanceSize);
Fariborz Jahanian06726462009-01-24 21:21:53 +00004347 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahanianddd2fdd2009-01-24 23:43:01 +00004348 InstanceStart,
4349 InstanceSize,
4350 ID);
Fariborz Jahanian06726462009-01-24 21:21:53 +00004351
4352 TClassName = ObjCClassName + ClassName;
Fariborz Jahanian11c93dd2009-01-30 20:55:31 +00004353 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00004354 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
4355 classIsHidden);
Fariborz Jahanian11c93dd2009-01-30 20:55:31 +00004356 DefinedClasses.push_back(ClassMD);
Daniel Dunbarc2129532009-04-08 04:21:03 +00004357
4358 // Force the definition of the EHType if necessary.
4359 if (flags & CLS_EXCEPTION)
4360 GetInterfaceEHType(ID->getClassInterface(), true);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00004361}
4362
Fariborz Jahanian5d13ab12009-01-30 18:58:59 +00004363/// GenerateProtocolRef - This routine is called to generate code for
4364/// a protocol reference expression; as in:
4365/// @code
4366/// @protocol(Proto1);
4367/// @endcode
4368/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
4369/// which will hold address of the protocol meta-data.
4370///
4371llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
4372 const ObjCProtocolDecl *PD) {
4373
Fariborz Jahaniand3243322009-04-10 18:47:34 +00004374 // This routine is called for @protocol only. So, we must build definition
4375 // of protocol's meta-data (not a reference to it!)
4376 //
4377 llvm::Constant *Init = llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
Fariborz Jahanian5d13ab12009-01-30 18:58:59 +00004378 ObjCTypes.ExternalProtocolPtrTy);
4379
4380 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
4381 ProtocolName += PD->getNameAsCString();
4382
4383 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
4384 if (PTGV)
4385 return Builder.CreateLoad(PTGV, false, "tmp");
4386 PTGV = new llvm::GlobalVariable(
4387 Init->getType(), false,
Mike Stump36dbf222009-03-07 16:33:28 +00004388 llvm::GlobalValue::WeakAnyLinkage,
Fariborz Jahanian5d13ab12009-01-30 18:58:59 +00004389 Init,
4390 ProtocolName,
4391 &CGM.getModule());
4392 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
4393 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4394 UsedGlobals.push_back(PTGV);
4395 return Builder.CreateLoad(PTGV, false, "tmp");
4396}
4397
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00004398/// GenerateCategory - Build metadata for a category implementation.
4399/// struct _category_t {
4400/// const char * const name;
4401/// struct _class_t *const cls;
4402/// const struct _method_list_t * const instance_methods;
4403/// const struct _method_list_t * const class_methods;
4404/// const struct _protocol_list_t * const protocols;
4405/// const struct _prop_list_t * const properties;
4406/// }
4407///
4408void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD)
4409{
4410 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanianc98c87b2009-01-26 22:58:07 +00004411 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
4412 std::string ExtCatName(Prefix + Interface->getNameAsString()+
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00004413 "_$_" + OCD->getNameAsString());
Daniel Dunbara2d275d2009-04-07 05:48:37 +00004414 std::string ExtClassName(getClassSymbolPrefix() +
4415 Interface->getNameAsString());
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00004416
4417 std::vector<llvm::Constant*> Values(6);
4418 Values[0] = GetClassName(OCD->getIdentifier());
4419 // meta-class entry symbol
Daniel Dunbarabbda222009-03-01 04:40:10 +00004420 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00004421 Values[1] = ClassGV;
Fariborz Jahanianc98c87b2009-01-26 22:58:07 +00004422 std::vector<llvm::Constant*> Methods;
4423 std::string MethodListName(Prefix);
4424 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
4425 "_$_" + OCD->getNameAsString();
4426
4427 for (ObjCCategoryImplDecl::instmeth_iterator i = OCD->instmeth_begin(),
4428 e = OCD->instmeth_end(); i != e; ++i) {
4429 // Instance methods should always be defined.
4430 Methods.push_back(GetMethodConstant(*i));
4431 }
4432
4433 Values[2] = EmitMethodList(MethodListName,
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004434 "__DATA, __objc_const",
Fariborz Jahanianc98c87b2009-01-26 22:58:07 +00004435 Methods);
4436
4437 MethodListName = Prefix;
4438 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
4439 OCD->getNameAsString();
4440 Methods.clear();
4441 for (ObjCCategoryImplDecl::classmeth_iterator i = OCD->classmeth_begin(),
4442 e = OCD->classmeth_end(); i != e; ++i) {
4443 // Class methods should always be defined.
4444 Methods.push_back(GetMethodConstant(*i));
4445 }
4446
4447 Values[3] = EmitMethodList(MethodListName,
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004448 "__DATA, __objc_const",
Fariborz Jahanianc98c87b2009-01-26 22:58:07 +00004449 Methods);
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00004450 const ObjCCategoryDecl *Category =
4451 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahanian8c7904b2009-02-13 17:52:22 +00004452 if (Category) {
4453 std::string ExtName(Interface->getNameAsString() + "_$_" +
4454 OCD->getNameAsString());
4455 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
4456 + Interface->getNameAsString() + "_$_"
4457 + Category->getNameAsString(),
4458 Category->protocol_begin(),
4459 Category->protocol_end());
4460 Values[5] =
4461 EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_") + ExtName,
4462 OCD, Category, ObjCTypes);
4463 }
4464 else {
4465 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
4466 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
4467 }
4468
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00004469 llvm::Constant *Init =
4470 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
4471 Values);
4472 llvm::GlobalVariable *GCATV
4473 = new llvm::GlobalVariable(ObjCTypes.CategorynfABITy,
4474 false,
4475 llvm::GlobalValue::InternalLinkage,
4476 Init,
4477 ExtCatName,
4478 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004479 GCATV->setAlignment(
4480 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004481 GCATV->setSection("__DATA, __objc_const");
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00004482 UsedGlobals.push_back(GCATV);
4483 DefinedCategories.push_back(GCATV);
4484}
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004485
4486/// GetMethodConstant - Return a struct objc_method constant for the
4487/// given method if it has been defined. The result is null if the
4488/// method has not been defined. The return value has type MethodPtrTy.
4489llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
4490 const ObjCMethodDecl *MD) {
4491 // FIXME: Use DenseMap::lookup
4492 llvm::Function *Fn = MethodDefinitions[MD];
4493 if (!Fn)
4494 return 0;
4495
4496 std::vector<llvm::Constant*> Method(3);
4497 Method[0] =
4498 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
4499 ObjCTypes.SelectorPtrTy);
4500 Method[1] = GetMethodVarType(MD);
4501 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
4502 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
4503}
4504
4505/// EmitMethodList - Build meta-data for method declarations
4506/// struct _method_list_t {
4507/// uint32_t entsize; // sizeof(struct _objc_method)
4508/// uint32_t method_count;
4509/// struct _objc_method method_list[method_count];
4510/// }
4511///
4512llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(
4513 const std::string &Name,
4514 const char *Section,
4515 const ConstantVector &Methods) {
4516 // Return null for empty list.
4517 if (Methods.empty())
4518 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
4519
4520 std::vector<llvm::Constant*> Values(3);
4521 // sizeof(struct _objc_method)
4522 unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.MethodTy);
4523 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4524 // method_count
4525 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
4526 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
4527 Methods.size());
4528 Values[2] = llvm::ConstantArray::get(AT, Methods);
4529 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
4530
4531 llvm::GlobalVariable *GV =
4532 new llvm::GlobalVariable(Init->getType(), false,
4533 llvm::GlobalValue::InternalLinkage,
4534 Init,
4535 Name,
4536 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004537 GV->setAlignment(
4538 CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004539 GV->setSection(Section);
4540 UsedGlobals.push_back(GV);
4541 return llvm::ConstantExpr::getBitCast(GV,
4542 ObjCTypes.MethodListnfABIPtrTy);
4543}
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004544
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004545/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
4546/// the given ivar.
4547///
4548llvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(
Fariborz Jahaniana09a5142009-02-12 18:51:23 +00004549 const ObjCInterfaceDecl *ID,
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004550 const ObjCIvarDecl *Ivar) {
Daniel Dunbar07d204a2009-04-19 00:31:15 +00004551 std::string Name = "OBJC_IVAR_$_" +
Douglas Gregorc55b0b02009-04-09 21:40:53 +00004552 getInterfaceDeclForIvar(ID, Ivar, CGM.getContext())->getNameAsString() +
4553 '.' + Ivar->getNameAsString();
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004554 llvm::GlobalVariable *IvarOffsetGV =
4555 CGM.getModule().getGlobalVariable(Name);
4556 if (!IvarOffsetGV)
4557 IvarOffsetGV =
4558 new llvm::GlobalVariable(ObjCTypes.LongTy,
4559 false,
4560 llvm::GlobalValue::ExternalLinkage,
4561 0,
4562 Name,
4563 &CGM.getModule());
4564 return IvarOffsetGV;
4565}
4566
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004567llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar(
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004568 const ObjCInterfaceDecl *ID,
Fariborz Jahanian150f7732009-01-28 01:36:42 +00004569 const ObjCIvarDecl *Ivar,
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004570 unsigned long int Offset) {
Daniel Dunbar0438ff42009-04-19 00:44:02 +00004571 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
4572 IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
4573 Offset));
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004574 IvarOffsetGV->setAlignment(
Fariborz Jahanian55343922009-02-03 00:09:52 +00004575 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy));
Daniel Dunbar0438ff42009-04-19 00:44:02 +00004576
4577 // FIXME: This matches gcc, but shouldn't the visibility be set on
4578 // the use as well (i.e., in ObjCIvarOffsetVariable).
4579 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
4580 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
4581 CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden)
Fariborz Jahanian150f7732009-01-28 01:36:42 +00004582 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbar8394fda2009-04-14 06:00:08 +00004583 else
Fariborz Jahanian745fd892009-04-06 18:30:00 +00004584 IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004585 IvarOffsetGV->setSection("__DATA, __objc_const");
Fariborz Jahanian55343922009-02-03 00:09:52 +00004586 return IvarOffsetGV;
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004587}
4588
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004589/// EmitIvarList - Emit the ivar list for the given
Daniel Dunbar3c190812009-04-18 08:51:00 +00004590/// implementation. The return value has type
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004591/// IvarListnfABIPtrTy.
4592/// struct _ivar_t {
4593/// unsigned long int *offset; // pointer to ivar offset location
4594/// char *name;
4595/// char *type;
4596/// uint32_t alignment;
4597/// uint32_t size;
4598/// }
4599/// struct _ivar_list_t {
4600/// uint32 entsize; // sizeof(struct _ivar_t)
4601/// uint32 count;
4602/// struct _iver_t list[count];
4603/// }
4604///
Daniel Dunbar356f0742009-04-20 06:54:31 +00004605
4606void CGObjCCommonMac::GetNamedIvarList(const ObjCInterfaceDecl *OID,
4607 llvm::SmallVector<ObjCIvarDecl*, 16> &Res) const {
4608 for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
4609 E = OID->ivar_end(); I != E; ++I) {
4610 // Ignore unnamed bit-fields.
4611 if (!(*I)->getDeclName())
4612 continue;
4613
4614 Res.push_back(*I);
4615 }
4616
4617 for (ObjCInterfaceDecl::prop_iterator I = OID->prop_begin(CGM.getContext()),
4618 E = OID->prop_end(CGM.getContext()); I != E; ++I)
4619 if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl())
4620 Res.push_back(IV);
4621}
4622
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004623llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
4624 const ObjCImplementationDecl *ID) {
4625
4626 std::vector<llvm::Constant*> Ivars, Ivar(5);
4627
4628 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4629 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
4630
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004631 // FIXME. Consolidate this with similar code in GenerateClass.
Fariborz Jahanian6d49ab62009-03-11 21:42:00 +00004632 const llvm::StructLayout *Layout = GetInterfaceDeclStructLayout(OID);
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00004633
Daniel Dunbar1748ac32009-04-20 00:33:43 +00004634 // Collect declared and synthesized ivars in a small vector.
Fariborz Jahanianfbf44642009-03-31 18:11:23 +00004635 llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
Daniel Dunbar356f0742009-04-20 06:54:31 +00004636 GetNamedIvarList(OID, OIvars);
Fariborz Jahanian84c45692009-04-01 19:37:34 +00004637
Daniel Dunbar356f0742009-04-20 06:54:31 +00004638 for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
4639 ObjCIvarDecl *IVD = OIvars[i];
4640 const FieldDecl *Field = OID->lookupFieldDeclForIvar(CGM.getContext(), IVD);
Daniel Dunbard73f5f22009-04-20 05:53:40 +00004641 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
Daniel Dunbar1cfb5192009-04-19 02:03:42 +00004642 GetIvarBaseOffset(Layout, Field));
Daniel Dunbard73f5f22009-04-20 05:53:40 +00004643 Ivar[1] = GetMethodVarName(Field->getIdentifier());
Devang Patel593a07a2009-03-04 18:21:39 +00004644 Ivar[2] = GetMethodVarType(Field);
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004645 const llvm::Type *FieldTy =
4646 CGM.getTypes().ConvertTypeForMem(Field->getType());
4647 unsigned Size = CGM.getTargetData().getTypePaddedSize(FieldTy);
4648 unsigned Align = CGM.getContext().getPreferredTypeAlign(
4649 Field->getType().getTypePtr()) >> 3;
4650 Align = llvm::Log2_32(Align);
4651 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Daniel Dunbar1748ac32009-04-20 00:33:43 +00004652 // NOTE. Size of a bitfield does not match gcc's, because of the
4653 // way bitfields are treated special in each. But I am told that
4654 // 'size' for bitfield ivars is ignored by the runtime so it does
4655 // not matter. If it matters, there is enough info to get the
4656 // bitfield right!
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004657 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4658 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
4659 }
4660 // Return null for empty list.
4661 if (Ivars.empty())
4662 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
4663 std::vector<llvm::Constant*> Values(3);
4664 unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.IvarnfABITy);
4665 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4666 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
4667 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
4668 Ivars.size());
4669 Values[2] = llvm::ConstantArray::get(AT, Ivars);
4670 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
4671 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
4672 llvm::GlobalVariable *GV =
4673 new llvm::GlobalVariable(Init->getType(), false,
4674 llvm::GlobalValue::InternalLinkage,
4675 Init,
4676 Prefix + OID->getNameAsString(),
4677 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004678 GV->setAlignment(
4679 CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004680 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004681
4682 UsedGlobals.push_back(GV);
4683 return llvm::ConstantExpr::getBitCast(GV,
4684 ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004685}
4686
4687llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
4688 const ObjCProtocolDecl *PD) {
4689 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
4690
4691 if (!Entry) {
4692 // We use the initializer as a marker of whether this is a forward
4693 // reference or not. At module finalization we add the empty
4694 // contents for protocols which were referenced but never defined.
4695 Entry =
4696 new llvm::GlobalVariable(ObjCTypes.ProtocolnfABITy, false,
4697 llvm::GlobalValue::ExternalLinkage,
4698 0,
4699 "\01l_OBJC_PROTOCOL_$_" + PD->getNameAsString(),
4700 &CGM.getModule());
4701 Entry->setSection("__DATA,__datacoal_nt,coalesced");
4702 UsedGlobals.push_back(Entry);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004703 }
4704
4705 return Entry;
4706}
4707
4708/// GetOrEmitProtocol - Generate the protocol meta-data:
4709/// @code
4710/// struct _protocol_t {
4711/// id isa; // NULL
4712/// const char * const protocol_name;
4713/// const struct _protocol_list_t * protocol_list; // super protocols
4714/// const struct method_list_t * const instance_methods;
4715/// const struct method_list_t * const class_methods;
4716/// const struct method_list_t *optionalInstanceMethods;
4717/// const struct method_list_t *optionalClassMethods;
4718/// const struct _prop_list_t * properties;
4719/// const uint32_t size; // sizeof(struct _protocol_t)
4720/// const uint32_t flags; // = 0
4721/// }
4722/// @endcode
4723///
4724
4725llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
4726 const ObjCProtocolDecl *PD) {
4727 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
4728
4729 // Early exit if a defining object has already been generated.
4730 if (Entry && Entry->hasInitializer())
4731 return Entry;
4732
4733 const char *ProtocolName = PD->getNameAsCString();
4734
4735 // Construct method lists.
4736 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
4737 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
Douglas Gregorc55b0b02009-04-09 21:40:53 +00004738 for (ObjCProtocolDecl::instmeth_iterator
4739 i = PD->instmeth_begin(CGM.getContext()),
4740 e = PD->instmeth_end(CGM.getContext());
4741 i != e; ++i) {
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004742 ObjCMethodDecl *MD = *i;
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004743 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004744 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
4745 OptInstanceMethods.push_back(C);
4746 } else {
4747 InstanceMethods.push_back(C);
4748 }
4749 }
4750
Douglas Gregorc55b0b02009-04-09 21:40:53 +00004751 for (ObjCProtocolDecl::classmeth_iterator
4752 i = PD->classmeth_begin(CGM.getContext()),
4753 e = PD->classmeth_end(CGM.getContext());
4754 i != e; ++i) {
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004755 ObjCMethodDecl *MD = *i;
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004756 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004757 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
4758 OptClassMethods.push_back(C);
4759 } else {
4760 ClassMethods.push_back(C);
4761 }
4762 }
4763
4764 std::vector<llvm::Constant*> Values(10);
4765 // isa is NULL
4766 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
4767 Values[1] = GetClassName(PD->getIdentifier());
4768 Values[2] = EmitProtocolList(
4769 "\01l_OBJC_$_PROTOCOL_REFS_" + PD->getNameAsString(),
4770 PD->protocol_begin(),
4771 PD->protocol_end());
4772
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004773 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004774 + PD->getNameAsString(),
4775 "__DATA, __objc_const",
4776 InstanceMethods);
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004777 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004778 + PD->getNameAsString(),
4779 "__DATA, __objc_const",
4780 ClassMethods);
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004781 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004782 + PD->getNameAsString(),
4783 "__DATA, __objc_const",
4784 OptInstanceMethods);
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004785 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004786 + PD->getNameAsString(),
4787 "__DATA, __objc_const",
4788 OptClassMethods);
4789 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getNameAsString(),
4790 0, PD, ObjCTypes);
4791 uint32_t Size =
4792 CGM.getTargetData().getTypePaddedSize(ObjCTypes.ProtocolnfABITy);
4793 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4794 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
4795 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
4796 Values);
4797
4798 if (Entry) {
4799 // Already created, fix the linkage and update the initializer.
Mike Stump36dbf222009-03-07 16:33:28 +00004800 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004801 Entry->setInitializer(Init);
4802 } else {
4803 Entry =
4804 new llvm::GlobalVariable(ObjCTypes.ProtocolnfABITy, false,
Mike Stump36dbf222009-03-07 16:33:28 +00004805 llvm::GlobalValue::WeakAnyLinkage,
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004806 Init,
4807 std::string("\01l_OBJC_PROTOCOL_$_")+ProtocolName,
4808 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004809 Entry->setAlignment(
4810 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004811 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004812 }
Fariborz Jahanianfd02a662009-01-29 20:10:59 +00004813 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
4814
4815 // Use this protocol meta-data to build protocol list table in section
4816 // __DATA, __objc_protolist
Fariborz Jahanianfd02a662009-01-29 20:10:59 +00004817 llvm::GlobalVariable *PTGV = new llvm::GlobalVariable(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004818 ObjCTypes.ProtocolnfABIPtrTy, false,
Mike Stump36dbf222009-03-07 16:33:28 +00004819 llvm::GlobalValue::WeakAnyLinkage,
Fariborz Jahanianfd02a662009-01-29 20:10:59 +00004820 Entry,
4821 std::string("\01l_OBJC_LABEL_PROTOCOL_$_")
4822 +ProtocolName,
4823 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004824 PTGV->setAlignment(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004825 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Daniel Dunbar9dfd3a72009-04-15 02:56:18 +00004826 PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
Fariborz Jahanianfd02a662009-01-29 20:10:59 +00004827 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4828 UsedGlobals.push_back(PTGV);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004829 return Entry;
4830}
4831
4832/// EmitProtocolList - Generate protocol list meta-data:
4833/// @code
4834/// struct _protocol_list_t {
4835/// long protocol_count; // Note, this is 32/64 bit
4836/// struct _protocol_t[protocol_count];
4837/// }
4838/// @endcode
4839///
4840llvm::Constant *
4841CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name,
4842 ObjCProtocolDecl::protocol_iterator begin,
4843 ObjCProtocolDecl::protocol_iterator end) {
4844 std::vector<llvm::Constant*> ProtocolRefs;
4845
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004846 // Just return null for empty protocol lists
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004847 if (begin == end)
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004848 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
4849
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004850 // FIXME: We shouldn't need to do this lookup here, should we?
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004851 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
4852 if (GV)
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004853 return llvm::ConstantExpr::getBitCast(GV,
4854 ObjCTypes.ProtocolListnfABIPtrTy);
4855
4856 for (; begin != end; ++begin)
4857 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
4858
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004859 // This list is null terminated.
4860 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004861 ObjCTypes.ProtocolnfABIPtrTy));
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004862
4863 std::vector<llvm::Constant*> Values(2);
4864 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
4865 Values[1] =
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004866 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004867 ProtocolRefs.size()),
4868 ProtocolRefs);
4869
4870 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
4871 GV = new llvm::GlobalVariable(Init->getType(), false,
4872 llvm::GlobalValue::InternalLinkage,
4873 Init,
4874 Name,
4875 &CGM.getModule());
4876 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004877 GV->setAlignment(
4878 CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004879 UsedGlobals.push_back(GV);
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004880 return llvm::ConstantExpr::getBitCast(GV,
4881 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004882}
4883
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004884/// GetMethodDescriptionConstant - This routine build following meta-data:
4885/// struct _objc_method {
4886/// SEL _cmd;
4887/// char *method_type;
4888/// char *_imp;
4889/// }
4890
4891llvm::Constant *
4892CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
4893 std::vector<llvm::Constant*> Desc(3);
4894 Desc[0] = llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
4895 ObjCTypes.SelectorPtrTy);
4896 Desc[1] = GetMethodVarType(MD);
Fariborz Jahanian5d13ab12009-01-30 18:58:59 +00004897 // Protocol methods have no implementation. So, this entry is always NULL.
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004898 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
4899 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
4900}
Fariborz Jahanian55343922009-02-03 00:09:52 +00004901
4902/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
4903/// This code gen. amounts to generating code for:
4904/// @code
4905/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
4906/// @encode
4907///
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00004908LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
Fariborz Jahanian55343922009-02-03 00:09:52 +00004909 CodeGen::CodeGenFunction &CGF,
4910 QualType ObjectTy,
4911 llvm::Value *BaseValue,
4912 const ObjCIvarDecl *Ivar,
Fariborz Jahanian55343922009-02-03 00:09:52 +00004913 unsigned CVRQualifiers) {
Daniel Dunbarf5254bd2009-04-21 01:19:28 +00004914 const ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl();
4915 const FieldDecl *Field = ID->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
Daniel Dunbar07d204a2009-04-19 00:31:15 +00004916 llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00004917
Fariborz Jahanian55343922009-02-03 00:09:52 +00004918 // (char *) BaseValue
Chris Lattnerbb87be22009-04-17 17:46:19 +00004919 llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, ObjCTypes.Int8PtrTy);
Fariborz Jahanian55343922009-02-03 00:09:52 +00004920 llvm::Value *Offset = CGF.Builder.CreateLoad(IvarOffsetGV);
4921 // (char*)BaseValue + Offset_symbol
4922 V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
4923 // (type *)((char*)BaseValue + Offset_symbol)
4924 const llvm::Type *IvarTy =
Chris Lattnerbb87be22009-04-17 17:46:19 +00004925 CGM.getTypes().ConvertTypeForMem(Ivar->getType());
Fariborz Jahanian55343922009-02-03 00:09:52 +00004926 llvm::Type *ptrIvarTy = llvm::PointerType::getUnqual(IvarTy);
4927 V = CGF.Builder.CreateBitCast(V, ptrIvarTy);
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00004928
Fariborz Jahanian40a94a92009-03-09 20:44:22 +00004929 if (Ivar->isBitField()) {
Chris Lattnerbb87be22009-04-17 17:46:19 +00004930 QualType FieldTy = Field->getType();
Fariborz Jahanian40a94a92009-03-09 20:44:22 +00004931 CodeGenTypes::BitFieldInfo bitFieldInfo =
4932 CGM.getTypes().getBitFieldInfo(Field);
4933 return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size,
Chris Lattnerbb87be22009-04-17 17:46:19 +00004934 FieldTy->isSignedIntegerType(),
4935 FieldTy.getCVRQualifiers()|CVRQualifiers);
Fariborz Jahanian40a94a92009-03-09 20:44:22 +00004936 }
4937
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00004938 LValue LV = LValue::MakeAddr(V,
Fariborz Jahanianbbd4ca92009-02-19 23:36:06 +00004939 Ivar->getType().getCVRQualifiers()|CVRQualifiers,
4940 CGM.getContext().getObjCGCAttrKind(Ivar->getType()));
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00004941 LValue::SetObjCIvar(LV, true);
4942 return LV;
Fariborz Jahanian55343922009-02-03 00:09:52 +00004943}
4944
Fariborz Jahanian27cc6662009-02-10 19:02:04 +00004945llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
4946 CodeGen::CodeGenFunction &CGF,
4947 ObjCInterfaceDecl *Interface,
4948 const ObjCIvarDecl *Ivar) {
Daniel Dunbar07d204a2009-04-19 00:31:15 +00004949 return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),
4950 false, "ivar");
Fariborz Jahanian27cc6662009-02-10 19:02:04 +00004951}
4952
Fariborz Jahanian7e881162009-02-04 00:22:57 +00004953CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
4954 CodeGen::CodeGenFunction &CGF,
4955 QualType ResultType,
4956 Selector Sel,
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004957 llvm::Value *Receiver,
Fariborz Jahanian7e881162009-02-04 00:22:57 +00004958 QualType Arg0Ty,
4959 bool IsSuper,
4960 const CallArgList &CallArgs) {
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004961 // FIXME. Even though IsSuper is passes. This function doese not
4962 // handle calls to 'super' receivers.
4963 CodeGenTypes &Types = CGM.getTypes();
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004964 llvm::Value *Arg0 = Receiver;
4965 if (!IsSuper)
4966 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004967
4968 // Find the message function name.
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00004969 // FIXME. This is too much work to get the ABI-specific result type
4970 // needed to find the message name.
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004971 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType,
4972 llvm::SmallVector<QualType, 16>());
4973 llvm::Constant *Fn;
4974 std::string Name("\01l_");
4975 if (CGM.ReturnTypeUsesSret(FnInfo)) {
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00004976#if 0
4977 // unlike what is documented. gcc never generates this API!!
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004978 if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
4979 Fn = ObjCTypes.MessageSendIdStretFixupFn;
4980 // FIXME. Is there a better way of getting these names.
4981 // They are available in RuntimeFunctions vector pair.
4982 Name += "objc_msgSendId_stret_fixup";
4983 }
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00004984 else
4985#endif
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004986 if (IsSuper) {
4987 Fn = ObjCTypes.MessageSendSuper2StretFixupFn;
4988 Name += "objc_msgSendSuper2_stret_fixup";
4989 }
4990 else
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00004991 {
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004992 Fn = ObjCTypes.MessageSendStretFixupFn;
4993 Name += "objc_msgSend_stret_fixup";
4994 }
4995 }
Fariborz Jahanianbea03192009-02-05 19:35:43 +00004996 else if (ResultType->isFloatingType() &&
4997 // Selection of frret API only happens in 32bit nonfragile ABI.
4998 CGM.getTargetData().getTypePaddedSize(ObjCTypes.LongTy) == 4) {
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004999 Fn = ObjCTypes.MessageSendFpretFixupFn;
5000 Name += "objc_msgSend_fpret_fixup";
5001 }
5002 else {
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00005003#if 0
5004// unlike what is documented. gcc never generates this API!!
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00005005 if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
5006 Fn = ObjCTypes.MessageSendIdFixupFn;
5007 Name += "objc_msgSendId_fixup";
5008 }
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00005009 else
5010#endif
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00005011 if (IsSuper) {
5012 Fn = ObjCTypes.MessageSendSuper2FixupFn;
5013 Name += "objc_msgSendSuper2_fixup";
5014 }
5015 else
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00005016 {
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00005017 Fn = ObjCTypes.MessageSendFixupFn;
5018 Name += "objc_msgSend_fixup";
5019 }
5020 }
5021 Name += '_';
5022 std::string SelName(Sel.getAsString());
5023 // Replace all ':' in selector name with '_' ouch!
5024 for(unsigned i = 0; i < SelName.size(); i++)
5025 if (SelName[i] == ':')
5026 SelName[i] = '_';
5027 Name += SelName;
5028 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5029 if (!GV) {
Daniel Dunbar4993e292009-04-15 19:03:14 +00005030 // Build message ref table entry.
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00005031 std::vector<llvm::Constant*> Values(2);
5032 Values[0] = Fn;
5033 Values[1] = GetMethodVarName(Sel);
5034 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
5035 GV = new llvm::GlobalVariable(Init->getType(), false,
Mike Stump36dbf222009-03-07 16:33:28 +00005036 llvm::GlobalValue::WeakAnyLinkage,
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00005037 Init,
5038 Name,
5039 &CGM.getModule());
5040 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbara405f782009-04-15 19:04:46 +00005041 GV->setAlignment(16);
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00005042 GV->setSection("__DATA, __objc_msgrefs, coalesced");
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00005043 }
5044 llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy);
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00005045
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00005046 CallArgList ActualArgs;
5047 ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
5048 ActualArgs.push_back(std::make_pair(RValue::get(Arg1),
5049 ObjCTypes.MessageRefCPtrTy));
5050 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00005051 const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs);
5052 llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0);
5053 Callee = CGF.Builder.CreateLoad(Callee);
Fariborz Jahanianf3c17752009-02-14 21:25:36 +00005054 const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true);
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00005055 Callee = CGF.Builder.CreateBitCast(Callee,
5056 llvm::PointerType::getUnqual(FTy));
5057 return CGF.EmitCall(FnInfo1, Callee, ActualArgs);
Fariborz Jahanian7e881162009-02-04 00:22:57 +00005058}
5059
5060/// Generate code for a message send expression in the nonfragile abi.
5061CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend(
5062 CodeGen::CodeGenFunction &CGF,
5063 QualType ResultType,
5064 Selector Sel,
5065 llvm::Value *Receiver,
5066 bool IsClassMessage,
5067 const CallArgList &CallArgs) {
Fariborz Jahanian7e881162009-02-04 00:22:57 +00005068 return EmitMessageSend(CGF, ResultType, Sel,
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00005069 Receiver, CGF.getContext().getObjCIdType(),
Fariborz Jahanian7e881162009-02-04 00:22:57 +00005070 false, CallArgs);
5071}
5072
Daniel Dunbarabbda222009-03-01 04:40:10 +00005073llvm::GlobalVariable *
Fariborz Jahanianab438842009-04-14 18:41:56 +00005074CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
Daniel Dunbarabbda222009-03-01 04:40:10 +00005075 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
5076
Daniel Dunbar66b47512009-03-02 05:18:14 +00005077 if (!GV) {
Daniel Dunbarabbda222009-03-01 04:40:10 +00005078 GV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false,
5079 llvm::GlobalValue::ExternalLinkage,
5080 0, Name, &CGM.getModule());
Daniel Dunbarabbda222009-03-01 04:40:10 +00005081 }
5082
5083 return GV;
5084}
5085
Fariborz Jahanian917c0402009-02-05 20:41:40 +00005086llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar3c190812009-04-18 08:51:00 +00005087 const ObjCInterfaceDecl *ID) {
Fariborz Jahanian917c0402009-02-05 20:41:40 +00005088 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
5089
5090 if (!Entry) {
Daniel Dunbara2d275d2009-04-07 05:48:37 +00005091 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbarabbda222009-03-01 04:40:10 +00005092 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Fariborz Jahanian917c0402009-02-05 20:41:40 +00005093 Entry =
5094 new llvm::GlobalVariable(ObjCTypes.ClassnfABIPtrTy, false,
5095 llvm::GlobalValue::InternalLinkage,
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00005096 ClassGV,
Daniel Dunbar3c190812009-04-18 08:51:00 +00005097 "\01L_OBJC_CLASSLIST_REFERENCES_$_",
Fariborz Jahanian917c0402009-02-05 20:41:40 +00005098 &CGM.getModule());
5099 Entry->setAlignment(
5100 CGM.getTargetData().getPrefTypeAlignment(
5101 ObjCTypes.ClassnfABIPtrTy));
Daniel Dunbar3c190812009-04-18 08:51:00 +00005102 Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
5103 UsedGlobals.push_back(Entry);
5104 }
5105
5106 return Builder.CreateLoad(Entry, false, "tmp");
5107}
Fariborz Jahanian917c0402009-02-05 20:41:40 +00005108
Daniel Dunbar3c190812009-04-18 08:51:00 +00005109llvm::Value *
5110CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
5111 const ObjCInterfaceDecl *ID) {
5112 llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
5113
5114 if (!Entry) {
5115 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
5116 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
5117 Entry =
5118 new llvm::GlobalVariable(ObjCTypes.ClassnfABIPtrTy, false,
5119 llvm::GlobalValue::InternalLinkage,
5120 ClassGV,
5121 "\01L_OBJC_CLASSLIST_SUP_REFS_$_",
5122 &CGM.getModule());
5123 Entry->setAlignment(
5124 CGM.getTargetData().getPrefTypeAlignment(
5125 ObjCTypes.ClassnfABIPtrTy));
5126 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Fariborz Jahanian917c0402009-02-05 20:41:40 +00005127 UsedGlobals.push_back(Entry);
5128 }
5129
5130 return Builder.CreateLoad(Entry, false, "tmp");
5131}
5132
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00005133/// EmitMetaClassRef - Return a Value * of the address of _class_t
5134/// meta-data
5135///
5136llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
5137 const ObjCInterfaceDecl *ID) {
5138 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
5139 if (Entry)
5140 return Builder.CreateLoad(Entry, false, "tmp");
5141
Daniel Dunbara2d275d2009-04-07 05:48:37 +00005142 std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
Fariborz Jahanianab438842009-04-14 18:41:56 +00005143 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00005144 Entry =
5145 new llvm::GlobalVariable(ObjCTypes.ClassnfABIPtrTy, false,
5146 llvm::GlobalValue::InternalLinkage,
5147 MetaClassGV,
5148 "\01L_OBJC_CLASSLIST_SUP_REFS_$_",
5149 &CGM.getModule());
5150 Entry->setAlignment(
5151 CGM.getTargetData().getPrefTypeAlignment(
5152 ObjCTypes.ClassnfABIPtrTy));
5153
Daniel Dunbar4993e292009-04-15 19:03:14 +00005154 Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00005155 UsedGlobals.push_back(Entry);
5156
5157 return Builder.CreateLoad(Entry, false, "tmp");
5158}
5159
Fariborz Jahanian917c0402009-02-05 20:41:40 +00005160/// GetClass - Return a reference to the class for the given interface
5161/// decl.
5162llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
5163 const ObjCInterfaceDecl *ID) {
5164 return EmitClassRef(Builder, ID);
5165}
5166
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00005167/// Generates a message send where the super is the receiver. This is
5168/// a message send to self with special delivery semantics indicating
5169/// which class's method should be called.
5170CodeGen::RValue
5171CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
5172 QualType ResultType,
5173 Selector Sel,
5174 const ObjCInterfaceDecl *Class,
Fariborz Jahanian17636fa2009-02-28 20:07:56 +00005175 bool isCategoryImpl,
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00005176 llvm::Value *Receiver,
5177 bool IsClassMessage,
5178 const CodeGen::CallArgList &CallArgs) {
5179 // ...
5180 // Create and init a super structure; this is a (receiver, class)
5181 // pair we will pass to objc_msgSendSuper.
5182 llvm::Value *ObjCSuper =
5183 CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
5184
5185 llvm::Value *ReceiverAsObject =
5186 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
5187 CGF.Builder.CreateStore(ReceiverAsObject,
5188 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
5189
5190 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanian17636fa2009-02-28 20:07:56 +00005191 llvm::Value *Target;
5192 if (IsClassMessage) {
5193 if (isCategoryImpl) {
5194 // Message sent to "super' in a class method defined in
5195 // a category implementation.
Daniel Dunbar3c190812009-04-18 08:51:00 +00005196 Target = EmitClassRef(CGF.Builder, Class);
Fariborz Jahanian17636fa2009-02-28 20:07:56 +00005197 Target = CGF.Builder.CreateStructGEP(Target, 0);
5198 Target = CGF.Builder.CreateLoad(Target);
5199 }
5200 else
5201 Target = EmitMetaClassRef(CGF.Builder, Class);
5202 }
5203 else
Daniel Dunbar3c190812009-04-18 08:51:00 +00005204 Target = EmitSuperClassRef(CGF.Builder, Class);
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00005205
5206 // FIXME: We shouldn't need to do this cast, rectify the ASTContext
5207 // and ObjCTypes types.
5208 const llvm::Type *ClassTy =
5209 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
5210 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
5211 CGF.Builder.CreateStore(Target,
5212 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
5213
5214 return EmitMessageSend(CGF, ResultType, Sel,
5215 ObjCSuper, ObjCTypes.SuperPtrCTy,
5216 true, CallArgs);
5217}
Fariborz Jahanianebb82c62009-02-11 20:51:17 +00005218
5219llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
5220 Selector Sel) {
5221 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
5222
5223 if (!Entry) {
5224 llvm::Constant *Casted =
5225 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
5226 ObjCTypes.SelectorPtrTy);
5227 Entry =
5228 new llvm::GlobalVariable(ObjCTypes.SelectorPtrTy, false,
5229 llvm::GlobalValue::InternalLinkage,
5230 Casted, "\01L_OBJC_SELECTOR_REFERENCES_",
5231 &CGM.getModule());
5232 Entry->setSection("__DATA,__objc_selrefs,literal_pointers,no_dead_strip");
5233 UsedGlobals.push_back(Entry);
5234 }
5235
5236 return Builder.CreateLoad(Entry, false, "tmp");
5237}
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00005238/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
5239/// objc_assign_ivar (id src, id *dst)
5240///
5241void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
5242 llvm::Value *src, llvm::Value *dst)
5243{
Fariborz Jahanianad51ca02009-03-23 19:10:40 +00005244 const llvm::Type * SrcTy = src->getType();
5245 if (!isa<llvm::PointerType>(SrcTy)) {
5246 unsigned Size = CGM.getTargetData().getTypePaddedSize(SrcTy);
5247 assert(Size <= 8 && "does not support size > 8");
5248 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5249 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian664da982009-03-13 00:42:52 +00005250 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5251 }
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00005252 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5253 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5254 CGF.Builder.CreateCall2(ObjCTypes.GcAssignIvarFn,
5255 src, dst, "assignivar");
5256 return;
5257}
5258
5259/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
5260/// objc_assign_strongCast (id src, id *dst)
5261///
5262void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
5263 CodeGen::CodeGenFunction &CGF,
5264 llvm::Value *src, llvm::Value *dst)
5265{
Fariborz Jahanianad51ca02009-03-23 19:10:40 +00005266 const llvm::Type * SrcTy = src->getType();
5267 if (!isa<llvm::PointerType>(SrcTy)) {
5268 unsigned Size = CGM.getTargetData().getTypePaddedSize(SrcTy);
5269 assert(Size <= 8 && "does not support size > 8");
5270 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5271 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian664da982009-03-13 00:42:52 +00005272 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5273 }
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00005274 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5275 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5276 CGF.Builder.CreateCall2(ObjCTypes.GcAssignStrongCastFn,
5277 src, dst, "weakassign");
5278 return;
5279}
5280
5281/// EmitObjCWeakRead - Code gen for loading value of a __weak
5282/// object: objc_read_weak (id *src)
5283///
5284llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
5285 CodeGen::CodeGenFunction &CGF,
5286 llvm::Value *AddrWeakObj)
5287{
Eli Friedmanf8466232009-03-07 03:57:15 +00005288 const llvm::Type* DestTy =
5289 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00005290 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
5291 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.GcReadWeakFn,
5292 AddrWeakObj, "weakread");
Eli Friedmanf8466232009-03-07 03:57:15 +00005293 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00005294 return read_weak;
5295}
5296
5297/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
5298/// objc_assign_weak (id src, id *dst)
5299///
5300void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
5301 llvm::Value *src, llvm::Value *dst)
5302{
Fariborz Jahanianad51ca02009-03-23 19:10:40 +00005303 const llvm::Type * SrcTy = src->getType();
5304 if (!isa<llvm::PointerType>(SrcTy)) {
5305 unsigned Size = CGM.getTargetData().getTypePaddedSize(SrcTy);
5306 assert(Size <= 8 && "does not support size > 8");
5307 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5308 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian664da982009-03-13 00:42:52 +00005309 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5310 }
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00005311 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5312 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Chris Lattner293c1d32009-04-17 22:12:36 +00005313 CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00005314 src, dst, "weakassign");
5315 return;
5316}
5317
5318/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
5319/// objc_assign_global (id src, id *dst)
5320///
5321void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
5322 llvm::Value *src, llvm::Value *dst)
5323{
Fariborz Jahanianad51ca02009-03-23 19:10:40 +00005324 const llvm::Type * SrcTy = src->getType();
5325 if (!isa<llvm::PointerType>(SrcTy)) {
5326 unsigned Size = CGM.getTargetData().getTypePaddedSize(SrcTy);
5327 assert(Size <= 8 && "does not support size > 8");
5328 src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
5329 : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
Fariborz Jahanian664da982009-03-13 00:42:52 +00005330 src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
5331 }
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00005332 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
5333 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
5334 CGF.Builder.CreateCall2(ObjCTypes.GcAssignGlobalFn,
5335 src, dst, "globalassign");
5336 return;
5337}
Fariborz Jahanianebb82c62009-02-11 20:51:17 +00005338
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005339void
5340CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
5341 const Stmt &S) {
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005342 bool isTry = isa<ObjCAtTryStmt>(S);
5343 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
5344 llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest();
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005345 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005346 llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005347 llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005348 llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
5349
5350 // For @synchronized, call objc_sync_enter(sync.expr). The
5351 // evaluation of the expression must occur before we enter the
5352 // @synchronized. We can safely avoid a temp here because jumps into
5353 // @synchronized are illegal & this will dominate uses.
5354 llvm::Value *SyncArg = 0;
5355 if (!isTry) {
5356 SyncArg =
5357 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
5358 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
Chris Lattner23e24652009-04-06 16:53:45 +00005359 CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg);
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005360 }
5361
5362 // Push an EH context entry, used for handling rethrows and jumps
5363 // through finally.
5364 CGF.PushCleanupBlock(FinallyBlock);
5365
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005366 CGF.setInvokeDest(TryHandler);
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005367
5368 CGF.EmitBlock(TryBlock);
5369 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
5370 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
5371 CGF.EmitBranchThroughCleanup(FinallyEnd);
5372
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005373 // Emit the exception handler.
5374
5375 CGF.EmitBlock(TryHandler);
5376
5377 llvm::Value *llvm_eh_exception =
5378 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
5379 llvm::Value *llvm_eh_selector_i64 =
5380 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector_i64);
5381 llvm::Value *llvm_eh_typeid_for_i64 =
5382 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for_i64);
5383 llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5384 llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow");
5385
5386 llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
5387 SelectorArgs.push_back(Exc);
Chris Lattner23e24652009-04-06 16:53:45 +00005388 SelectorArgs.push_back(ObjCTypes.getEHPersonalityPtr());
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005389
5390 // Construct the lists of (type, catch body) to handle.
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00005391 llvm::SmallVector<std::pair<const ParmVarDecl*, const Stmt*>, 8> Handlers;
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005392 bool HasCatchAll = false;
5393 if (isTry) {
5394 if (const ObjCAtCatchStmt* CatchStmt =
5395 cast<ObjCAtTryStmt>(S).getCatchStmts()) {
5396 for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00005397 const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
Steve Naroff0e8b96a2009-03-03 19:52:17 +00005398 Handlers.push_back(std::make_pair(CatchDecl, CatchStmt->getCatchBody()));
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005399
5400 // catch(...) always matches.
Steve Naroff0e8b96a2009-03-03 19:52:17 +00005401 if (!CatchDecl) {
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005402 // Use i8* null here to signal this is a catch all, not a cleanup.
5403 llvm::Value *Null = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
5404 SelectorArgs.push_back(Null);
5405 HasCatchAll = true;
5406 break;
5407 }
5408
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00005409 if (CGF.getContext().isObjCIdType(CatchDecl->getType()) ||
5410 CatchDecl->getType()->isObjCQualifiedIdType()) {
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005411 llvm::Value *IDEHType =
5412 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
5413 if (!IDEHType)
5414 IDEHType =
5415 new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
5416 llvm::GlobalValue::ExternalLinkage,
5417 0, "OBJC_EHTYPE_id", &CGM.getModule());
5418 SelectorArgs.push_back(IDEHType);
5419 HasCatchAll = true;
5420 break;
5421 }
5422
5423 // All other types should be Objective-C interface pointer types.
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00005424 const PointerType *PT = CatchDecl->getType()->getAsPointerType();
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005425 assert(PT && "Invalid @catch type.");
5426 const ObjCInterfaceType *IT =
5427 PT->getPointeeType()->getAsObjCInterfaceType();
5428 assert(IT && "Invalid @catch type.");
Daniel Dunbarc2129532009-04-08 04:21:03 +00005429 llvm::Value *EHType = GetInterfaceEHType(IT->getDecl(), false);
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005430 SelectorArgs.push_back(EHType);
5431 }
5432 }
5433 }
5434
5435 // We use a cleanup unless there was already a catch all.
5436 if (!HasCatchAll) {
5437 SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0));
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00005438 Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0));
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005439 }
5440
5441 llvm::Value *Selector =
5442 CGF.Builder.CreateCall(llvm_eh_selector_i64,
5443 SelectorArgs.begin(), SelectorArgs.end(),
5444 "selector");
5445 for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00005446 const ParmVarDecl *CatchParam = Handlers[i].first;
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005447 const Stmt *CatchBody = Handlers[i].second;
5448
5449 llvm::BasicBlock *Next = 0;
5450
5451 // The last handler always matches.
5452 if (i + 1 != e) {
5453 assert(CatchParam && "Only last handler can be a catch all.");
5454
5455 llvm::BasicBlock *Match = CGF.createBasicBlock("match");
5456 Next = CGF.createBasicBlock("catch.next");
5457 llvm::Value *Id =
5458 CGF.Builder.CreateCall(llvm_eh_typeid_for_i64,
5459 CGF.Builder.CreateBitCast(SelectorArgs[i+2],
5460 ObjCTypes.Int8PtrTy));
5461 CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(Selector, Id),
5462 Match, Next);
5463
5464 CGF.EmitBlock(Match);
5465 }
5466
5467 if (CatchBody) {
5468 llvm::BasicBlock *MatchEnd = CGF.createBasicBlock("match.end");
5469 llvm::BasicBlock *MatchHandler = CGF.createBasicBlock("match.handler");
5470
5471 // Cleanups must call objc_end_catch.
5472 //
5473 // FIXME: It seems incorrect for objc_begin_catch to be inside
5474 // this context, but this matches gcc.
5475 CGF.PushCleanupBlock(MatchEnd);
5476 CGF.setInvokeDest(MatchHandler);
5477
5478 llvm::Value *ExcObject =
Chris Lattner93dca5b2009-04-22 02:15:23 +00005479 CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), Exc);
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005480
5481 // Bind the catch parameter if it exists.
5482 if (CatchParam) {
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00005483 ExcObject =
5484 CGF.Builder.CreateBitCast(ExcObject,
5485 CGF.ConvertType(CatchParam->getType()));
5486 // CatchParam is a ParmVarDecl because of the grammar
5487 // construction used to handle this, but for codegen purposes
5488 // we treat this as a local decl.
5489 CGF.EmitLocalBlockVarDecl(*CatchParam);
5490 CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005491 }
5492
5493 CGF.ObjCEHValueStack.push_back(ExcObject);
5494 CGF.EmitStmt(CatchBody);
5495 CGF.ObjCEHValueStack.pop_back();
5496
5497 CGF.EmitBranchThroughCleanup(FinallyEnd);
5498
5499 CGF.EmitBlock(MatchHandler);
5500
5501 llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5502 // We are required to emit this call to satisfy LLVM, even
5503 // though we don't use the result.
5504 llvm::SmallVector<llvm::Value*, 8> Args;
5505 Args.push_back(Exc);
Chris Lattner23e24652009-04-06 16:53:45 +00005506 Args.push_back(ObjCTypes.getEHPersonalityPtr());
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005507 Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty,
5508 0));
5509 CGF.Builder.CreateCall(llvm_eh_selector_i64, Args.begin(), Args.end());
5510 CGF.Builder.CreateStore(Exc, RethrowPtr);
5511 CGF.EmitBranchThroughCleanup(FinallyRethrow);
5512
5513 CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
5514
5515 CGF.EmitBlock(MatchEnd);
5516
5517 // Unfortunately, we also have to generate another EH frame here
5518 // in case this throws.
5519 llvm::BasicBlock *MatchEndHandler =
5520 CGF.createBasicBlock("match.end.handler");
5521 llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
Chris Lattner93dca5b2009-04-22 02:15:23 +00005522 CGF.Builder.CreateInvoke(ObjCTypes.getObjCEndCatchFn(),
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005523 Cont, MatchEndHandler,
5524 Args.begin(), Args.begin());
5525
5526 CGF.EmitBlock(Cont);
5527 if (Info.SwitchBlock)
5528 CGF.EmitBlock(Info.SwitchBlock);
5529 if (Info.EndBlock)
5530 CGF.EmitBlock(Info.EndBlock);
5531
5532 CGF.EmitBlock(MatchEndHandler);
5533 Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5534 // We are required to emit this call to satisfy LLVM, even
5535 // though we don't use the result.
5536 Args.clear();
5537 Args.push_back(Exc);
Chris Lattner23e24652009-04-06 16:53:45 +00005538 Args.push_back(ObjCTypes.getEHPersonalityPtr());
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005539 Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty,
5540 0));
5541 CGF.Builder.CreateCall(llvm_eh_selector_i64, Args.begin(), Args.end());
5542 CGF.Builder.CreateStore(Exc, RethrowPtr);
5543 CGF.EmitBranchThroughCleanup(FinallyRethrow);
5544
5545 if (Next)
5546 CGF.EmitBlock(Next);
5547 } else {
5548 assert(!Next && "catchup should be last handler.");
5549
5550 CGF.Builder.CreateStore(Exc, RethrowPtr);
5551 CGF.EmitBranchThroughCleanup(FinallyRethrow);
5552 }
5553 }
5554
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005555 // Pop the cleanup entry, the @finally is outside this cleanup
5556 // scope.
5557 CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
5558 CGF.setInvokeDest(PrevLandingPad);
5559
5560 CGF.EmitBlock(FinallyBlock);
5561
5562 if (isTry) {
5563 if (const ObjCAtFinallyStmt* FinallyStmt =
5564 cast<ObjCAtTryStmt>(S).getFinallyStmt())
5565 CGF.EmitStmt(FinallyStmt->getFinallyBody());
5566 } else {
5567 // Emit 'objc_sync_exit(expr)' as finally's sole statement for
5568 // @synchronized.
5569 CGF.Builder.CreateCall(ObjCTypes.SyncExitFn, SyncArg);
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005570 }
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005571
5572 if (Info.SwitchBlock)
5573 CGF.EmitBlock(Info.SwitchBlock);
5574 if (Info.EndBlock)
5575 CGF.EmitBlock(Info.EndBlock);
5576
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005577 // Branch around the rethrow code.
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005578 CGF.EmitBranch(FinallyEnd);
5579
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005580 CGF.EmitBlock(FinallyRethrow);
Chris Lattner93dca5b2009-04-22 02:15:23 +00005581 CGF.Builder.CreateCall(ObjCTypes.getUnwindResumeOrRethrowFn(),
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005582 CGF.Builder.CreateLoad(RethrowPtr));
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005583 CGF.Builder.CreateUnreachable();
5584
5585 CGF.EmitBlock(FinallyEnd);
5586}
5587
Anders Carlsson1cf75362009-02-16 22:59:18 +00005588/// EmitThrowStmt - Generate code for a throw statement.
5589void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
5590 const ObjCAtThrowStmt &S) {
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005591 llvm::Value *Exception;
Anders Carlsson1cf75362009-02-16 22:59:18 +00005592 if (const Expr *ThrowExpr = S.getThrowExpr()) {
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005593 Exception = CGF.EmitScalarExpr(ThrowExpr);
Anders Carlsson1cf75362009-02-16 22:59:18 +00005594 } else {
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005595 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
5596 "Unexpected rethrow outside @catch block.");
5597 Exception = CGF.ObjCEHValueStack.back();
Anders Carlsson1cf75362009-02-16 22:59:18 +00005598 }
5599
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005600 llvm::Value *ExceptionAsObject =
5601 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
5602 llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
5603 if (InvokeDest) {
5604 llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
5605 CGF.Builder.CreateInvoke(ObjCTypes.ExceptionThrowFn,
5606 Cont, InvokeDest,
5607 &ExceptionAsObject, &ExceptionAsObject + 1);
5608 CGF.EmitBlock(Cont);
5609 } else
5610 CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn, ExceptionAsObject);
5611 CGF.Builder.CreateUnreachable();
5612
Anders Carlsson1cf75362009-02-16 22:59:18 +00005613 // Clear the insertion point to indicate we are in unreachable code.
5614 CGF.Builder.ClearInsertionPoint();
5615}
Daniel Dunbar9c285e72009-03-01 04:46:24 +00005616
5617llvm::Value *
Daniel Dunbarc2129532009-04-08 04:21:03 +00005618CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
5619 bool ForDefinition) {
Daniel Dunbar9c285e72009-03-01 04:46:24 +00005620 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
Daniel Dunbar9c285e72009-03-01 04:46:24 +00005621
Daniel Dunbarc2129532009-04-08 04:21:03 +00005622 // If we don't need a definition, return the entry if found or check
5623 // if we use an external reference.
5624 if (!ForDefinition) {
5625 if (Entry)
5626 return Entry;
Daniel Dunbarafac9be2009-04-07 06:43:45 +00005627
Daniel Dunbarc2129532009-04-08 04:21:03 +00005628 // If this type (or a super class) has the __objc_exception__
5629 // attribute, emit an external reference.
5630 if (hasObjCExceptionAttribute(ID))
5631 return Entry =
5632 new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
5633 llvm::GlobalValue::ExternalLinkage,
5634 0,
5635 (std::string("OBJC_EHTYPE_$_") +
5636 ID->getIdentifier()->getName()),
5637 &CGM.getModule());
5638 }
5639
5640 // Otherwise we need to either make a new entry or fill in the
5641 // initializer.
5642 assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
Daniel Dunbara2d275d2009-04-07 05:48:37 +00005643 std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
Daniel Dunbar9c285e72009-03-01 04:46:24 +00005644 std::string VTableName = "objc_ehtype_vtable";
5645 llvm::GlobalVariable *VTableGV =
5646 CGM.getModule().getGlobalVariable(VTableName);
5647 if (!VTableGV)
5648 VTableGV = new llvm::GlobalVariable(ObjCTypes.Int8PtrTy, false,
5649 llvm::GlobalValue::ExternalLinkage,
5650 0, VTableName, &CGM.getModule());
5651
5652 llvm::Value *VTableIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, 2);
5653
5654 std::vector<llvm::Constant*> Values(3);
5655 Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
5656 Values[1] = GetClassName(ID->getIdentifier());
Fariborz Jahanianab438842009-04-14 18:41:56 +00005657 Values[2] = GetClassGlobal(ClassName);
Daniel Dunbar9c285e72009-03-01 04:46:24 +00005658 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
5659
Daniel Dunbarc2129532009-04-08 04:21:03 +00005660 if (Entry) {
5661 Entry->setInitializer(Init);
5662 } else {
5663 Entry = new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
5664 llvm::GlobalValue::WeakAnyLinkage,
5665 Init,
5666 (std::string("OBJC_EHTYPE_$_") +
5667 ID->getIdentifier()->getName()),
5668 &CGM.getModule());
5669 }
5670
Daniel Dunbar8394fda2009-04-14 06:00:08 +00005671 if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden)
Daniel Dunbara2d275d2009-04-07 05:48:37 +00005672 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Daniel Dunbarc2129532009-04-08 04:21:03 +00005673 Entry->setAlignment(8);
5674
5675 if (ForDefinition) {
5676 Entry->setSection("__DATA,__objc_const");
5677 Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
5678 } else {
5679 Entry->setSection("__DATA,__datacoal_nt,coalesced");
5680 }
Daniel Dunbar9c285e72009-03-01 04:46:24 +00005681
5682 return Entry;
5683}
Anders Carlsson1cf75362009-02-16 22:59:18 +00005684
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00005685/* *** */
5686
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00005687CodeGen::CGObjCRuntime *
5688CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00005689 return new CGObjCMac(CGM);
5690}
Fariborz Jahanian48543f52009-01-21 22:04:16 +00005691
5692CodeGen::CGObjCRuntime *
Fariborz Jahaniand0374812009-01-22 23:02:58 +00005693CodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) {
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00005694 return new CGObjCNonFragileABIMac(CGM);
Fariborz Jahanian48543f52009-01-21 22:04:16 +00005695}