blob: 5ae32e8737d271b9704e900b33ab80fe37ada9db [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:
Daniel Dunbarb050fa62008-08-21 04:36:09 +000044 const llvm::Type *ShortTy, *IntTy, *LongTy;
45 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
Fariborz Jahanian4b161702009-01-22 00:37:21 +000087 llvm::Function *GetPropertyFn, *SetPropertyFn;
88
89 llvm::Function *EnumerationMutationFn;
90
91 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
92 llvm::Function *GcReadWeakFn;
93
94 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
95 llvm::Function *GcAssignWeakFn;
96
97 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
98 llvm::Function *GcAssignGlobalFn;
99
100 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
101 llvm::Function *GcAssignIvarFn;
102
103 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
104 llvm::Function *GcAssignStrongCastFn;
Anders Carlsson1cf75362009-02-16 22:59:18 +0000105
106 /// ExceptionThrowFn - LLVM objc_exception_throw function.
107 llvm::Function *ExceptionThrowFn;
108
Daniel Dunbar34416d62009-02-24 01:43:46 +0000109 /// SyncEnterFn - LLVM object_sync_enter function.
110 llvm::Function *SyncEnterFn;
111
112 /// SyncExitFn - LLVM object_sync_exit function.
113 llvm::Function *SyncExitFn;
114
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000115 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
116 ~ObjCCommonTypesHelper(){}
117};
Daniel Dunbar15245e52008-08-23 04:28:29 +0000118
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000119/// ObjCTypesHelper - Helper class that encapsulates lazy
120/// construction of varies types used during ObjC generation.
121class ObjCTypesHelper : public ObjCCommonTypesHelper {
122private:
123
124 llvm::Function *MessageSendFn, *MessageSendStretFn, *MessageSendFpretFn;
125 llvm::Function *MessageSendSuperFn, *MessageSendSuperStretFn,
126 *MessageSendSuperFpretFn;
127
128public:
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000129 /// SymtabTy - LLVM type for struct objc_symtab.
130 const llvm::StructType *SymtabTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000131 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
132 const llvm::Type *SymtabPtrTy;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000133 /// ModuleTy - LLVM type for struct objc_module.
134 const llvm::StructType *ModuleTy;
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000135
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000136 /// ProtocolTy - LLVM type for struct objc_protocol.
137 const llvm::StructType *ProtocolTy;
138 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
139 const llvm::Type *ProtocolPtrTy;
140 /// ProtocolExtensionTy - LLVM type for struct
141 /// objc_protocol_extension.
142 const llvm::StructType *ProtocolExtensionTy;
143 /// ProtocolExtensionTy - LLVM type for struct
144 /// objc_protocol_extension *.
145 const llvm::Type *ProtocolExtensionPtrTy;
146 /// MethodDescriptionTy - LLVM type for struct
147 /// objc_method_description.
148 const llvm::StructType *MethodDescriptionTy;
149 /// MethodDescriptionListTy - LLVM type for struct
150 /// objc_method_description_list.
151 const llvm::StructType *MethodDescriptionListTy;
152 /// MethodDescriptionListPtrTy - LLVM type for struct
153 /// objc_method_description_list *.
154 const llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000155 /// ProtocolListTy - LLVM type for struct objc_property_list.
156 const llvm::Type *ProtocolListTy;
157 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
158 const llvm::Type *ProtocolListPtrTy;
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000159 /// CategoryTy - LLVM type for struct objc_category.
160 const llvm::StructType *CategoryTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000161 /// ClassTy - LLVM type for struct objc_class.
162 const llvm::StructType *ClassTy;
163 /// ClassPtrTy - LLVM type for struct objc_class *.
164 const llvm::Type *ClassPtrTy;
165 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
166 const llvm::StructType *ClassExtensionTy;
167 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
168 const llvm::Type *ClassExtensionPtrTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000169 // IvarTy - LLVM type for struct objc_ivar.
170 const llvm::StructType *IvarTy;
171 /// IvarListTy - LLVM type for struct objc_ivar_list.
172 const llvm::Type *IvarListTy;
173 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
174 const llvm::Type *IvarListPtrTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000175 /// MethodListTy - LLVM type for struct objc_method_list.
176 const llvm::Type *MethodListTy;
177 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
178 const llvm::Type *MethodListPtrTy;
Anders Carlsson9acb0a42008-09-09 10:10:21 +0000179
180 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
181 const llvm::Type *ExceptionDataTy;
182
Anders Carlsson9acb0a42008-09-09 10:10:21 +0000183 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
184 llvm::Function *ExceptionTryEnterFn;
185
186 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
187 llvm::Function *ExceptionTryExitFn;
188
189 /// ExceptionExtractFn - LLVM objc_exception_extract function.
190 llvm::Function *ExceptionExtractFn;
191
192 /// ExceptionMatchFn - LLVM objc_exception_match function.
193 llvm::Function *ExceptionMatchFn;
194
195 /// SetJmpFn - LLVM _setjmp function.
196 llvm::Function *SetJmpFn;
Chris Lattnerdd978702008-11-15 21:26:17 +0000197
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000198public:
199 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000200 ~ObjCTypesHelper() {}
Daniel Dunbaraecef4c2008-10-17 03:24:53 +0000201
202
203 llvm::Function *getSendFn(bool IsSuper) {
204 return IsSuper ? MessageSendSuperFn : MessageSendFn;
205 }
206
207 llvm::Function *getSendStretFn(bool IsSuper) {
208 return IsSuper ? MessageSendSuperStretFn : MessageSendStretFn;
209 }
210
211 llvm::Function *getSendFpretFn(bool IsSuper) {
212 return IsSuper ? MessageSendSuperFpretFn : MessageSendFpretFn;
213 }
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000214};
215
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000216/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000217/// modern abi
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000218class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanianf52110f2009-02-04 20:42:28 +0000219public:
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +0000220 llvm::Function *MessageSendFixupFn, *MessageSendFpretFixupFn,
221 *MessageSendStretFixupFn, *MessageSendIdFixupFn,
222 *MessageSendIdStretFixupFn, *MessageSendSuper2FixupFn,
223 *MessageSendSuper2StretFixupFn;
224
Fariborz Jahanian781f2732009-01-23 01:46:23 +0000225 // MethodListnfABITy - LLVM for struct _method_list_t
226 const llvm::StructType *MethodListnfABITy;
227
228 // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
229 const llvm::Type *MethodListnfABIPtrTy;
230
231 // ProtocolnfABITy = LLVM for struct _protocol_t
232 const llvm::StructType *ProtocolnfABITy;
233
Daniel Dunbar1f42bb02009-02-15 07:36:20 +0000234 // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
235 const llvm::Type *ProtocolnfABIPtrTy;
236
Fariborz Jahanian781f2732009-01-23 01:46:23 +0000237 // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
238 const llvm::StructType *ProtocolListnfABITy;
239
240 // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
241 const llvm::Type *ProtocolListnfABIPtrTy;
242
243 // ClassnfABITy - LLVM for struct _class_t
244 const llvm::StructType *ClassnfABITy;
245
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000246 // ClassnfABIPtrTy - LLVM for struct _class_t*
247 const llvm::Type *ClassnfABIPtrTy;
248
Fariborz Jahanian781f2732009-01-23 01:46:23 +0000249 // IvarnfABITy - LLVM for struct _ivar_t
250 const llvm::StructType *IvarnfABITy;
251
252 // IvarListnfABITy - LLVM for struct _ivar_list_t
253 const llvm::StructType *IvarListnfABITy;
254
255 // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
256 const llvm::Type *IvarListnfABIPtrTy;
257
258 // ClassRonfABITy - LLVM for struct _class_ro_t
259 const llvm::StructType *ClassRonfABITy;
260
261 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
262 const llvm::Type *ImpnfABITy;
263
264 // CategorynfABITy - LLVM for struct _category_t
265 const llvm::StructType *CategorynfABITy;
266
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +0000267 // New types for nonfragile abi messaging.
268
269 // MessageRefTy - LLVM for:
270 // struct _message_ref_t {
271 // IMP messenger;
272 // SEL name;
273 // };
274 const llvm::StructType *MessageRefTy;
Fariborz Jahanianf52110f2009-02-04 20:42:28 +0000275 // MessageRefCTy - clang type for struct _message_ref_t
276 QualType MessageRefCTy;
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +0000277
278 // MessageRefPtrTy - LLVM for struct _message_ref_t*
279 const llvm::Type *MessageRefPtrTy;
Fariborz Jahanianf52110f2009-02-04 20:42:28 +0000280 // MessageRefCPtrTy - clang type for struct _message_ref_t*
281 QualType MessageRefCPtrTy;
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +0000282
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +0000283 // MessengerTy - Type of the messenger (shown as IMP above)
284 const llvm::FunctionType *MessengerTy;
285
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +0000286 // SuperMessageRefTy - LLVM for:
287 // struct _super_message_ref_t {
288 // SUPER_IMP messenger;
289 // SEL name;
290 // };
291 const llvm::StructType *SuperMessageRefTy;
292
293 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
294 const llvm::Type *SuperMessageRefPtrTy;
Daniel Dunbar75de89f2009-02-24 07:47:38 +0000295
296 /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C
297 /// exception personality function.
298 llvm::Value *EHPersonalityPtr;
299
Daniel Dunbar9c285e72009-03-01 04:46:24 +0000300 llvm::Function *UnwindResumeOrRethrowFn, *ObjCBeginCatchFn, *ObjCEndCatchFn;
301
302 const llvm::StructType *EHTypeTy;
303 const llvm::Type *EHTypePtrTy;
Daniel Dunbar75de89f2009-02-24 07:47:38 +0000304
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000305 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
306 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000307};
308
309class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
310protected:
311 CodeGen::CodeGenModule &CGM;
312 // FIXME! May not be needing this after all.
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000313 unsigned ObjCABI;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000314
Daniel Dunbar8ede0052008-08-25 06:02:07 +0000315 /// LazySymbols - Symbols to generate a lazy reference for. See
316 /// DefinedSymbols and FinishModule().
317 std::set<IdentifierInfo*> LazySymbols;
318
319 /// DefinedSymbols - External symbols which are defined by this
320 /// module. The symbols in this list and LazySymbols are used to add
321 /// special linker symbols which ensure that Objective-C modules are
322 /// linked properly.
323 std::set<IdentifierInfo*> DefinedSymbols;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000324
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000325 /// ClassNames - uniqued class names.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000326 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000327
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000328 /// MethodVarNames - uniqued method variable names.
329 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000330
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000331 /// MethodVarTypes - uniqued method type signatures. We have to use
332 /// a StringMap here because have no other unique reference.
333 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000334
Daniel Dunbar12996f52008-08-26 21:51:14 +0000335 /// MethodDefinitions - map of methods which have been defined in
336 /// this translation unit.
337 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000338
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000339 /// PropertyNames - uniqued method variable names.
340 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000341
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000342 /// ClassReferences - uniqued class references.
343 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000344
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000345 /// SelectorReferences - uniqued selector references.
346 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000347
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000348 /// Protocols - Protocols for which an objc_protocol structure has
349 /// been emitted. Forward declarations are handled by creating an
350 /// empty structure whose initializer is filled in when/if defined.
351 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000352
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000353 /// DefinedProtocols - Protocols which have actually been
354 /// defined. We should not need this, see FIXME in GenerateProtocol.
355 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000356
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000357 /// DefinedClasses - List of defined classes.
358 std::vector<llvm::GlobalValue*> DefinedClasses;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000359
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000360 /// DefinedCategories - List of defined categories.
361 std::vector<llvm::GlobalValue*> DefinedCategories;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000362
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000363 /// UsedGlobals - List of globals to pack into the llvm.used metadata
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000364 /// to prevent them from being clobbered.
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000365 std::vector<llvm::GlobalVariable*> UsedGlobals;
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000366
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +0000367 /// GetNameForMethod - Return a name for the given method.
368 /// \param[out] NameOut - The return value.
369 void GetNameForMethod(const ObjCMethodDecl *OMD,
370 const ObjCContainerDecl *CD,
371 std::string &NameOut);
372
373 /// GetMethodVarName - Return a unique constant for the given
374 /// selector's name. The return value has type char *.
375 llvm::Constant *GetMethodVarName(Selector Sel);
376 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
377 llvm::Constant *GetMethodVarName(const std::string &Name);
378
379 /// GetMethodVarType - Return a unique constant for the given
380 /// selector's name. The return value has type char *.
381
382 // FIXME: This is a horrible name.
383 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Devang Patel593a07a2009-03-04 18:21:39 +0000384 llvm::Constant *GetMethodVarType(FieldDecl *D);
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +0000385
386 /// GetPropertyName - Return a unique constant for the given
387 /// name. The return value has type char *.
388 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
389
390 // FIXME: This can be dropped once string functions are unified.
391 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
392 const Decl *Container);
393
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +0000394 /// GetClassName - Return a unique constant for the given selector's
395 /// name. The return value has type char *.
396 llvm::Constant *GetClassName(IdentifierInfo *Ident);
397
Fariborz Jahanian01b3e342009-03-05 22:39:55 +0000398 /// BuildIvarLayout - Builds ivar layout bitmap for the class
399 /// implementation for the __strong or __weak case.
400 ///
401 llvm::Constant *BuildIvarLayout(ObjCImplementationDecl *OI,
402 bool ForStrongLayout);
403
404 void BuildAggrIvarLayout(RecordDecl *RD,
405 const std::vector<FieldDecl*>& RecFields,
406 unsigned int BytePos, bool ForStrongLayout,
407 int &Index, int &SkIndex, bool &HasUnion);
408
Fariborz Jahanian7345eba2009-03-05 19:17:31 +0000409 /// GetIvarLayoutName - Returns a unique constant for the given
410 /// ivar layout bitmap.
411 llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
412 const ObjCCommonTypesHelper &ObjCTypes);
413
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +0000414 const RecordDecl *GetFirstIvarInRecord(const ObjCInterfaceDecl *OID,
415 RecordDecl::field_iterator &FIV,
416 RecordDecl::field_iterator &PIV);
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +0000417 /// EmitPropertyList - Emit the given property list. The return
418 /// value has type PropertyListPtrTy.
419 llvm::Constant *EmitPropertyList(const std::string &Name,
420 const Decl *Container,
421 const ObjCContainerDecl *OCD,
422 const ObjCCommonTypesHelper &ObjCTypes);
423
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000424 /// GetProtocolRef - Return a reference to the internal protocol
425 /// description, creating an empty one if it has not been
426 /// defined. The return value has type ProtocolPtrTy.
427 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Fariborz Jahaniand65949b2009-03-08 20:18:37 +0000428
429 /// GetIvarBaseOffset - returns ivars byte offset.
430 uint64_t GetIvarBaseOffset(const llvm::StructLayout *Layout,
431 FieldDecl *Field);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000432
Daniel Dunbarc4594f22009-03-09 20:09:19 +0000433 /// CreateMetadataVar - Create a global variable with internal
434 /// linkage for use by the Objective-C runtime.
435 ///
436 /// This is a convenience wrapper which not only creates the
437 /// variable, but also sets the section and alignment and adds the
438 /// global to the UsedGlobals list.
439 llvm::GlobalVariable *CreateMetadataVar(const std::string &Name,
440 llvm::Constant *Init,
441 const char *Section,
442 bool SetAlignment,
443 bool IsUsed);
444
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000445public:
446 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGM(cgm)
447 { }
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000448
449 virtual llvm::Constant *GenerateConstantString(const std::string &String);
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000450
451 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
452 const ObjCContainerDecl *CD=0);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000453
454 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
455
456 /// GetOrEmitProtocol - Get the protocol object for the given
457 /// declaration, emitting it if necessary. The return value has type
458 /// ProtocolPtrTy.
459 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
460
461 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
462 /// object for the given declaration, emitting it if needed. These
463 /// forward references will be filled in with empty bodies if no
464 /// definition is seen. The return value has type ProtocolPtrTy.
465 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000466};
467
468class CGObjCMac : public CGObjCCommonMac {
469private:
470 ObjCTypesHelper ObjCTypes;
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000471 /// EmitImageInfo - Emit the image info marker used to encode some module
472 /// level information.
473 void EmitImageInfo();
474
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000475 /// EmitModuleInfo - Another marker encoding module level
476 /// information.
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000477 void EmitModuleInfo();
478
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000479 /// EmitModuleSymols - Emit module symbols, the list of defined
480 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000481 llvm::Constant *EmitModuleSymbols();
482
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000483 /// FinishModule - Write out global data structures at the end of
484 /// processing a translation unit.
485 void FinishModule();
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000486
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000487 /// EmitClassExtension - Generate the class extension structure used
488 /// to store the weak ivar layout and properties. The return value
489 /// has type ClassExtensionPtrTy.
490 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
491
492 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
493 /// for the given class.
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000494 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000495 const ObjCInterfaceDecl *ID);
496
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000497 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000498 QualType ResultType,
499 Selector Sel,
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000500 llvm::Value *Arg0,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000501 QualType Arg0Ty,
502 bool IsSuper,
503 const CallArgList &CallArgs);
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000504
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000505 /// EmitIvarList - Emit the ivar list for the given
506 /// implementation. If ForClass is true the list of class ivars
507 /// (i.e. metaclass ivars) is emitted, otherwise the list of
508 /// interface ivars will be emitted. The return value has type
509 /// IvarListPtrTy.
510 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +0000511 bool ForClass);
512
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000513 /// EmitMetaClass - Emit a forward reference to the class structure
514 /// for the metaclass of the given interface. The return value has
515 /// type ClassPtrTy.
516 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
517
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000518 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000519 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000520 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
521 llvm::Constant *Protocols,
Daniel Dunbar12996f52008-08-26 21:51:14 +0000522 const llvm::Type *InterfaceTy,
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000523 const ConstantVector &Methods);
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000524
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000525 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000526
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000527 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000528
529 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar6b57d432008-08-26 08:29:31 +0000530 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000531 llvm::Constant *EmitMethodList(const std::string &Name,
532 const char *Section,
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000533 const ConstantVector &Methods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000534
535 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000536 /// method declarations.
537 /// - TypeName: The name for the type containing the methods.
538 /// - IsProtocol: True iff these methods are for a protocol.
539 /// - ClassMethds: True iff these are class methods.
540 /// - Required: When true, only "required" methods are
541 /// listed. Similarly, when false only "optional" methods are
542 /// listed. For classes this should always be true.
543 /// - begin, end: The method list to output.
544 ///
545 /// The return value has type MethodDescriptionListPtrTy.
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000546 llvm::Constant *EmitMethodDescList(const std::string &Name,
547 const char *Section,
548 const ConstantVector &Methods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000549
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000550 /// GetOrEmitProtocol - Get the protocol object for the given
551 /// declaration, emitting it if necessary. The return value has type
552 /// ProtocolPtrTy.
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000553 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000554
555 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
556 /// object for the given declaration, emitting it if needed. These
557 /// forward references will be filled in with empty bodies if no
558 /// definition is seen. The return value has type ProtocolPtrTy.
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000559 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000560
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000561 /// EmitProtocolExtension - Generate the protocol extension
562 /// structure used to store optional instance and class methods, and
563 /// protocol properties. The return value has type
564 /// ProtocolExtensionPtrTy.
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000565 llvm::Constant *
566 EmitProtocolExtension(const ObjCProtocolDecl *PD,
567 const ConstantVector &OptInstanceMethods,
568 const ConstantVector &OptClassMethods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000569
570 /// EmitProtocolList - Generate the list of referenced
571 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar67e778b2008-08-21 21:57:41 +0000572 llvm::Constant *EmitProtocolList(const std::string &Name,
573 ObjCProtocolDecl::protocol_iterator begin,
574 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000575
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000576 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
577 /// for the given selector.
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000578 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000579
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000580 public:
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000581 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000582
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000583 virtual llvm::Function *ModuleInitFunction();
584
Daniel Dunbara04840b2008-08-23 03:46:30 +0000585 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000586 QualType ResultType,
587 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000588 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000589 bool IsClassMessage,
590 const CallArgList &CallArgs);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000591
Daniel Dunbara04840b2008-08-23 03:46:30 +0000592 virtual CodeGen::RValue
593 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000594 QualType ResultType,
595 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000596 const ObjCInterfaceDecl *Class,
Fariborz Jahanian17636fa2009-02-28 20:07:56 +0000597 bool isCategoryImpl,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000598 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000599 bool IsClassMessage,
600 const CallArgList &CallArgs);
Daniel Dunbar434627a2008-08-16 00:25:02 +0000601
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000602 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000603 const ObjCInterfaceDecl *ID);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000604
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000605 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000606
Daniel Dunbarac93e472008-08-15 22:20:32 +0000607 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000608
Daniel Dunbarac93e472008-08-15 22:20:32 +0000609 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000610
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000611 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000612 const ObjCProtocolDecl *PD);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000613
Daniel Dunbarf7103722008-09-24 03:38:44 +0000614 virtual llvm::Function *GetPropertyGetFunction();
615 virtual llvm::Function *GetPropertySetFunction();
Anders Carlsson58d16242008-08-31 04:05:03 +0000616 virtual llvm::Function *EnumerationMutationFunction();
Anders Carlssonb01a2112008-09-09 10:04:29 +0000617
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +0000618 virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
619 const Stmt &S);
Anders Carlssonb01a2112008-09-09 10:04:29 +0000620 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
621 const ObjCAtThrowStmt &S);
Fariborz Jahanian252d87f2008-11-18 22:37:34 +0000622 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian3305ad32008-11-18 21:45:40 +0000623 llvm::Value *AddrWeakObj);
Fariborz Jahanian252d87f2008-11-18 22:37:34 +0000624 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
625 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian17958902008-11-19 00:59:10 +0000626 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
627 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanianf310b592008-11-20 19:23:36 +0000628 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
629 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian17958902008-11-19 00:59:10 +0000630 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
631 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian4337afe2009-02-02 20:02:29 +0000632
Fariborz Jahanianc912eb72009-02-03 19:03:09 +0000633 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
634 QualType ObjectTy,
635 llvm::Value *BaseValue,
636 const ObjCIvarDecl *Ivar,
637 const FieldDecl *Field,
638 unsigned CVRQualifiers);
Fariborz Jahanian27cc6662009-02-10 19:02:04 +0000639 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
640 ObjCInterfaceDecl *Interface,
641 const ObjCIvarDecl *Ivar);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000642};
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000643
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000644class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000645private:
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000646 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000647 llvm::GlobalVariable* ObjCEmptyCacheVar;
648 llvm::GlobalVariable* ObjCEmptyVtableVar;
Daniel Dunbarc0318b22009-03-02 06:08:11 +0000649
Fariborz Jahanianf3a44012009-02-06 20:09:23 +0000650 /// MetaClassReferences - uniqued meta class references.
651 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
Daniel Dunbar9c285e72009-03-01 04:46:24 +0000652
653 /// EHTypeReferences - uniqued class ehtype references.
654 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
Daniel Dunbarc0318b22009-03-02 06:08:11 +0000655
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000656 /// FinishNonFragileABIModule - Write out global data structures at the end of
657 /// processing a translation unit.
658 void FinishNonFragileABIModule();
659
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +0000660 llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
661 unsigned InstanceStart,
662 unsigned InstanceSize,
663 const ObjCImplementationDecl *ID);
Fariborz Jahanian06726462009-01-24 21:21:53 +0000664 llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
665 llvm::Constant *IsAGV,
666 llvm::Constant *SuperClassGV,
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +0000667 llvm::Constant *ClassRoGV,
668 bool HiddenVisibility);
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000669
670 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
671
Fariborz Jahanian151747b2009-01-30 00:46:37 +0000672 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
673
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +0000674 /// EmitMethodList - Emit the method list for the given
675 /// implementation. The return value has type MethodListnfABITy.
676 llvm::Constant *EmitMethodList(const std::string &Name,
677 const char *Section,
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +0000678 const ConstantVector &Methods);
679 /// EmitIvarList - Emit the ivar list for the given
680 /// implementation. If ForClass is true the list of class ivars
681 /// (i.e. metaclass ivars) is emitted, otherwise the list of
682 /// interface ivars will be emitted. The return value has type
683 /// IvarListnfABIPtrTy.
684 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +0000685
Fariborz Jahaniancc00f922009-02-10 20:21:06 +0000686 llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
Fariborz Jahanian150f7732009-01-28 01:36:42 +0000687 const ObjCIvarDecl *Ivar,
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +0000688 unsigned long int offset);
689
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000690 /// GetOrEmitProtocol - Get the protocol object for the given
691 /// declaration, emitting it if necessary. The return value has type
692 /// ProtocolPtrTy.
693 virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
694
695 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
696 /// object for the given declaration, emitting it if needed. These
697 /// forward references will be filled in with empty bodies if no
698 /// definition is seen. The return value has type ProtocolPtrTy.
699 virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
700
701 /// EmitProtocolList - Generate the list of referenced
702 /// protocols. The return value has type ProtocolListPtrTy.
703 llvm::Constant *EmitProtocolList(const std::string &Name,
704 ObjCProtocolDecl::protocol_iterator begin,
Fariborz Jahanian7e881162009-02-04 00:22:57 +0000705 ObjCProtocolDecl::protocol_iterator end);
706
707 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
708 QualType ResultType,
709 Selector Sel,
Fariborz Jahanianf52110f2009-02-04 20:42:28 +0000710 llvm::Value *Receiver,
Fariborz Jahanian7e881162009-02-04 00:22:57 +0000711 QualType Arg0Ty,
712 bool IsSuper,
713 const CallArgList &CallArgs);
Daniel Dunbarabbda222009-03-01 04:40:10 +0000714
715 /// GetClassGlobal - Return the global variable for the Objective-C
716 /// class of the given name.
717 llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000718
Fariborz Jahanian917c0402009-02-05 20:41:40 +0000719 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
720 /// for the given class.
721 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Fariborz Jahanianf3a44012009-02-06 20:09:23 +0000722 const ObjCInterfaceDecl *ID,
723 bool IsSuper = false);
724
725 /// EmitMetaClassRef - Return a Value * of the address of _class_t
726 /// meta-data
727 llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
728 const ObjCInterfaceDecl *ID);
729
Fariborz Jahaniancc00f922009-02-10 20:21:06 +0000730 /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
731 /// the given ivar.
732 ///
733 llvm::GlobalVariable * ObjCIvarOffsetVariable(std::string &Name,
Fariborz Jahaniana09a5142009-02-12 18:51:23 +0000734 const ObjCInterfaceDecl *ID,
Fariborz Jahaniancc00f922009-02-10 20:21:06 +0000735 const ObjCIvarDecl *Ivar);
Fariborz Jahanian917c0402009-02-05 20:41:40 +0000736
Fariborz Jahanianebb82c62009-02-11 20:51:17 +0000737 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
738 /// for the given selector.
739 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
Daniel Dunbar9c285e72009-03-01 04:46:24 +0000740
741 /// GetInterfaceEHType - Get the ehtype for the given Objective-C
742 /// interface. The return value has type EHTypePtrTy.
743 llvm::Value *GetInterfaceEHType(const ObjCInterfaceType *IT);
Daniel Dunbarc0318b22009-03-02 06:08:11 +0000744
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000745public:
Fariborz Jahaniand0374812009-01-22 23:02:58 +0000746 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000747 // FIXME. All stubs for now!
748 virtual llvm::Function *ModuleInitFunction();
749
750 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
751 QualType ResultType,
752 Selector Sel,
753 llvm::Value *Receiver,
754 bool IsClassMessage,
Fariborz Jahanian7e881162009-02-04 00:22:57 +0000755 const CallArgList &CallArgs);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000756
757 virtual CodeGen::RValue
758 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
759 QualType ResultType,
760 Selector Sel,
761 const ObjCInterfaceDecl *Class,
Fariborz Jahanian17636fa2009-02-28 20:07:56 +0000762 bool isCategoryImpl,
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000763 llvm::Value *Receiver,
764 bool IsClassMessage,
Fariborz Jahanianf3a44012009-02-06 20:09:23 +0000765 const CallArgList &CallArgs);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000766
767 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Fariborz Jahanian917c0402009-02-05 20:41:40 +0000768 const ObjCInterfaceDecl *ID);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000769
770 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel)
Fariborz Jahanianebb82c62009-02-11 20:51:17 +0000771 { return EmitSelector(Builder, Sel); }
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000772
Fariborz Jahanianfe49a092009-01-26 18:32:24 +0000773 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000774
775 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000776 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Fariborz Jahanian5d13ab12009-01-30 18:58:59 +0000777 const ObjCProtocolDecl *PD);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000778
Fariborz Jahanian27cc6662009-02-10 19:02:04 +0000779 virtual llvm::Function *GetPropertyGetFunction(){
780 return ObjCTypes.GetPropertyFn;
781 }
782 virtual llvm::Function *GetPropertySetFunction(){
783 return ObjCTypes.SetPropertyFn;
784 }
Daniel Dunbar978d2be2009-02-16 18:48:45 +0000785 virtual llvm::Function *EnumerationMutationFunction() {
786 return ObjCTypes.EnumerationMutationFn;
787 }
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000788
789 virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar75de89f2009-02-24 07:47:38 +0000790 const Stmt &S);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000791 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Anders Carlsson1cf75362009-02-16 22:59:18 +0000792 const ObjCAtThrowStmt &S);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000793 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian5eefb432009-02-16 22:52:32 +0000794 llvm::Value *AddrWeakObj);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000795 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian5eefb432009-02-16 22:52:32 +0000796 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000797 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian5eefb432009-02-16 22:52:32 +0000798 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000799 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian5eefb432009-02-16 22:52:32 +0000800 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000801 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian5eefb432009-02-16 22:52:32 +0000802 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanianc912eb72009-02-03 19:03:09 +0000803 virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
804 QualType ObjectTy,
805 llvm::Value *BaseValue,
806 const ObjCIvarDecl *Ivar,
807 const FieldDecl *Field,
808 unsigned CVRQualifiers);
Fariborz Jahanian27cc6662009-02-10 19:02:04 +0000809 virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
810 ObjCInterfaceDecl *Interface,
811 const ObjCIvarDecl *Ivar);
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000812};
813
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000814} // end anonymous namespace
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000815
816/* *** Helper Functions *** */
817
818/// getConstantGEP() - Help routine to construct simple GEPs.
819static llvm::Constant *getConstantGEP(llvm::Constant *C,
820 unsigned idx0,
821 unsigned idx1) {
822 llvm::Value *Idxs[] = {
823 llvm::ConstantInt::get(llvm::Type::Int32Ty, idx0),
824 llvm::ConstantInt::get(llvm::Type::Int32Ty, idx1)
825 };
826 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
827}
828
829/* *** CGObjCMac Public Interface *** */
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000830
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000831CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
832 ObjCTypes(cgm)
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000833{
Fariborz Jahanian48543f52009-01-21 22:04:16 +0000834 ObjCABI = 1;
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000835 EmitImageInfo();
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000836}
837
Daniel Dunbar434627a2008-08-16 00:25:02 +0000838/// GetClass - Return a reference to the class for the given interface
839/// decl.
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000840llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000841 const ObjCInterfaceDecl *ID) {
842 return EmitClassRef(Builder, ID);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000843}
844
845/// GetSelector - Return the pointer to the unique'd string for this selector.
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000846llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) {
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000847 return EmitSelector(Builder, Sel);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000848}
849
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000850/// Generate a constant CFString object.
851/*
852 struct __builtin_CFString {
853 const int *isa; // point to __CFConstantStringClassReference
854 int flags;
855 const char *str;
856 long length;
857 };
858*/
859
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +0000860llvm::Constant *CGObjCCommonMac::GenerateConstantString(
861 const std::string &String) {
Daniel Dunbardbdb9512008-08-23 18:37:06 +0000862 return CGM.GetAddrOfConstantCFString(String);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000863}
864
865/// Generates a message send where the super is the receiver. This is
866/// a message send to self with special delivery semantics indicating
867/// which class's method should be called.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000868CodeGen::RValue
869CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000870 QualType ResultType,
871 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000872 const ObjCInterfaceDecl *Class,
Fariborz Jahanian17636fa2009-02-28 20:07:56 +0000873 bool isCategoryImpl,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000874 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000875 bool IsClassMessage,
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +0000876 const CodeGen::CallArgList &CallArgs) {
Daniel Dunbar15245e52008-08-23 04:28:29 +0000877 // Create and init a super structure; this is a (receiver, class)
878 // pair we will pass to objc_msgSendSuper.
879 llvm::Value *ObjCSuper =
880 CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
881 llvm::Value *ReceiverAsObject =
882 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
883 CGF.Builder.CreateStore(ReceiverAsObject,
884 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar15245e52008-08-23 04:28:29 +0000885
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000886 // If this is a class message the metaclass is passed as the target.
887 llvm::Value *Target;
888 if (IsClassMessage) {
Fariborz Jahanian17636fa2009-02-28 20:07:56 +0000889 if (isCategoryImpl) {
890 // Message sent to 'super' in a class method defined in a category
891 // implementation requires an odd treatment.
892 // If we are in a class method, we must retrieve the
893 // _metaclass_ for the current class, pointed at by
894 // the class's "isa" pointer. The following assumes that
895 // isa" is the first ivar in a class (which it must be).
896 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
897 Target = CGF.Builder.CreateStructGEP(Target, 0);
898 Target = CGF.Builder.CreateLoad(Target);
899 }
900 else {
901 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
902 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
903 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
904 Target = Super;
905 }
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000906 } else {
907 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
908 }
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000909 // FIXME: We shouldn't need to do this cast, rectify the ASTContext
910 // and ObjCTypes types.
911 const llvm::Type *ClassTy =
912 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000913 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000914 CGF.Builder.CreateStore(Target,
915 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
916
Daniel Dunbardd851282008-08-30 05:35:15 +0000917 return EmitMessageSend(CGF, ResultType, Sel,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000918 ObjCSuper, ObjCTypes.SuperPtrCTy,
919 true, CallArgs);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000920}
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000921
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000922/// Generate code for a message send expression.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000923CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000924 QualType ResultType,
925 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000926 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000927 bool IsClassMessage,
928 const CallArgList &CallArgs) {
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000929 llvm::Value *Arg0 =
930 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
Daniel Dunbardd851282008-08-30 05:35:15 +0000931 return EmitMessageSend(CGF, ResultType, Sel,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000932 Arg0, CGF.getContext().getObjCIdType(),
933 false, CallArgs);
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000934}
935
936CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000937 QualType ResultType,
938 Selector Sel,
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000939 llvm::Value *Arg0,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000940 QualType Arg0Ty,
941 bool IsSuper,
942 const CallArgList &CallArgs) {
943 CallArgList ActualArgs;
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +0000944 ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
945 ActualArgs.push_back(std::make_pair(RValue::get(EmitSelector(CGF.Builder,
946 Sel)),
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000947 CGF.getContext().getObjCSelType()));
948 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbarac93e472008-08-15 22:20:32 +0000949
Daniel Dunbar34bda882009-02-02 23:23:47 +0000950 CodeGenTypes &Types = CGM.getTypes();
951 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs);
952 const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo, false);
Daniel Dunbaraecef4c2008-10-17 03:24:53 +0000953
954 llvm::Constant *Fn;
Daniel Dunbar6ee022b2009-02-02 22:03:45 +0000955 if (CGM.ReturnTypeUsesSret(FnInfo)) {
Daniel Dunbaraecef4c2008-10-17 03:24:53 +0000956 Fn = ObjCTypes.getSendStretFn(IsSuper);
957 } else if (ResultType->isFloatingType()) {
958 // FIXME: Sadly, this is wrong. This actually depends on the
959 // architecture. This happens to be right for x86-32 though.
960 Fn = ObjCTypes.getSendFpretFn(IsSuper);
961 } else {
962 Fn = ObjCTypes.getSendFn(IsSuper);
963 }
Daniel Dunbara9976a22008-09-10 07:00:50 +0000964 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
Daniel Dunbar6ee022b2009-02-02 22:03:45 +0000965 return CGF.EmitCall(FnInfo, Fn, ActualArgs);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000966}
967
Daniel Dunbard916e6e2008-11-01 01:53:16 +0000968llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000969 const ObjCProtocolDecl *PD) {
Daniel Dunbarb3518152008-09-04 04:33:15 +0000970 // FIXME: I don't understand why gcc generates this, or where it is
971 // resolved. Investigate. Its also wasteful to look this up over and
972 // over.
973 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
974
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000975 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
976 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000977}
978
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000979void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000980 // FIXME: We shouldn't need this, the protocol decl should contain
981 // enough information to tell us whether this was a declaration or a
982 // definition.
983 DefinedProtocols.insert(PD->getIdentifier());
984
985 // If we have generated a forward reference to this protocol, emit
986 // it now. Otherwise do nothing, the protocol objects are lazily
987 // emitted.
988 if (Protocols.count(PD->getIdentifier()))
989 GetOrEmitProtocol(PD);
990}
991
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +0000992llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar35b777f2008-10-29 22:36:39 +0000993 if (DefinedProtocols.count(PD->getIdentifier()))
994 return GetOrEmitProtocol(PD);
995 return GetOrEmitProtocolRef(PD);
996}
997
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000998/*
999 // APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
1000 struct _objc_protocol {
1001 struct _objc_protocol_extension *isa;
1002 char *protocol_name;
1003 struct _objc_protocol_list *protocol_list;
1004 struct _objc__method_prototype_list *instance_methods;
1005 struct _objc__method_prototype_list *class_methods
1006 };
1007
1008 See EmitProtocolExtension().
1009*/
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001010llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
1011 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1012
1013 // Early exit if a defining object has already been generated.
1014 if (Entry && Entry->hasInitializer())
1015 return Entry;
1016
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001017 // FIXME: I don't understand why gcc generates this, or where it is
1018 // resolved. Investigate. Its also wasteful to look this up over and
1019 // over.
1020 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
1021
Chris Lattnerd120b9e2008-11-24 03:54:41 +00001022 const char *ProtocolName = PD->getNameAsCString();
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001023
1024 // Construct method lists.
1025 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1026 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
1027 for (ObjCProtocolDecl::instmeth_iterator i = PD->instmeth_begin(),
1028 e = PD->instmeth_end(); i != e; ++i) {
1029 ObjCMethodDecl *MD = *i;
1030 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1031 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1032 OptInstanceMethods.push_back(C);
1033 } else {
1034 InstanceMethods.push_back(C);
1035 }
1036 }
1037
1038 for (ObjCProtocolDecl::classmeth_iterator i = PD->classmeth_begin(),
1039 e = PD->classmeth_end(); i != e; ++i) {
1040 ObjCMethodDecl *MD = *i;
1041 llvm::Constant *C = GetMethodDescriptionConstant(MD);
1042 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
1043 OptClassMethods.push_back(C);
1044 } else {
1045 ClassMethods.push_back(C);
1046 }
1047 }
1048
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001049 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001050 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001051 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001052 Values[2] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001053 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getNameAsString(),
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001054 PD->protocol_begin(),
1055 PD->protocol_end());
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001056 Values[3] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001057 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_"
1058 + PD->getNameAsString(),
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001059 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1060 InstanceMethods);
1061 Values[4] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001062 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_"
1063 + PD->getNameAsString(),
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001064 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1065 ClassMethods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001066 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
1067 Values);
1068
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001069 if (Entry) {
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001070 // Already created, fix the linkage and update the initializer.
1071 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001072 Entry->setInitializer(Init);
1073 } else {
1074 Entry =
1075 new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false,
1076 llvm::GlobalValue::InternalLinkage,
1077 Init,
1078 std::string("\01L_OBJC_PROTOCOL_")+ProtocolName,
1079 &CGM.getModule());
1080 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
1081 UsedGlobals.push_back(Entry);
1082 // FIXME: Is this necessary? Why only for protocol?
1083 Entry->setAlignment(4);
1084 }
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001085
1086 return Entry;
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001087}
1088
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001089llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001090 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
1091
1092 if (!Entry) {
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001093 // We use the initializer as a marker of whether this is a forward
1094 // reference or not. At module finalization we add the empty
1095 // contents for protocols which were referenced but never defined.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001096 Entry =
1097 new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false,
Daniel Dunbar35b777f2008-10-29 22:36:39 +00001098 llvm::GlobalValue::ExternalLinkage,
1099 0,
Chris Lattner271d4c22008-11-24 05:29:24 +00001100 "\01L_OBJC_PROTOCOL_" + PD->getNameAsString(),
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001101 &CGM.getModule());
1102 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
1103 UsedGlobals.push_back(Entry);
1104 // FIXME: Is this necessary? Why only for protocol?
1105 Entry->setAlignment(4);
1106 }
1107
1108 return Entry;
1109}
1110
1111/*
1112 struct _objc_protocol_extension {
1113 uint32_t size;
1114 struct objc_method_description_list *optional_instance_methods;
1115 struct objc_method_description_list *optional_class_methods;
1116 struct objc_property_list *instance_properties;
1117 };
1118*/
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001119llvm::Constant *
1120CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
1121 const ConstantVector &OptInstanceMethods,
1122 const ConstantVector &OptClassMethods) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001123 uint64_t Size =
Daniel Dunbard8439f22009-01-12 21:08:18 +00001124 CGM.getTargetData().getTypePaddedSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001125 std::vector<llvm::Constant*> Values(4);
1126 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001127 Values[1] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001128 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
1129 + PD->getNameAsString(),
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001130 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
1131 OptInstanceMethods);
1132 Values[2] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001133 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_"
1134 + PD->getNameAsString(),
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001135 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
1136 OptClassMethods);
Chris Lattner271d4c22008-11-24 05:29:24 +00001137 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" +
1138 PD->getNameAsString(),
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00001139 0, PD, ObjCTypes);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001140
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001141 // Return null if no extension bits are used.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001142 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
1143 Values[3]->isNullValue())
1144 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
1145
1146 llvm::Constant *Init =
1147 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
1148 llvm::GlobalVariable *GV =
1149 new llvm::GlobalVariable(ObjCTypes.ProtocolExtensionTy, false,
1150 llvm::GlobalValue::InternalLinkage,
1151 Init,
Chris Lattner271d4c22008-11-24 05:29:24 +00001152 "\01L_OBJC_PROTOCOLEXT_" + PD->getNameAsString(),
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001153 &CGM.getModule());
1154 // No special section, but goes in llvm.used
1155 UsedGlobals.push_back(GV);
1156
1157 return GV;
1158}
1159
1160/*
1161 struct objc_protocol_list {
1162 struct objc_protocol_list *next;
1163 long count;
1164 Protocol *list[];
1165 };
1166*/
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001167llvm::Constant *
1168CGObjCMac::EmitProtocolList(const std::string &Name,
1169 ObjCProtocolDecl::protocol_iterator begin,
1170 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001171 std::vector<llvm::Constant*> ProtocolRefs;
1172
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001173 for (; begin != end; ++begin)
1174 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001175
1176 // Just return null for empty protocol lists
1177 if (ProtocolRefs.empty())
1178 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1179
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001180 // This list is null terminated.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001181 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
1182
1183 std::vector<llvm::Constant*> Values(3);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001184 // This field is only used by the runtime.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001185 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1186 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
1187 Values[2] =
1188 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
1189 ProtocolRefs.size()),
1190 ProtocolRefs);
1191
1192 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1193 llvm::GlobalVariable *GV =
1194 new llvm::GlobalVariable(Init->getType(), false,
1195 llvm::GlobalValue::InternalLinkage,
1196 Init,
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001197 Name,
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001198 &CGM.getModule());
1199 GV->setSection("__OBJC,__cat_cls_meth,regular,no_dead_strip");
1200 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
1201}
1202
1203/*
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001204 struct _objc_property {
1205 const char * const name;
1206 const char * const attributes;
1207 };
1208
1209 struct _objc_property_list {
1210 uint32_t entsize; // sizeof (struct _objc_property)
1211 uint32_t prop_count;
1212 struct _objc_property[prop_count];
1213 };
1214*/
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00001215llvm::Constant *CGObjCCommonMac::EmitPropertyList(const std::string &Name,
1216 const Decl *Container,
1217 const ObjCContainerDecl *OCD,
1218 const ObjCCommonTypesHelper &ObjCTypes) {
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001219 std::vector<llvm::Constant*> Properties, Prop(2);
Steve Naroffdcf1e842009-01-11 12:47:58 +00001220 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
1221 E = OCD->prop_end(); I != E; ++I) {
1222 const ObjCPropertyDecl *PD = *I;
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001223 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbar698d6f32008-08-28 04:38:10 +00001224 Prop[1] = GetPropertyTypeString(PD, Container);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001225 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
1226 Prop));
1227 }
1228
1229 // Return null for empty list.
1230 if (Properties.empty())
1231 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1232
1233 unsigned PropertySize =
Daniel Dunbard8439f22009-01-12 21:08:18 +00001234 CGM.getTargetData().getTypePaddedSize(ObjCTypes.PropertyTy);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001235 std::vector<llvm::Constant*> Values(3);
1236 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
1237 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
1238 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
1239 Properties.size());
1240 Values[2] = llvm::ConstantArray::get(AT, Properties);
1241 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1242
1243 llvm::GlobalVariable *GV =
1244 new llvm::GlobalVariable(Init->getType(), false,
1245 llvm::GlobalValue::InternalLinkage,
1246 Init,
1247 Name,
1248 &CGM.getModule());
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00001249 if (ObjCABI == 2)
1250 GV->setSection("__DATA, __objc_const");
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001251 // No special section on property lists?
1252 UsedGlobals.push_back(GV);
1253 return llvm::ConstantExpr::getBitCast(GV,
1254 ObjCTypes.PropertyListPtrTy);
1255
1256}
1257
1258/*
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001259 struct objc_method_description_list {
1260 int count;
1261 struct objc_method_description list[];
1262 };
1263*/
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001264llvm::Constant *
1265CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
1266 std::vector<llvm::Constant*> Desc(2);
1267 Desc[0] = llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1268 ObjCTypes.SelectorPtrTy);
1269 Desc[1] = GetMethodVarType(MD);
1270 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
1271 Desc);
1272}
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001273
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001274llvm::Constant *CGObjCMac::EmitMethodDescList(const std::string &Name,
1275 const char *Section,
1276 const ConstantVector &Methods) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001277 // Return null for empty list.
1278 if (Methods.empty())
1279 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
1280
1281 std::vector<llvm::Constant*> Values(2);
1282 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
1283 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
1284 Methods.size());
1285 Values[1] = llvm::ConstantArray::get(AT, Methods);
1286 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1287
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001288 llvm::GlobalVariable *GV =
1289 new llvm::GlobalVariable(Init->getType(), false,
1290 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001291 Init, Name, &CGM.getModule());
1292 GV->setSection(Section);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001293 UsedGlobals.push_back(GV);
1294 return llvm::ConstantExpr::getBitCast(GV,
1295 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001296}
1297
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001298/*
1299 struct _objc_category {
1300 char *category_name;
1301 char *class_name;
1302 struct _objc_method_list *instance_methods;
1303 struct _objc_method_list *class_methods;
1304 struct _objc_protocol_list *protocols;
1305 uint32_t size; // <rdar://4585769>
1306 struct _objc_property_list *instance_properties;
1307 };
1308 */
Daniel Dunbarac93e472008-08-15 22:20:32 +00001309void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Daniel Dunbard8439f22009-01-12 21:08:18 +00001310 unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.CategoryTy);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001311
Daniel Dunbar0cd49032008-08-26 23:03:11 +00001312 // FIXME: This is poor design, the OCD should have a pointer to the
1313 // category decl. Additionally, note that Category can be null for
1314 // the @implementation w/o an @interface case. Sema should just
1315 // create one for us as it does for @implementation so everyone else
1316 // can live life under a clear blue sky.
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001317 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar0cd49032008-08-26 23:03:11 +00001318 const ObjCCategoryDecl *Category =
1319 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Chris Lattner271d4c22008-11-24 05:29:24 +00001320 std::string ExtName(Interface->getNameAsString() + "_" +
1321 OCD->getNameAsString());
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001322
Daniel Dunbar12996f52008-08-26 21:51:14 +00001323 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1324 for (ObjCCategoryImplDecl::instmeth_iterator i = OCD->instmeth_begin(),
1325 e = OCD->instmeth_end(); i != e; ++i) {
1326 // Instance methods should always be defined.
1327 InstanceMethods.push_back(GetMethodConstant(*i));
1328 }
1329 for (ObjCCategoryImplDecl::classmeth_iterator i = OCD->classmeth_begin(),
1330 e = OCD->classmeth_end(); i != e; ++i) {
1331 // Class methods should always be defined.
1332 ClassMethods.push_back(GetMethodConstant(*i));
1333 }
1334
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001335 std::vector<llvm::Constant*> Values(7);
1336 Values[0] = GetClassName(OCD->getIdentifier());
1337 Values[1] = GetClassName(Interface->getIdentifier());
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001338 Values[2] =
1339 EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") +
1340 ExtName,
1341 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +00001342 InstanceMethods);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001343 Values[3] =
1344 EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName,
1345 "__OBJC,__cat_class_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +00001346 ClassMethods);
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001347 if (Category) {
1348 Values[4] =
1349 EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName,
1350 Category->protocol_begin(),
1351 Category->protocol_end());
1352 } else {
1353 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1354 }
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001355 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar0cd49032008-08-26 23:03:11 +00001356
1357 // If there is no category @interface then there can be no properties.
1358 if (Category) {
1359 Values[6] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_LIST_") + ExtName,
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00001360 OCD, Category, ObjCTypes);
Daniel Dunbar0cd49032008-08-26 23:03:11 +00001361 } else {
1362 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1363 }
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001364
1365 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
1366 Values);
1367
1368 llvm::GlobalVariable *GV =
1369 new llvm::GlobalVariable(ObjCTypes.CategoryTy, false,
1370 llvm::GlobalValue::InternalLinkage,
1371 Init,
1372 std::string("\01L_OBJC_CATEGORY_")+ExtName,
1373 &CGM.getModule());
1374 GV->setSection("__OBJC,__category,regular,no_dead_strip");
1375 UsedGlobals.push_back(GV);
1376 DefinedCategories.push_back(GV);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001377}
1378
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001379// FIXME: Get from somewhere?
1380enum ClassFlags {
1381 eClassFlags_Factory = 0x00001,
1382 eClassFlags_Meta = 0x00002,
1383 // <rdr://5142207>
1384 eClassFlags_HasCXXStructors = 0x02000,
1385 eClassFlags_Hidden = 0x20000,
1386 eClassFlags_ABI2_Hidden = 0x00010,
1387 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
1388};
1389
1390// <rdr://5142207&4705298&4843145>
1391static bool IsClassHidden(const ObjCInterfaceDecl *ID) {
1392 if (const VisibilityAttr *attr = ID->getAttr<VisibilityAttr>()) {
1393 // FIXME: Support -fvisibility
1394 switch (attr->getVisibility()) {
1395 default:
1396 assert(0 && "Unknown visibility");
1397 return false;
1398 case VisibilityAttr::DefaultVisibility:
1399 case VisibilityAttr::ProtectedVisibility: // FIXME: What do we do here?
1400 return false;
1401 case VisibilityAttr::HiddenVisibility:
1402 return true;
1403 }
1404 } else {
1405 return false; // FIXME: Support -fvisibility
1406 }
1407}
1408
1409/*
1410 struct _objc_class {
1411 Class isa;
1412 Class super_class;
1413 const char *name;
1414 long version;
1415 long info;
1416 long instance_size;
1417 struct _objc_ivar_list *ivars;
1418 struct _objc_method_list *methods;
1419 struct _objc_cache *cache;
1420 struct _objc_protocol_list *protocols;
1421 // Objective-C 1.0 extensions (<rdr://4585769>)
1422 const char *ivar_layout;
1423 struct _objc_class_ext *ext;
1424 };
1425
1426 See EmitClassExtension();
1427 */
1428void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001429 DefinedSymbols.insert(ID->getIdentifier());
1430
Chris Lattnerd120b9e2008-11-24 03:54:41 +00001431 std::string ClassName = ID->getNameAsString();
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001432 // FIXME: Gross
1433 ObjCInterfaceDecl *Interface =
1434 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001435 llvm::Constant *Protocols =
Chris Lattner271d4c22008-11-24 05:29:24 +00001436 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getNameAsString(),
Daniel Dunbar67e778b2008-08-21 21:57:41 +00001437 Interface->protocol_begin(),
1438 Interface->protocol_end());
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001439 const llvm::Type *InterfaceTy =
Fariborz Jahanian27ecc672009-02-14 20:13:28 +00001440 CGM.getTypes().ConvertType(CGM.getContext().buildObjCInterfaceType(Interface));
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001441 unsigned Flags = eClassFlags_Factory;
Daniel Dunbard8439f22009-01-12 21:08:18 +00001442 unsigned Size = CGM.getTargetData().getTypePaddedSize(InterfaceTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001443
1444 // FIXME: Set CXX-structors flag.
1445 if (IsClassHidden(ID->getClassInterface()))
1446 Flags |= eClassFlags_Hidden;
1447
Daniel Dunbar12996f52008-08-26 21:51:14 +00001448 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1449 for (ObjCImplementationDecl::instmeth_iterator i = ID->instmeth_begin(),
1450 e = ID->instmeth_end(); i != e; ++i) {
1451 // Instance methods should always be defined.
1452 InstanceMethods.push_back(GetMethodConstant(*i));
1453 }
1454 for (ObjCImplementationDecl::classmeth_iterator i = ID->classmeth_begin(),
1455 e = ID->classmeth_end(); i != e; ++i) {
1456 // Class methods should always be defined.
1457 ClassMethods.push_back(GetMethodConstant(*i));
1458 }
1459
1460 for (ObjCImplementationDecl::propimpl_iterator i = ID->propimpl_begin(),
1461 e = ID->propimpl_end(); i != e; ++i) {
1462 ObjCPropertyImplDecl *PID = *i;
1463
1464 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
1465 ObjCPropertyDecl *PD = PID->getPropertyDecl();
1466
1467 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
1468 if (llvm::Constant *C = GetMethodConstant(MD))
1469 InstanceMethods.push_back(C);
1470 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
1471 if (llvm::Constant *C = GetMethodConstant(MD))
1472 InstanceMethods.push_back(C);
1473 }
1474 }
1475
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001476 std::vector<llvm::Constant*> Values(12);
Daniel Dunbar12996f52008-08-26 21:51:14 +00001477 Values[ 0] = EmitMetaClass(ID, Protocols, InterfaceTy, ClassMethods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001478 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001479 // Record a reference to the super class.
1480 LazySymbols.insert(Super->getIdentifier());
1481
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001482 Values[ 1] =
1483 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
1484 ObjCTypes.ClassPtrTy);
1485 } else {
1486 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
1487 }
1488 Values[ 2] = GetClassName(ID->getIdentifier());
1489 // Version is always 0.
1490 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
1491 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
1492 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00001493 Values[ 6] = EmitIvarList(ID, false);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001494 Values[ 7] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001495 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getNameAsString(),
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001496 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +00001497 InstanceMethods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001498 // cache is always NULL.
1499 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
1500 Values[ 9] = Protocols;
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001501 // FIXME: Set ivar_layout
Fariborz Jahanian7345eba2009-03-05 19:17:31 +00001502 Values[10] = GetIvarLayoutName(0, ObjCTypes);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001503 Values[11] = EmitClassExtension(ID);
1504 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
1505 Values);
1506
1507 llvm::GlobalVariable *GV =
1508 new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1509 llvm::GlobalValue::InternalLinkage,
1510 Init,
1511 std::string("\01L_OBJC_CLASS_")+ClassName,
1512 &CGM.getModule());
1513 GV->setSection("__OBJC,__class,regular,no_dead_strip");
1514 UsedGlobals.push_back(GV);
1515 // FIXME: Why?
1516 GV->setAlignment(32);
1517 DefinedClasses.push_back(GV);
1518}
1519
1520llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
1521 llvm::Constant *Protocols,
Daniel Dunbar12996f52008-08-26 21:51:14 +00001522 const llvm::Type *InterfaceTy,
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001523 const ConstantVector &Methods) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001524 unsigned Flags = eClassFlags_Meta;
Daniel Dunbard8439f22009-01-12 21:08:18 +00001525 unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.ClassTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001526
1527 if (IsClassHidden(ID->getClassInterface()))
1528 Flags |= eClassFlags_Hidden;
1529
1530 std::vector<llvm::Constant*> Values(12);
1531 // The isa for the metaclass is the root of the hierarchy.
1532 const ObjCInterfaceDecl *Root = ID->getClassInterface();
1533 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
1534 Root = Super;
1535 Values[ 0] =
1536 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
1537 ObjCTypes.ClassPtrTy);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001538 // The super class for the metaclass is emitted as the name of the
1539 // super class. The runtime fixes this up to point to the
1540 // *metaclass* for the super class.
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001541 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
1542 Values[ 1] =
1543 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
1544 ObjCTypes.ClassPtrTy);
1545 } else {
1546 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
1547 }
1548 Values[ 2] = GetClassName(ID->getIdentifier());
1549 // Version is always 0.
1550 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
1551 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
1552 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00001553 Values[ 6] = EmitIvarList(ID, true);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001554 Values[ 7] =
Chris Lattner271d4c22008-11-24 05:29:24 +00001555 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001556 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +00001557 Methods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001558 // cache is always NULL.
1559 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
1560 Values[ 9] = Protocols;
1561 // ivar_layout for metaclass is always NULL.
1562 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
1563 // The class extension is always unused for metaclasses.
1564 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
1565 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
1566 Values);
1567
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001568 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattnerd120b9e2008-11-24 03:54:41 +00001569 Name += ID->getNameAsCString();
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001570
1571 // Check for a forward reference.
1572 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
1573 if (GV) {
1574 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
1575 "Forward metaclass reference has incorrect type.");
1576 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
1577 GV->setInitializer(Init);
1578 } else {
1579 GV = new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1580 llvm::GlobalValue::InternalLinkage,
1581 Init, Name,
1582 &CGM.getModule());
1583 }
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001584 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
1585 UsedGlobals.push_back(GV);
1586 // FIXME: Why?
1587 GV->setAlignment(32);
1588
1589 return GV;
1590}
1591
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001592llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattner271d4c22008-11-24 05:29:24 +00001593 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001594
1595 // FIXME: Should we look these up somewhere other than the
1596 // module. Its a bit silly since we only generate these while
1597 // processing an implementation, so exactly one pointer would work
1598 // if know when we entered/exitted an implementation block.
1599
1600 // Check for an existing forward reference.
Fariborz Jahanian5fe09f72009-01-07 20:11:22 +00001601 // Previously, metaclass with internal linkage may have been defined.
1602 // pass 'true' as 2nd argument so it is returned.
1603 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true)) {
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001604 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
1605 "Forward metaclass reference has incorrect type.");
1606 return GV;
1607 } else {
1608 // Generate as an external reference to keep a consistent
1609 // module. This will be patched up when we emit the metaclass.
1610 return new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1611 llvm::GlobalValue::ExternalLinkage,
1612 0,
1613 Name,
1614 &CGM.getModule());
1615 }
1616}
1617
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001618/*
1619 struct objc_class_ext {
1620 uint32_t size;
1621 const char *weak_ivar_layout;
1622 struct _objc_property_list *properties;
1623 };
1624*/
1625llvm::Constant *
1626CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
1627 uint64_t Size =
Daniel Dunbard8439f22009-01-12 21:08:18 +00001628 CGM.getTargetData().getTypePaddedSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001629
1630 std::vector<llvm::Constant*> Values(3);
1631 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001632 // FIXME: Output weak_ivar_layout string.
Fariborz Jahanian7345eba2009-03-05 19:17:31 +00001633 Values[1] = GetIvarLayoutName(0, ObjCTypes);
Chris Lattner271d4c22008-11-24 05:29:24 +00001634 Values[2] = EmitPropertyList("\01L_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00001635 ID, ID->getClassInterface(), ObjCTypes);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001636
1637 // Return null if no extension bits are used.
1638 if (Values[1]->isNullValue() && Values[2]->isNullValue())
1639 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
1640
1641 llvm::Constant *Init =
1642 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
1643 llvm::GlobalVariable *GV =
1644 new llvm::GlobalVariable(ObjCTypes.ClassExtensionTy, false,
1645 llvm::GlobalValue::InternalLinkage,
1646 Init,
Chris Lattner271d4c22008-11-24 05:29:24 +00001647 "\01L_OBJC_CLASSEXT_" + ID->getNameAsString(),
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001648 &CGM.getModule());
1649 // No special section, but goes in llvm.used
1650 UsedGlobals.push_back(GV);
1651
1652 return GV;
1653}
1654
Fariborz Jahanianc314a492009-01-17 19:36:33 +00001655/// countInheritedIvars - count number of ivars in class and its super class(s)
1656///
1657static int countInheritedIvars(const ObjCInterfaceDecl *OI) {
1658 int count = 0;
1659 if (!OI)
1660 return 0;
1661 const ObjCInterfaceDecl *SuperClass = OI->getSuperClass();
1662 if (SuperClass)
1663 count += countInheritedIvars(SuperClass);
1664 for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
1665 E = OI->ivar_end(); I != E; ++I)
1666 ++count;
1667 return count;
1668}
1669
Fariborz Jahaniana09a5142009-02-12 18:51:23 +00001670/// getInterfaceDeclForIvar - Get the interface declaration node where
1671/// this ivar is declared in.
1672/// FIXME. Ideally, this info should be in the ivar node. But currently
1673/// it is not and prevailing wisdom is that ASTs should not have more
1674/// info than is absolutely needed, even though this info reflects the
1675/// source language.
1676///
1677static const ObjCInterfaceDecl *getInterfaceDeclForIvar(
1678 const ObjCInterfaceDecl *OI,
1679 const ObjCIvarDecl *IVD) {
1680 if (!OI)
1681 return 0;
1682 assert(isa<ObjCInterfaceDecl>(OI) && "OI is not an interface");
1683 for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
1684 E = OI->ivar_end(); I != E; ++I)
1685 if ((*I)->getIdentifier() == IVD->getIdentifier())
1686 return OI;
1687 return getInterfaceDeclForIvar(OI->getSuperClass(), IVD);
1688}
1689
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001690/*
1691 struct objc_ivar {
1692 char *ivar_name;
1693 char *ivar_type;
1694 int ivar_offset;
1695 };
1696
1697 struct objc_ivar_list {
1698 int ivar_count;
1699 struct objc_ivar list[count];
1700 };
1701 */
1702llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00001703 bool ForClass) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001704 std::vector<llvm::Constant*> Ivars, Ivar(3);
1705
1706 // When emitting the root class GCC emits ivar entries for the
1707 // actual class structure. It is not clear if we need to follow this
1708 // behavior; for now lets try and get away with not doing it. If so,
1709 // the cleanest solution would be to make up an ObjCInterfaceDecl
1710 // for the class.
1711 if (ForClass)
1712 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00001713
1714 ObjCInterfaceDecl *OID =
1715 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
1716 const llvm::Type *InterfaceTy =
1717 CGM.getTypes().ConvertType(CGM.getContext().getObjCInterfaceType(OID));
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001718 const llvm::StructLayout *Layout =
1719 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(InterfaceTy));
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00001720
1721 RecordDecl::field_iterator ifield, pfield;
1722 const RecordDecl *RD = GetFirstIvarInRecord(OID, ifield, pfield);
Fariborz Jahanianc314a492009-01-17 19:36:33 +00001723 for (RecordDecl::field_iterator e = RD->field_end(); ifield != e; ++ifield) {
1724 FieldDecl *Field = *ifield;
Fariborz Jahaniand65949b2009-03-08 20:18:37 +00001725 uint64_t Offset = GetIvarBaseOffset(Layout, Field);
Fariborz Jahanianc314a492009-01-17 19:36:33 +00001726 if (Field->getIdentifier())
1727 Ivar[0] = GetMethodVarName(Field->getIdentifier());
1728 else
1729 Ivar[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Devang Patel593a07a2009-03-04 18:21:39 +00001730 Ivar[1] = GetMethodVarType(Field);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001731 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, Offset);
Daniel Dunbarc9197cd2008-10-17 20:21:44 +00001732 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001733 }
1734
1735 // Return null for empty list.
1736 if (Ivars.empty())
1737 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
1738
1739 std::vector<llvm::Constant*> Values(2);
1740 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
1741 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
1742 Ivars.size());
1743 Values[1] = llvm::ConstantArray::get(AT, Ivars);
1744 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1745
1746 const char *Prefix = (ForClass ? "\01L_OBJC_CLASS_VARIABLES_" :
1747 "\01L_OBJC_INSTANCE_VARIABLES_");
1748 llvm::GlobalVariable *GV =
1749 new llvm::GlobalVariable(Init->getType(), false,
1750 llvm::GlobalValue::InternalLinkage,
1751 Init,
Chris Lattner271d4c22008-11-24 05:29:24 +00001752 Prefix + ID->getNameAsString(),
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001753 &CGM.getModule());
1754 if (ForClass) {
1755 GV->setSection("__OBJC,__cls_vars,regular,no_dead_strip");
1756 // FIXME: Why is this only here?
1757 GV->setAlignment(32);
1758 } else {
1759 GV->setSection("__OBJC,__instance_vars,regular,no_dead_strip");
1760 }
1761 UsedGlobals.push_back(GV);
1762 return llvm::ConstantExpr::getBitCast(GV,
1763 ObjCTypes.IvarListPtrTy);
1764}
1765
1766/*
1767 struct objc_method {
1768 SEL method_name;
1769 char *method_types;
1770 void *method;
1771 };
1772
1773 struct objc_method_list {
1774 struct objc_method_list *obsolete;
1775 int count;
1776 struct objc_method methods_list[count];
1777 };
1778*/
Daniel Dunbar12996f52008-08-26 21:51:14 +00001779
1780/// GetMethodConstant - Return a struct objc_method constant for the
1781/// given method if it has been defined. The result is null if the
1782/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001783llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Daniel Dunbar12996f52008-08-26 21:51:14 +00001784 // FIXME: Use DenseMap::lookup
1785 llvm::Function *Fn = MethodDefinitions[MD];
1786 if (!Fn)
1787 return 0;
1788
1789 std::vector<llvm::Constant*> Method(3);
1790 Method[0] =
1791 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1792 ObjCTypes.SelectorPtrTy);
1793 Method[1] = GetMethodVarType(MD);
1794 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
1795 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
1796}
1797
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001798llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
1799 const char *Section,
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001800 const ConstantVector &Methods) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001801 // Return null for empty list.
1802 if (Methods.empty())
1803 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
1804
1805 std::vector<llvm::Constant*> Values(3);
1806 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
1807 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
1808 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
1809 Methods.size());
1810 Values[2] = llvm::ConstantArray::get(AT, Methods);
1811 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1812
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001813 llvm::GlobalVariable *GV =
1814 new llvm::GlobalVariable(Init->getType(), false,
1815 llvm::GlobalValue::InternalLinkage,
1816 Init,
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001817 Name,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001818 &CGM.getModule());
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001819 GV->setSection(Section);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001820 UsedGlobals.push_back(GV);
1821 return llvm::ConstantExpr::getBitCast(GV,
1822 ObjCTypes.MethodListPtrTy);
Daniel Dunbarace33292008-08-16 03:19:19 +00001823}
1824
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00001825llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
Daniel Dunbar9fc15a82009-02-02 21:43:58 +00001826 const ObjCContainerDecl *CD) {
Daniel Dunbarace33292008-08-16 03:19:19 +00001827 std::string Name;
Fariborz Jahanian0adaa8a2009-01-10 21:06:09 +00001828 GetNameForMethod(OMD, CD, Name);
Daniel Dunbarace33292008-08-16 03:19:19 +00001829
Daniel Dunbar34bda882009-02-02 23:23:47 +00001830 CodeGenTypes &Types = CGM.getTypes();
Daniel Dunbar3ad1f072008-09-10 04:01:49 +00001831 const llvm::FunctionType *MethodTy =
Daniel Dunbar34bda882009-02-02 23:23:47 +00001832 Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
Daniel Dunbarace33292008-08-16 03:19:19 +00001833 llvm::Function *Method =
Daniel Dunbar3ad1f072008-09-10 04:01:49 +00001834 llvm::Function::Create(MethodTy,
Daniel Dunbarace33292008-08-16 03:19:19 +00001835 llvm::GlobalValue::InternalLinkage,
1836 Name,
1837 &CGM.getModule());
Daniel Dunbar12996f52008-08-26 21:51:14 +00001838 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarace33292008-08-16 03:19:19 +00001839
Daniel Dunbarace33292008-08-16 03:19:19 +00001840 return Method;
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001841}
1842
Fariborz Jahaniand65949b2009-03-08 20:18:37 +00001843uint64_t CGObjCCommonMac::GetIvarBaseOffset(const llvm::StructLayout *Layout,
1844 FieldDecl *Field) {
Fariborz Jahanian40a94a92009-03-09 20:44:22 +00001845 if (!Field->isBitField())
1846 return Layout->getElementOffset(
1847 CGM.getTypes().getLLVMFieldNo(Field));
1848 // FIXME. Must be a better way of getting a bitfield base offset.
1849 uint64_t offset = CGM.getTypes().getLLVMFieldNo(Field);
1850 const llvm::Type *Ty = CGM.getTypes().ConvertTypeForMemRecursive(Field->getType());
1851 uint64_t size = CGM.getTypes().getTargetData().getTypePaddedSizeInBits(Ty);
1852 offset = (offset*size)/8;
1853 return offset;
Fariborz Jahaniand65949b2009-03-08 20:18:37 +00001854}
1855
Daniel Dunbarc4594f22009-03-09 20:09:19 +00001856llvm::GlobalVariable *
1857CGObjCCommonMac::CreateMetadataVar(const std::string &Name,
1858 llvm::Constant *Init,
1859 const char *Section,
1860 bool SetAlignment,
1861 bool IsUsed) {
1862 const llvm::Type *Ty = Init->getType();
1863 llvm::GlobalVariable *GV =
1864 new llvm::GlobalVariable(Ty, false,
1865 llvm::GlobalValue::InternalLinkage,
1866 Init,
1867 Name,
1868 &CGM.getModule());
1869 if (Section)
1870 GV->setSection(Section);
1871 if (SetAlignment)
Daniel Dunbar7ba87d42009-03-09 20:16:39 +00001872 GV->setAlignment(CGM.getTargetData().getPrefTypeAlignment(Ty));
Daniel Dunbarc4594f22009-03-09 20:09:19 +00001873 if (IsUsed)
1874 UsedGlobals.push_back(GV);
1875 return GV;
1876}
1877
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001878llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001879 // Abuse this interface function as a place to finalize.
1880 FinishModule();
1881
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001882 return NULL;
1883}
1884
Daniel Dunbarf7103722008-09-24 03:38:44 +00001885llvm::Function *CGObjCMac::GetPropertyGetFunction() {
1886 return ObjCTypes.GetPropertyFn;
1887}
1888
1889llvm::Function *CGObjCMac::GetPropertySetFunction() {
1890 return ObjCTypes.SetPropertyFn;
1891}
1892
Anders Carlsson58d16242008-08-31 04:05:03 +00001893llvm::Function *CGObjCMac::EnumerationMutationFunction()
1894{
1895 return ObjCTypes.EnumerationMutationFn;
1896}
1897
Daniel Dunbar83544842008-09-28 01:03:14 +00001898/*
1899
1900Objective-C setjmp-longjmp (sjlj) Exception Handling
1901--
1902
1903The basic framework for a @try-catch-finally is as follows:
1904{
1905 objc_exception_data d;
1906 id _rethrow = null;
Anders Carlsson8559de12009-02-07 21:26:04 +00001907 bool _call_try_exit = true;
1908
Daniel Dunbar83544842008-09-28 01:03:14 +00001909 objc_exception_try_enter(&d);
1910 if (!setjmp(d.jmp_buf)) {
1911 ... try body ...
1912 } else {
1913 // exception path
1914 id _caught = objc_exception_extract(&d);
1915
1916 // enter new try scope for handlers
1917 if (!setjmp(d.jmp_buf)) {
1918 ... match exception and execute catch blocks ...
1919
1920 // fell off end, rethrow.
1921 _rethrow = _caught;
Daniel Dunbare9900eb2008-09-30 01:06:03 +00001922 ... jump-through-finally to finally_rethrow ...
Daniel Dunbar83544842008-09-28 01:03:14 +00001923 } else {
1924 // exception in catch block
1925 _rethrow = objc_exception_extract(&d);
Anders Carlsson8559de12009-02-07 21:26:04 +00001926 _call_try_exit = false;
1927 ... jump-through-finally to finally_rethrow ...
Daniel Dunbar83544842008-09-28 01:03:14 +00001928 }
1929 }
Daniel Dunbare9900eb2008-09-30 01:06:03 +00001930 ... jump-through-finally to finally_end ...
Daniel Dunbar83544842008-09-28 01:03:14 +00001931
1932finally:
Anders Carlsson8559de12009-02-07 21:26:04 +00001933 if (_call_try_exit)
1934 objc_exception_try_exit(&d);
1935
Daniel Dunbar83544842008-09-28 01:03:14 +00001936 ... finally block ....
Daniel Dunbare9900eb2008-09-30 01:06:03 +00001937 ... dispatch to finally destination ...
1938
1939finally_rethrow:
1940 objc_exception_throw(_rethrow);
1941
1942finally_end:
Daniel Dunbar83544842008-09-28 01:03:14 +00001943}
1944
1945This framework differs slightly from the one gcc uses, in that gcc
Daniel Dunbare9900eb2008-09-30 01:06:03 +00001946uses _rethrow to determine if objc_exception_try_exit should be called
1947and if the object should be rethrown. This breaks in the face of
1948throwing nil and introduces unnecessary branches.
Daniel Dunbar83544842008-09-28 01:03:14 +00001949
1950We specialize this framework for a few particular circumstances:
1951
1952 - If there are no catch blocks, then we avoid emitting the second
1953 exception handling context.
1954
1955 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
1956 e)) we avoid emitting the code to rethrow an uncaught exception.
1957
1958 - FIXME: If there is no @finally block we can do a few more
1959 simplifications.
1960
1961Rethrows and Jumps-Through-Finally
1962--
1963
1964Support for implicit rethrows and jumping through the finally block is
1965handled by storing the current exception-handling context in
1966ObjCEHStack.
1967
Daniel Dunbare9900eb2008-09-30 01:06:03 +00001968In order to implement proper @finally semantics, we support one basic
1969mechanism for jumping through the finally block to an arbitrary
1970destination. Constructs which generate exits from a @try or @catch
1971block use this mechanism to implement the proper semantics by chaining
1972jumps, as necessary.
1973
1974This mechanism works like the one used for indirect goto: we
1975arbitrarily assign an ID to each destination and store the ID for the
1976destination in a variable prior to entering the finally block. At the
1977end of the finally block we simply create a switch to the proper
1978destination.
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00001979
1980Code gen for @synchronized(expr) stmt;
1981Effectively generating code for:
1982objc_sync_enter(expr);
1983@try stmt @finally { objc_sync_exit(expr); }
Daniel Dunbar83544842008-09-28 01:03:14 +00001984*/
1985
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00001986void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1987 const Stmt &S) {
1988 bool isTry = isa<ObjCAtTryStmt>(S);
Daniel Dunbare9900eb2008-09-30 01:06:03 +00001989 // Create various blocks we refer to for handling @finally.
Daniel Dunbar72f96552008-11-11 02:29:29 +00001990 llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
Anders Carlsson8559de12009-02-07 21:26:04 +00001991 llvm::BasicBlock *FinallyExit = CGF.createBasicBlock("finally.exit");
Daniel Dunbar72f96552008-11-11 02:29:29 +00001992 llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit");
1993 llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
1994 llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
Daniel Dunbar34416d62009-02-24 01:43:46 +00001995
1996 // For @synchronized, call objc_sync_enter(sync.expr). The
1997 // evaluation of the expression must occur before we enter the
1998 // @synchronized. We can safely avoid a temp here because jumps into
1999 // @synchronized are illegal & this will dominate uses.
2000 llvm::Value *SyncArg = 0;
2001 if (!isTry) {
2002 SyncArg =
2003 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
2004 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
2005 CGF.Builder.CreateCall(ObjCTypes.SyncEnterFn, SyncArg);
2006 }
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002007
2008 // Push an EH context entry, used for handling rethrows and jumps
2009 // through finally.
Anders Carlsson00ffb962009-02-09 20:38:58 +00002010 CGF.PushCleanupBlock(FinallyBlock);
2011
Anders Carlssonecd81832009-02-07 21:37:21 +00002012 CGF.ObjCEHValueStack.push_back(0);
2013
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002014 // Allocate memory for the exception data and rethrow pointer.
Anders Carlssonfca6c292008-09-09 17:59:25 +00002015 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
2016 "exceptiondata.ptr");
Daniel Dunbar35b777f2008-10-29 22:36:39 +00002017 llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy,
2018 "_rethrow");
Anders Carlsson8559de12009-02-07 21:26:04 +00002019 llvm::Value *CallTryExitPtr = CGF.CreateTempAlloca(llvm::Type::Int1Ty,
2020 "_call_try_exit");
2021 CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(), CallTryExitPtr);
2022
Anders Carlssonfca6c292008-09-09 17:59:25 +00002023 // Enter a new try block and call setjmp.
2024 CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
2025 llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0,
2026 "jmpbufarray");
2027 JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp");
2028 llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn,
2029 JmpBufPtr, "result");
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002030
Daniel Dunbar72f96552008-11-11 02:29:29 +00002031 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
2032 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
Daniel Dunbarbe56f012008-10-02 17:05:36 +00002033 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"),
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002034 TryHandler, TryBlock);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002035
2036 // Emit the @try block.
2037 CGF.EmitBlock(TryBlock);
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00002038 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
2039 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
Anders Carlsson00ffb962009-02-09 20:38:58 +00002040 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002041
2042 // Emit the "exception in @try" block.
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002043 CGF.EmitBlock(TryHandler);
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002044
2045 // Retrieve the exception object. We may emit multiple blocks but
2046 // nothing can cross this so the value is already in SSA form.
2047 llvm::Value *Caught = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
2048 ExceptionData,
2049 "caught");
Anders Carlssonecd81832009-02-07 21:37:21 +00002050 CGF.ObjCEHValueStack.back() = Caught;
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00002051 if (!isTry)
2052 {
2053 CGF.Builder.CreateStore(Caught, RethrowPtr);
Anders Carlsson8559de12009-02-07 21:26:04 +00002054 CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr);
Anders Carlsson00ffb962009-02-09 20:38:58 +00002055 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00002056 }
2057 else if (const ObjCAtCatchStmt* CatchStmt =
2058 cast<ObjCAtTryStmt>(S).getCatchStmts())
2059 {
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002060 // Enter a new exception try block (in case a @catch block throws
2061 // an exception).
Anders Carlssonfca6c292008-09-09 17:59:25 +00002062 CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002063
Anders Carlssonfca6c292008-09-09 17:59:25 +00002064 llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn,
2065 JmpBufPtr, "result");
Daniel Dunbarbe56f012008-10-02 17:05:36 +00002066 llvm::Value *Threw = CGF.Builder.CreateIsNotNull(SetJmpResult, "threw");
Anders Carlssonfca6c292008-09-09 17:59:25 +00002067
Daniel Dunbar72f96552008-11-11 02:29:29 +00002068 llvm::BasicBlock *CatchBlock = CGF.createBasicBlock("catch");
2069 llvm::BasicBlock *CatchHandler = CGF.createBasicBlock("catch.handler");
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002070 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002071
2072 CGF.EmitBlock(CatchBlock);
2073
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002074 // Handle catch list. As a special case we check if everything is
2075 // matched and avoid generating code for falling off the end if
2076 // so.
2077 bool AllMatched = false;
Anders Carlssonfca6c292008-09-09 17:59:25 +00002078 for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
Daniel Dunbar72f96552008-11-11 02:29:29 +00002079 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch");
Anders Carlssonfca6c292008-09-09 17:59:25 +00002080
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002081 const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl();
Daniel Dunbar7a68b452008-09-27 07:36:24 +00002082 const PointerType *PT = 0;
2083
Anders Carlssonfca6c292008-09-09 17:59:25 +00002084 // catch(...) always matches.
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002085 if (!CatchParam) {
2086 AllMatched = true;
2087 } else {
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002088 PT = CatchParam->getType()->getAsPointerType();
Anders Carlssonfca6c292008-09-09 17:59:25 +00002089
Daniel Dunbard04c9352008-09-27 22:21:14 +00002090 // catch(id e) always matches.
2091 // FIXME: For the time being we also match id<X>; this should
2092 // be rejected by Sema instead.
Steve Naroff17c03822009-02-12 17:52:19 +00002093 if ((PT && CGF.getContext().isObjCIdStructType(PT->getPointeeType())) ||
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002094 CatchParam->getType()->isObjCQualifiedIdType())
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002095 AllMatched = true;
Anders Carlssonfca6c292008-09-09 17:59:25 +00002096 }
2097
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002098 if (AllMatched) {
Anders Carlsson75d86732008-09-11 09:15:33 +00002099 if (CatchParam) {
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002100 CGF.EmitLocalBlockVarDecl(*CatchParam);
Daniel Dunbar5aa22bc2008-11-11 23:11:34 +00002101 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002102 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson75d86732008-09-11 09:15:33 +00002103 }
Anders Carlsson1f4acc32008-09-11 08:21:54 +00002104
Anders Carlsson75d86732008-09-11 09:15:33 +00002105 CGF.EmitStmt(CatchStmt->getCatchBody());
Anders Carlsson00ffb962009-02-09 20:38:58 +00002106 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002107 break;
2108 }
2109
Daniel Dunbar7a68b452008-09-27 07:36:24 +00002110 assert(PT && "Unexpected non-pointer type in @catch");
2111 QualType T = PT->getPointeeType();
Anders Carlssona4519172008-09-11 06:35:14 +00002112 const ObjCInterfaceType *ObjCType = T->getAsObjCInterfaceType();
Anders Carlssonfca6c292008-09-09 17:59:25 +00002113 assert(ObjCType && "Catch parameter must have Objective-C type!");
2114
2115 // Check if the @catch block matches the exception object.
2116 llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl());
2117
Anders Carlssonfca6c292008-09-09 17:59:25 +00002118 llvm::Value *Match = CGF.Builder.CreateCall2(ObjCTypes.ExceptionMatchFn,
2119 Class, Caught, "match");
Anders Carlssonfca6c292008-09-09 17:59:25 +00002120
Daniel Dunbar72f96552008-11-11 02:29:29 +00002121 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("matched");
Anders Carlssonfca6c292008-09-09 17:59:25 +00002122
Daniel Dunbarbe56f012008-10-02 17:05:36 +00002123 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002124 MatchedBlock, NextCatchBlock);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002125
2126 // Emit the @catch block.
2127 CGF.EmitBlock(MatchedBlock);
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002128 CGF.EmitLocalBlockVarDecl(*CatchParam);
Daniel Dunbar5aa22bc2008-11-11 23:11:34 +00002129 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar83544842008-09-28 01:03:14 +00002130
2131 llvm::Value *Tmp =
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002132 CGF.Builder.CreateBitCast(Caught, CGF.ConvertType(CatchParam->getType()),
Daniel Dunbar83544842008-09-28 01:03:14 +00002133 "tmp");
Steve Naroff0e8b96a2009-03-03 19:52:17 +00002134 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
Anders Carlsson75d86732008-09-11 09:15:33 +00002135
2136 CGF.EmitStmt(CatchStmt->getCatchBody());
Anders Carlsson00ffb962009-02-09 20:38:58 +00002137 CGF.EmitBranchThroughCleanup(FinallyEnd);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002138
2139 CGF.EmitBlock(NextCatchBlock);
2140 }
2141
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002142 if (!AllMatched) {
2143 // None of the handlers caught the exception, so store it to be
2144 // rethrown at the end of the @finally block.
2145 CGF.Builder.CreateStore(Caught, RethrowPtr);
Anders Carlsson00ffb962009-02-09 20:38:58 +00002146 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002147 }
2148
2149 // Emit the exception handler for the @catch blocks.
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002150 CGF.EmitBlock(CatchHandler);
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002151 CGF.Builder.CreateStore(CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
2152 ExceptionData),
2153 RethrowPtr);
Anders Carlsson8559de12009-02-07 21:26:04 +00002154 CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr);
Anders Carlsson00ffb962009-02-09 20:38:58 +00002155 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Daniel Dunbar4655e2e2008-09-27 07:03:52 +00002156 } else {
Anders Carlssonfca6c292008-09-09 17:59:25 +00002157 CGF.Builder.CreateStore(Caught, RethrowPtr);
Anders Carlsson8559de12009-02-07 21:26:04 +00002158 CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(), CallTryExitPtr);
Anders Carlsson00ffb962009-02-09 20:38:58 +00002159 CGF.EmitBranchThroughCleanup(FinallyRethrow);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002160 }
2161
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002162 // Pop the exception-handling stack entry. It is important to do
2163 // this now, because the code in the @finally block is not in this
2164 // context.
Anders Carlsson00ffb962009-02-09 20:38:58 +00002165 CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
2166
Anders Carlssonecd81832009-02-07 21:37:21 +00002167 CGF.ObjCEHValueStack.pop_back();
2168
Anders Carlssonfca6c292008-09-09 17:59:25 +00002169 // Emit the @finally block.
2170 CGF.EmitBlock(FinallyBlock);
Anders Carlsson8559de12009-02-07 21:26:04 +00002171 llvm::Value* CallTryExit = CGF.Builder.CreateLoad(CallTryExitPtr, "tmp");
2172
2173 CGF.Builder.CreateCondBr(CallTryExit, FinallyExit, FinallyNoExit);
2174
2175 CGF.EmitBlock(FinallyExit);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002176 CGF.Builder.CreateCall(ObjCTypes.ExceptionTryExitFn, ExceptionData);
Daniel Dunbar7a68b452008-09-27 07:36:24 +00002177
2178 CGF.EmitBlock(FinallyNoExit);
Fariborz Jahanianfbeda7b2008-11-21 00:49:24 +00002179 if (isTry) {
2180 if (const ObjCAtFinallyStmt* FinallyStmt =
2181 cast<ObjCAtTryStmt>(S).getFinallyStmt())
2182 CGF.EmitStmt(FinallyStmt->getFinallyBody());
Daniel Dunbar34416d62009-02-24 01:43:46 +00002183 } else {
2184 // Emit objc_sync_exit(expr); as finally's sole statement for
2185 // @synchronized.
2186 CGF.Builder.CreateCall(ObjCTypes.SyncExitFn, SyncArg);
Fariborz Jahanian3895d922008-11-21 19:21:53 +00002187 }
Anders Carlssonfca6c292008-09-09 17:59:25 +00002188
Anders Carlsson00ffb962009-02-09 20:38:58 +00002189 // Emit the switch block
2190 if (Info.SwitchBlock)
2191 CGF.EmitBlock(Info.SwitchBlock);
2192 if (Info.EndBlock)
2193 CGF.EmitBlock(Info.EndBlock);
2194
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002195 CGF.EmitBlock(FinallyRethrow);
2196 CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn,
2197 CGF.Builder.CreateLoad(RethrowPtr));
Daniel Dunbar0ac66f72008-09-27 23:30:04 +00002198 CGF.Builder.CreateUnreachable();
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002199
2200 CGF.EmitBlock(FinallyEnd);
Anders Carlssonb01a2112008-09-09 10:04:29 +00002201}
2202
2203void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbare9900eb2008-09-30 01:06:03 +00002204 const ObjCAtThrowStmt &S) {
Anders Carlsson05d7be72008-09-09 16:16:55 +00002205 llvm::Value *ExceptionAsObject;
2206
2207 if (const Expr *ThrowExpr = S.getThrowExpr()) {
2208 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
2209 ExceptionAsObject =
2210 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
2211 } else {
Anders Carlssonecd81832009-02-07 21:37:21 +00002212 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
Daniel Dunbar83544842008-09-28 01:03:14 +00002213 "Unexpected rethrow outside @catch block.");
Anders Carlssonecd81832009-02-07 21:37:21 +00002214 ExceptionAsObject = CGF.ObjCEHValueStack.back();
Anders Carlsson05d7be72008-09-09 16:16:55 +00002215 }
2216
2217 CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn, ExceptionAsObject);
Anders Carlssonfca6c292008-09-09 17:59:25 +00002218 CGF.Builder.CreateUnreachable();
Daniel Dunbar5aa22bc2008-11-11 23:11:34 +00002219
2220 // Clear the insertion point to indicate we are in unreachable code.
2221 CGF.Builder.ClearInsertionPoint();
Anders Carlssonb01a2112008-09-09 10:04:29 +00002222}
2223
Fariborz Jahanian252d87f2008-11-18 22:37:34 +00002224/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanian3305ad32008-11-18 21:45:40 +00002225/// object: objc_read_weak (id *src)
2226///
Fariborz Jahanian252d87f2008-11-18 22:37:34 +00002227llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian3305ad32008-11-18 21:45:40 +00002228 llvm::Value *AddrWeakObj)
2229{
Eli Friedmanf8466232009-03-07 03:57:15 +00002230 const llvm::Type* DestTy =
2231 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
Fariborz Jahaniand2f661a2008-11-19 17:34:06 +00002232 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian3305ad32008-11-18 21:45:40 +00002233 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.GcReadWeakFn,
Fariborz Jahanian252d87f2008-11-18 22:37:34 +00002234 AddrWeakObj, "weakread");
Eli Friedmanf8466232009-03-07 03:57:15 +00002235 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian3305ad32008-11-18 21:45:40 +00002236 return read_weak;
2237}
2238
Fariborz Jahanian252d87f2008-11-18 22:37:34 +00002239/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
2240/// objc_assign_weak (id src, id *dst)
2241///
2242void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
2243 llvm::Value *src, llvm::Value *dst)
2244{
Fariborz Jahaniand2f661a2008-11-19 17:34:06 +00002245 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2246 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian252d87f2008-11-18 22:37:34 +00002247 CGF.Builder.CreateCall2(ObjCTypes.GcAssignWeakFn,
2248 src, dst, "weakassign");
2249 return;
2250}
2251
Fariborz Jahanian17958902008-11-19 00:59:10 +00002252/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
2253/// objc_assign_global (id src, id *dst)
2254///
2255void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
2256 llvm::Value *src, llvm::Value *dst)
2257{
Fariborz Jahaniand2f661a2008-11-19 17:34:06 +00002258 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2259 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian17958902008-11-19 00:59:10 +00002260 CGF.Builder.CreateCall2(ObjCTypes.GcAssignGlobalFn,
2261 src, dst, "globalassign");
2262 return;
2263}
2264
Fariborz Jahanianf310b592008-11-20 19:23:36 +00002265/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
2266/// objc_assign_ivar (id src, id *dst)
2267///
2268void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
2269 llvm::Value *src, llvm::Value *dst)
2270{
2271 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2272 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
2273 CGF.Builder.CreateCall2(ObjCTypes.GcAssignIvarFn,
2274 src, dst, "assignivar");
2275 return;
2276}
2277
Fariborz Jahanian17958902008-11-19 00:59:10 +00002278/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
2279/// objc_assign_strongCast (id src, id *dst)
2280///
2281void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
2282 llvm::Value *src, llvm::Value *dst)
2283{
Fariborz Jahaniand2f661a2008-11-19 17:34:06 +00002284 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
2285 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian17958902008-11-19 00:59:10 +00002286 CGF.Builder.CreateCall2(ObjCTypes.GcAssignStrongCastFn,
2287 src, dst, "weakassign");
2288 return;
2289}
2290
Fariborz Jahanian4337afe2009-02-02 20:02:29 +00002291/// EmitObjCValueForIvar - Code Gen for ivar reference.
2292///
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00002293LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
2294 QualType ObjectTy,
2295 llvm::Value *BaseValue,
2296 const ObjCIvarDecl *Ivar,
2297 const FieldDecl *Field,
2298 unsigned CVRQualifiers) {
2299 if (Ivar->isBitField())
2300 return CGF.EmitLValueForBitfield(BaseValue, const_cast<FieldDecl *>(Field),
2301 CVRQualifiers);
Fariborz Jahanian4337afe2009-02-02 20:02:29 +00002302 // TODO: Add a special case for isa (index 0)
2303 unsigned Index = CGM.getTypes().getLLVMFieldNo(Field);
2304 llvm::Value *V = CGF.Builder.CreateStructGEP(BaseValue, Index, "tmp");
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00002305 LValue LV = LValue::MakeAddr(V,
Fariborz Jahanianbbd4ca92009-02-19 23:36:06 +00002306 Ivar->getType().getCVRQualifiers()|CVRQualifiers,
2307 CGM.getContext().getObjCGCAttrKind(Ivar->getType()));
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00002308 LValue::SetObjCIvar(LV, true);
2309 return LV;
Fariborz Jahanian4337afe2009-02-02 20:02:29 +00002310}
2311
Fariborz Jahanian27cc6662009-02-10 19:02:04 +00002312llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
2313 ObjCInterfaceDecl *Interface,
2314 const ObjCIvarDecl *Ivar) {
2315 const llvm::Type *InterfaceLTy =
2316 CGM.getTypes().ConvertType(CGM.getContext().getObjCInterfaceType(Interface));
2317 const llvm::StructLayout *Layout =
2318 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(InterfaceLTy));
2319 FieldDecl *Field = Interface->lookupFieldDeclForIvar(CGM.getContext(), Ivar);
Fariborz Jahaniand65949b2009-03-08 20:18:37 +00002320 uint64_t Offset = GetIvarBaseOffset(Layout, Field);
Fariborz Jahanian27cc6662009-02-10 19:02:04 +00002321 return llvm::ConstantInt::get(
2322 CGM.getTypes().ConvertType(CGM.getContext().LongTy),
2323 Offset);
2324}
2325
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002326/* *** Private Interface *** */
2327
2328/// EmitImageInfo - Emit the image info marker used to encode some module
2329/// level information.
2330///
2331/// See: <rdr://4810609&4810587&4810587>
2332/// struct IMAGE_INFO {
2333/// unsigned version;
2334/// unsigned flags;
2335/// };
2336enum ImageInfoFlags {
2337 eImageInfo_FixAndContinue = (1 << 0), // FIXME: Not sure what this implies
2338 eImageInfo_GarbageCollected = (1 << 1),
2339 eImageInfo_GCOnly = (1 << 2)
2340};
2341
2342void CGObjCMac::EmitImageInfo() {
2343 unsigned version = 0; // Version is unused?
2344 unsigned flags = 0;
2345
2346 // FIXME: Fix and continue?
2347 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
2348 flags |= eImageInfo_GarbageCollected;
2349 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
2350 flags |= eImageInfo_GCOnly;
2351
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002352 // Emitted as int[2];
2353 llvm::Constant *values[2] = {
2354 llvm::ConstantInt::get(llvm::Type::Int32Ty, version),
2355 llvm::ConstantInt::get(llvm::Type::Int32Ty, flags)
2356 };
2357 llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::Int32Ty, 2);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002358 llvm::GlobalVariable *GV =
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002359 new llvm::GlobalVariable(AT, true,
2360 llvm::GlobalValue::InternalLinkage,
2361 llvm::ConstantArray::get(AT, values, 2),
2362 "\01L_OBJC_IMAGE_INFO",
2363 &CGM.getModule());
2364
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00002365 if (ObjCABI == 1) {
2366 GV->setSection("__OBJC, __image_info,regular");
2367 } else {
2368 GV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip");
2369 }
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002370
2371 UsedGlobals.push_back(GV);
2372}
2373
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002374
2375// struct objc_module {
2376// unsigned long version;
2377// unsigned long size;
2378// const char *name;
2379// Symtab symtab;
2380// };
2381
2382// FIXME: Get from somewhere
2383static const int ModuleVersion = 7;
2384
2385void CGObjCMac::EmitModuleInfo() {
Daniel Dunbard8439f22009-01-12 21:08:18 +00002386 uint64_t Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.ModuleTy);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002387
2388 std::vector<llvm::Constant*> Values(4);
2389 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
2390 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbarac93e472008-08-15 22:20:32 +00002391 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002392 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002393 Values[3] = EmitModuleSymbols();
2394
2395 llvm::GlobalVariable *GV =
2396 new llvm::GlobalVariable(ObjCTypes.ModuleTy, false,
2397 llvm::GlobalValue::InternalLinkage,
2398 llvm::ConstantStruct::get(ObjCTypes.ModuleTy,
2399 Values),
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002400 "\01L_OBJC_MODULES",
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002401 &CGM.getModule());
2402 GV->setSection("__OBJC,__module_info,regular,no_dead_strip");
2403 UsedGlobals.push_back(GV);
2404}
2405
2406llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002407 unsigned NumClasses = DefinedClasses.size();
2408 unsigned NumCategories = DefinedCategories.size();
2409
Daniel Dunbar8ede0052008-08-25 06:02:07 +00002410 // Return null if no symbols were defined.
2411 if (!NumClasses && !NumCategories)
2412 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
2413
2414 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002415 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2416 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
2417 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
2418 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
2419
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00002420 // The runtime expects exactly the list of defined classes followed
2421 // by the list of defined categories, in a single array.
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002422 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00002423 for (unsigned i=0; i<NumClasses; i++)
2424 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
2425 ObjCTypes.Int8PtrTy);
2426 for (unsigned i=0; i<NumCategories; i++)
2427 Symbols[NumClasses + i] =
2428 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
2429 ObjCTypes.Int8PtrTy);
2430
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002431 Values[4] =
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00002432 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002433 NumClasses + NumCategories),
2434 Symbols);
2435
2436 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
2437
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002438 llvm::GlobalVariable *GV =
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002439 new llvm::GlobalVariable(Init->getType(), false,
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002440 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002441 Init,
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002442 "\01L_OBJC_SYMBOLS",
2443 &CGM.getModule());
2444 GV->setSection("__OBJC,__symbols,regular,no_dead_strip");
2445 UsedGlobals.push_back(GV);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002446 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
2447}
2448
Daniel Dunbard916e6e2008-11-01 01:53:16 +00002449llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002450 const ObjCInterfaceDecl *ID) {
Daniel Dunbar8ede0052008-08-25 06:02:07 +00002451 LazySymbols.insert(ID->getIdentifier());
2452
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002453 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
2454
2455 if (!Entry) {
2456 llvm::Constant *Casted =
2457 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
2458 ObjCTypes.ClassPtrTy);
2459 Entry =
2460 new llvm::GlobalVariable(ObjCTypes.ClassPtrTy, false,
2461 llvm::GlobalValue::InternalLinkage,
2462 Casted, "\01L_OBJC_CLASS_REFERENCES_",
2463 &CGM.getModule());
2464 Entry->setSection("__OBJC,__cls_refs,literal_pointers,no_dead_strip");
2465 UsedGlobals.push_back(Entry);
2466 }
2467
2468 return Builder.CreateLoad(Entry, false, "tmp");
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002469}
2470
Daniel Dunbard916e6e2008-11-01 01:53:16 +00002471llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) {
Daniel Dunbar5eec6142008-08-12 03:39:23 +00002472 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
2473
2474 if (!Entry) {
2475 llvm::Constant *Casted =
2476 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
2477 ObjCTypes.SelectorPtrTy);
2478 Entry =
2479 new llvm::GlobalVariable(ObjCTypes.SelectorPtrTy, false,
2480 llvm::GlobalValue::InternalLinkage,
2481 Casted, "\01L_OBJC_SELECTOR_REFERENCES_",
2482 &CGM.getModule());
2483 Entry->setSection("__OBJC,__message_refs,literal_pointers,no_dead_strip");
2484 UsedGlobals.push_back(Entry);
2485 }
2486
2487 return Builder.CreateLoad(Entry, false, "tmp");
2488}
2489
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00002490llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002491 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002492
2493 if (!Entry) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002494 llvm::Constant *C = llvm::ConstantArray::get(Ident->getName());
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002495 Entry =
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002496 new llvm::GlobalVariable(C->getType(), false,
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002497 llvm::GlobalValue::InternalLinkage,
2498 C, "\01L_OBJC_CLASS_NAME_",
2499 &CGM.getModule());
2500 Entry->setSection("__TEXT,__cstring,cstring_literals");
2501 UsedGlobals.push_back(Entry);
2502 }
2503
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002504 return getConstantGEP(Entry, 0, 0);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002505}
2506
Fariborz Jahanian7345eba2009-03-05 19:17:31 +00002507/// GetIvarLayoutName - Returns a unique constant for the given
2508/// ivar layout bitmap.
2509llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
2510 const ObjCCommonTypesHelper &ObjCTypes) {
2511 return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
2512}
2513
Fariborz Jahanian01b3e342009-03-05 22:39:55 +00002514void CGObjCCommonMac::BuildAggrIvarLayout(RecordDecl *RD,
2515 const std::vector<FieldDecl*>& RecFields,
2516 unsigned int BytePos, bool ForStrongLayout,
2517 int &Index, int &SkIndex, bool &HasUnion) {
2518 return;
2519}
2520
2521/// BuildIvarLayout - Builds ivar layout bitmap for the class
2522/// implementation for the __strong or __weak case.
2523/// The layout map displays which words in ivar list must be skipped
2524/// and which must be scanned by GC (see below). String is built of bytes.
2525/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
2526/// of words to skip and right nibble is count of words to scan. So, each
2527/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
2528/// represented by a 0x00 byte which also ends the string.
2529/// 1. when ForStrongLayout is true, following ivars are scanned:
2530/// - id, Class
2531/// - object *
2532/// - __strong anything
2533///
2534/// 2. When ForStrongLayout is false, following ivars are scanned:
2535/// - __weak anything
2536///
2537llvm::Constant *CGObjCCommonMac::BuildIvarLayout(ObjCImplementationDecl *OMD,
2538 bool ForStrongLayout) {
2539 int iIndex = -1;
2540 int iSkIndex = -1;
2541 bool hasUnion = false;
2542
2543 std::vector<FieldDecl*> RecFields;
2544 ObjCInterfaceDecl *OI = OMD->getClassInterface();
2545 CGM.getContext().CollectObjCIvars(OI, RecFields);
2546 if (RecFields.empty())
2547 return 0;
2548 BuildAggrIvarLayout (0, RecFields, 0, ForStrongLayout,
2549 iIndex, iSkIndex, hasUnion);
2550 return 0;
2551}
2552
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00002553llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbar5eec6142008-08-12 03:39:23 +00002554 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
2555
2556 if (!Entry) {
Chris Lattner3a8f2942008-11-24 03:33:13 +00002557 // FIXME: Avoid std::string copying.
2558 llvm::Constant *C = llvm::ConstantArray::get(Sel.getAsString());
Daniel Dunbar5eec6142008-08-12 03:39:23 +00002559 Entry =
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002560 new llvm::GlobalVariable(C->getType(), false,
Daniel Dunbar5eec6142008-08-12 03:39:23 +00002561 llvm::GlobalValue::InternalLinkage,
2562 C, "\01L_OBJC_METH_VAR_NAME_",
2563 &CGM.getModule());
2564 Entry->setSection("__TEXT,__cstring,cstring_literals");
2565 UsedGlobals.push_back(Entry);
2566 }
2567
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002568 return getConstantGEP(Entry, 0, 0);
2569}
2570
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002571// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00002572llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002573 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
2574}
2575
2576// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00002577llvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002578 return GetMethodVarName(&CGM.getContext().Idents.get(Name));
2579}
2580
Devang Patel593a07a2009-03-04 18:21:39 +00002581llvm::Constant *CGObjCCommonMac::GetMethodVarType(FieldDecl *Field) {
2582 std::string TypeStr;
2583 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
2584
2585 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002586
2587 if (!Entry) {
Devang Patel593a07a2009-03-04 18:21:39 +00002588 llvm::Constant *C = llvm::ConstantArray::get(TypeStr);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002589 Entry =
2590 new llvm::GlobalVariable(C->getType(), false,
2591 llvm::GlobalValue::InternalLinkage,
2592 C, "\01L_OBJC_METH_VAR_TYPE_",
2593 &CGM.getModule());
2594 Entry->setSection("__TEXT,__cstring,cstring_literals");
2595 UsedGlobals.push_back(Entry);
2596 }
2597
2598 return getConstantGEP(Entry, 0, 0);
Daniel Dunbar5eec6142008-08-12 03:39:23 +00002599}
2600
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00002601llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002602 std::string TypeStr;
Daniel Dunbar12996f52008-08-26 21:51:14 +00002603 CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
2604 TypeStr);
Devang Patel593a07a2009-03-04 18:21:39 +00002605
2606 llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
2607
2608 if (!Entry) {
2609 llvm::Constant *C = llvm::ConstantArray::get(TypeStr);
2610 Entry =
2611 new llvm::GlobalVariable(C->getType(), false,
2612 llvm::GlobalValue::InternalLinkage,
2613 C, "\01L_OBJC_METH_VAR_TYPE_",
2614 &CGM.getModule());
2615 Entry->setSection("__TEXT,__cstring,cstring_literals");
2616 UsedGlobals.push_back(Entry);
2617 }
2618
2619 return getConstantGEP(Entry, 0, 0);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002620}
2621
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00002622// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00002623llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00002624 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
2625
2626 if (!Entry) {
2627 llvm::Constant *C = llvm::ConstantArray::get(Ident->getName());
2628 Entry =
2629 new llvm::GlobalVariable(C->getType(), false,
2630 llvm::GlobalValue::InternalLinkage,
2631 C, "\01L_OBJC_PROP_NAME_ATTR_",
2632 &CGM.getModule());
2633 Entry->setSection("__TEXT,__cstring,cstring_literals");
2634 UsedGlobals.push_back(Entry);
2635 }
2636
2637 return getConstantGEP(Entry, 0, 0);
2638}
2639
2640// FIXME: Merge into a single cstring creation function.
Daniel Dunbar698d6f32008-08-28 04:38:10 +00002641// FIXME: This Decl should be more precise.
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00002642llvm::Constant *CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
Daniel Dunbar698d6f32008-08-28 04:38:10 +00002643 const Decl *Container) {
2644 std::string TypeStr;
2645 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00002646 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
2647}
2648
Fariborz Jahanian32b5ea22009-01-21 23:34:32 +00002649void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
2650 const ObjCContainerDecl *CD,
2651 std::string &NameOut) {
Daniel Dunbarace33292008-08-16 03:19:19 +00002652 // FIXME: Find the mangling GCC uses.
Douglas Gregor5d764842009-01-09 17:18:27 +00002653 NameOut = (D->isInstanceMethod() ? "-" : "+");
Chris Lattner3a8f2942008-11-24 03:33:13 +00002654 NameOut += '[';
Fariborz Jahanian0adaa8a2009-01-10 21:06:09 +00002655 assert (CD && "Missing container decl in GetNameForMethod");
2656 NameOut += CD->getNameAsString();
Fariborz Jahanianc6f0c212009-01-26 23:49:05 +00002657 // FIXME. For a method in a category, (CAT_NAME) is inserted here.
2658 // Right now! there is not enough info. to do this.
Chris Lattner3a8f2942008-11-24 03:33:13 +00002659 NameOut += ' ';
2660 NameOut += D->getSelector().getAsString();
2661 NameOut += ']';
Daniel Dunbarace33292008-08-16 03:19:19 +00002662}
2663
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00002664/// GetFirstIvarInRecord - This routine returns the record for the
2665/// implementation of the fiven class OID. It also returns field
2666/// corresponding to the first ivar in the class in FIV. It also
2667/// returns the one before the first ivar.
2668///
2669const RecordDecl *CGObjCCommonMac::GetFirstIvarInRecord(
2670 const ObjCInterfaceDecl *OID,
2671 RecordDecl::field_iterator &FIV,
2672 RecordDecl::field_iterator &PIV) {
2673 int countSuperClassIvars = countInheritedIvars(OID->getSuperClass());
2674 const RecordDecl *RD = CGM.getContext().addRecordToClass(OID);
2675 RecordDecl::field_iterator ifield = RD->field_begin();
2676 RecordDecl::field_iterator pfield = RD->field_end();
2677 while (countSuperClassIvars-- > 0) {
2678 pfield = ifield;
2679 ++ifield;
2680 }
2681 FIV = ifield;
2682 PIV = pfield;
2683 return RD;
2684}
2685
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002686void CGObjCMac::FinishModule() {
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002687 EmitModuleInfo();
2688
Daniel Dunbar35b777f2008-10-29 22:36:39 +00002689 // Emit the dummy bodies for any protocols which were referenced but
2690 // never defined.
2691 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
2692 i = Protocols.begin(), e = Protocols.end(); i != e; ++i) {
2693 if (i->second->hasInitializer())
2694 continue;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002695
Daniel Dunbar35b777f2008-10-29 22:36:39 +00002696 std::vector<llvm::Constant*> Values(5);
2697 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
2698 Values[1] = GetClassName(i->first);
2699 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
2700 Values[3] = Values[4] =
2701 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
2702 i->second->setLinkage(llvm::GlobalValue::InternalLinkage);
2703 i->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
2704 Values));
2705 }
2706
2707 std::vector<llvm::Constant*> Used;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002708 for (std::vector<llvm::GlobalVariable*>::iterator i = UsedGlobals.begin(),
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002709 e = UsedGlobals.end(); i != e; ++i) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002710 Used.push_back(llvm::ConstantExpr::getBitCast(*i, ObjCTypes.Int8PtrTy));
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002711 }
2712
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002713 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Used.size());
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002714 llvm::GlobalValue *GV =
2715 new llvm::GlobalVariable(AT, false,
2716 llvm::GlobalValue::AppendingLinkage,
2717 llvm::ConstantArray::get(AT, Used),
2718 "llvm.used",
2719 &CGM.getModule());
2720
2721 GV->setSection("llvm.metadata");
Daniel Dunbar8ede0052008-08-25 06:02:07 +00002722
2723 // Add assembler directives to add lazy undefined symbol references
2724 // for classes which are referenced but not defined. This is
2725 // important for correct linker interaction.
2726
2727 // FIXME: Uh, this isn't particularly portable.
2728 std::stringstream s;
Anders Carlsson63f98352008-12-10 02:21:04 +00002729
2730 if (!CGM.getModule().getModuleInlineAsm().empty())
2731 s << "\n";
2732
Daniel Dunbar8ede0052008-08-25 06:02:07 +00002733 for (std::set<IdentifierInfo*>::iterator i = LazySymbols.begin(),
2734 e = LazySymbols.end(); i != e; ++i) {
2735 s << "\t.lazy_reference .objc_class_name_" << (*i)->getName() << "\n";
2736 }
2737 for (std::set<IdentifierInfo*>::iterator i = DefinedSymbols.begin(),
2738 e = DefinedSymbols.end(); i != e; ++i) {
Daniel Dunbar698d6f32008-08-28 04:38:10 +00002739 s << "\t.objc_class_name_" << (*i)->getName() << "=0\n"
Daniel Dunbar8ede0052008-08-25 06:02:07 +00002740 << "\t.globl .objc_class_name_" << (*i)->getName() << "\n";
2741 }
Anders Carlsson63f98352008-12-10 02:21:04 +00002742
Daniel Dunbar8ede0052008-08-25 06:02:07 +00002743 CGM.getModule().appendModuleInlineAsm(s.str());
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002744}
2745
Fariborz Jahaniand0374812009-01-22 23:02:58 +00002746CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian48543f52009-01-21 22:04:16 +00002747 : CGObjCCommonMac(cgm),
2748 ObjCTypes(cgm)
2749{
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00002750 ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
Fariborz Jahanian48543f52009-01-21 22:04:16 +00002751 ObjCABI = 2;
2752}
2753
Daniel Dunbar1be1df32008-08-11 21:35:06 +00002754/* *** */
2755
Fariborz Jahanian48543f52009-01-21 22:04:16 +00002756ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
2757: CGM(cgm)
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00002758{
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002759 CodeGen::CodeGenTypes &Types = CGM.getTypes();
2760 ASTContext &Ctx = CGM.getContext();
Fariborz Jahanian48543f52009-01-21 22:04:16 +00002761
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002762 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002763 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002764 LongTy = Types.ConvertType(Ctx.LongTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002765 Int8PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
2766
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002767 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Fariborz Jahanianc192d4d2008-11-18 20:18:11 +00002768 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002769 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002770
2771 // FIXME: It would be nice to unify this with the opaque type, so
2772 // that the IR comes out a bit cleaner.
2773 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
2774 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Fariborz Jahanian48543f52009-01-21 22:04:16 +00002775
2776 // I'm not sure I like this. The implicit coordination is a bit
2777 // gross. We should solve this in a reasonable fashion because this
2778 // is a pretty common task (match some runtime data structure with
2779 // an LLVM data structure).
2780
2781 // FIXME: This is leaked.
2782 // FIXME: Merge with rewriter code?
2783
2784 // struct _objc_super {
2785 // id self;
2786 // Class cls;
2787 // }
2788 RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
2789 SourceLocation(),
2790 &Ctx.Idents.get("_objc_super"));
2791 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
2792 Ctx.getObjCIdType(), 0, false));
2793 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
2794 Ctx.getObjCClassType(), 0, false));
2795 RD->completeDefinition(Ctx);
2796
2797 SuperCTy = Ctx.getTagDeclType(RD);
2798 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
2799
2800 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Fariborz Jahanian4b161702009-01-22 00:37:21 +00002801 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
2802
Fariborz Jahaniand0374812009-01-22 23:02:58 +00002803 // struct _prop_t {
2804 // char *name;
2805 // char *attributes;
2806 // }
2807 PropertyTy = llvm::StructType::get(Int8PtrTy,
2808 Int8PtrTy,
2809 NULL);
2810 CGM.getModule().addTypeName("struct._prop_t",
2811 PropertyTy);
2812
2813 // struct _prop_list_t {
Fariborz Jahanian781f2732009-01-23 01:46:23 +00002814 // uint32_t entsize; // sizeof(struct _prop_t)
Fariborz Jahaniand0374812009-01-22 23:02:58 +00002815 // uint32_t count_of_properties;
Fariborz Jahanian781f2732009-01-23 01:46:23 +00002816 // struct _prop_t prop_list[count_of_properties];
Fariborz Jahaniand0374812009-01-22 23:02:58 +00002817 // }
2818 PropertyListTy = llvm::StructType::get(IntTy,
2819 IntTy,
2820 llvm::ArrayType::get(PropertyTy, 0),
2821 NULL);
2822 CGM.getModule().addTypeName("struct._prop_list_t",
2823 PropertyListTy);
2824 // struct _prop_list_t *
2825 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
2826
2827 // struct _objc_method {
2828 // SEL _cmd;
2829 // char *method_type;
2830 // char *_imp;
2831 // }
2832 MethodTy = llvm::StructType::get(SelectorPtrTy,
2833 Int8PtrTy,
2834 Int8PtrTy,
2835 NULL);
2836 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
Fariborz Jahanian781f2732009-01-23 01:46:23 +00002837
2838 // struct _objc_cache *
2839 CacheTy = llvm::OpaqueType::get();
2840 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
2841 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
Fariborz Jahaniand0374812009-01-22 23:02:58 +00002842
Fariborz Jahanian4b161702009-01-22 00:37:21 +00002843 // Property manipulation functions.
Daniel Dunbardac29922009-02-04 00:44:42 +00002844
2845 QualType IdType = Ctx.getObjCIdType();
2846 QualType SelType = Ctx.getObjCSelType();
2847 llvm::SmallVector<QualType,16> Params;
2848 const llvm::FunctionType *FTy;
Fariborz Jahanian4b161702009-01-22 00:37:21 +00002849
2850 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
Daniel Dunbardac29922009-02-04 00:44:42 +00002851 Params.push_back(IdType);
2852 Params.push_back(SelType);
2853 Params.push_back(Ctx.LongTy);
2854 Params.push_back(Ctx.BoolTy);
2855 FTy = Types.GetFunctionType(Types.getFunctionInfo(IdType, Params),
2856 false);
2857 GetPropertyFn = CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
Fariborz Jahanian4b161702009-01-22 00:37:21 +00002858
2859 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
2860 Params.clear();
Daniel Dunbardac29922009-02-04 00:44:42 +00002861 Params.push_back(IdType);
2862 Params.push_back(SelType);
2863 Params.push_back(Ctx.LongTy);
2864 Params.push_back(IdType);
2865 Params.push_back(Ctx.BoolTy);
2866 Params.push_back(Ctx.BoolTy);
2867 FTy = Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
2868 SetPropertyFn = CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
2869
Fariborz Jahanian4b161702009-01-22 00:37:21 +00002870 // Enumeration mutation.
Daniel Dunbardac29922009-02-04 00:44:42 +00002871
2872 // void objc_enumerationMutation (id)
Fariborz Jahanian4b161702009-01-22 00:37:21 +00002873 Params.clear();
Daniel Dunbardac29922009-02-04 00:44:42 +00002874 Params.push_back(IdType);
2875 FTy = Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
2876 EnumerationMutationFn = CGM.CreateRuntimeFunction(FTy,
2877 "objc_enumerationMutation");
Fariborz Jahanian4b161702009-01-22 00:37:21 +00002878
2879 // gc's API
2880 // id objc_read_weak (id *)
2881 Params.clear();
Daniel Dunbardac29922009-02-04 00:44:42 +00002882 Params.push_back(Ctx.getPointerType(IdType));
2883 FTy = Types.GetFunctionType(Types.getFunctionInfo(IdType, Params), false);
2884 GcReadWeakFn = CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
2885
2886 // id objc_assign_weak (id, id *)
Fariborz Jahanian4b161702009-01-22 00:37:21 +00002887 Params.clear();
Daniel Dunbardac29922009-02-04 00:44:42 +00002888 Params.push_back(IdType);
2889 Params.push_back(Ctx.getPointerType(IdType));
2890
2891 FTy = Types.GetFunctionType(Types.getFunctionInfo(IdType, Params), false);
2892 GcAssignWeakFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
2893 GcAssignGlobalFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
2894 GcAssignIvarFn = CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
2895 GcAssignStrongCastFn =
2896 CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
Anders Carlsson1cf75362009-02-16 22:59:18 +00002897
2898 // void objc_exception_throw(id)
2899 Params.clear();
2900 Params.push_back(IdType);
2901
2902 FTy = Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
Anders Carlsson1cf75362009-02-16 22:59:18 +00002903 ExceptionThrowFn =
2904 CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
Daniel Dunbar34416d62009-02-24 01:43:46 +00002905
2906 // synchronized APIs
2907 // void objc_sync_enter (id)
2908 // void objc_sync_exit (id)
2909 Params.clear();
2910 Params.push_back(IdType);
2911
2912 FTy = Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params), false);
2913 SyncEnterFn = CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
2914 SyncExitFn = CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
Fariborz Jahanian48543f52009-01-21 22:04:16 +00002915}
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00002916
Fariborz Jahanian48543f52009-01-21 22:04:16 +00002917ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
2918 : ObjCCommonTypesHelper(cgm)
2919{
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00002920 // struct _objc_method_description {
2921 // SEL name;
2922 // char *types;
2923 // }
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002924 MethodDescriptionTy =
2925 llvm::StructType::get(SelectorPtrTy,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002926 Int8PtrTy,
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002927 NULL);
2928 CGM.getModule().addTypeName("struct._objc_method_description",
2929 MethodDescriptionTy);
2930
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00002931 // struct _objc_method_description_list {
2932 // int count;
2933 // struct _objc_method_description[1];
2934 // }
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002935 MethodDescriptionListTy =
2936 llvm::StructType::get(IntTy,
2937 llvm::ArrayType::get(MethodDescriptionTy, 0),
2938 NULL);
2939 CGM.getModule().addTypeName("struct._objc_method_description_list",
2940 MethodDescriptionListTy);
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00002941
2942 // struct _objc_method_description_list *
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002943 MethodDescriptionListPtrTy =
2944 llvm::PointerType::getUnqual(MethodDescriptionListTy);
2945
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002946 // Protocol description structures
2947
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00002948 // struct _objc_protocol_extension {
2949 // uint32_t size; // sizeof(struct _objc_protocol_extension)
2950 // struct _objc_method_description_list *optional_instance_methods;
2951 // struct _objc_method_description_list *optional_class_methods;
2952 // struct _objc_property_list *instance_properties;
2953 // }
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002954 ProtocolExtensionTy =
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00002955 llvm::StructType::get(IntTy,
2956 MethodDescriptionListPtrTy,
2957 MethodDescriptionListPtrTy,
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002958 PropertyListPtrTy,
2959 NULL);
2960 CGM.getModule().addTypeName("struct._objc_protocol_extension",
2961 ProtocolExtensionTy);
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00002962
2963 // struct _objc_protocol_extension *
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002964 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
2965
Daniel Dunbar35b777f2008-10-29 22:36:39 +00002966 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002967
2968 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get();
2969 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get();
2970
Fariborz Jahanian48543f52009-01-21 22:04:16 +00002971 const llvm::Type *T =
2972 llvm::StructType::get(llvm::PointerType::getUnqual(ProtocolListTyHolder),
2973 LongTy,
2974 llvm::ArrayType::get(ProtocolTyHolder, 0),
2975 NULL);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002976 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
2977
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00002978 // struct _objc_protocol {
2979 // struct _objc_protocol_extension *isa;
2980 // char *protocol_name;
2981 // struct _objc_protocol **_objc_protocol_list;
2982 // struct _objc_method_description_list *instance_methods;
2983 // struct _objc_method_description_list *class_methods;
2984 // }
2985 T = llvm::StructType::get(ProtocolExtensionPtrTy,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002986 Int8PtrTy,
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002987 llvm::PointerType::getUnqual(ProtocolListTyHolder),
2988 MethodDescriptionListPtrTy,
2989 MethodDescriptionListPtrTy,
2990 NULL);
2991 cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
2992
2993 ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
2994 CGM.getModule().addTypeName("struct._objc_protocol_list",
2995 ProtocolListTy);
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00002996 // struct _objc_protocol_list *
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002997 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
2998
2999 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003000 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00003001 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003002
3003 // Class description structures
3004
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003005 // struct _objc_ivar {
3006 // char *ivar_name;
3007 // char *ivar_type;
3008 // int ivar_offset;
3009 // }
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003010 IvarTy = llvm::StructType::get(Int8PtrTy,
3011 Int8PtrTy,
3012 IntTy,
3013 NULL);
3014 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
3015
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003016 // struct _objc_ivar_list *
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003017 IvarListTy = llvm::OpaqueType::get();
3018 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
3019 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
3020
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003021 // struct _objc_method_list *
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003022 MethodListTy = llvm::OpaqueType::get();
3023 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
3024 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
3025
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003026 // struct _objc_class_extension *
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003027 ClassExtensionTy =
3028 llvm::StructType::get(IntTy,
3029 Int8PtrTy,
3030 PropertyListPtrTy,
3031 NULL);
3032 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
3033 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
3034
3035 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get();
3036
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003037 // struct _objc_class {
3038 // Class isa;
3039 // Class super_class;
3040 // char *name;
3041 // long version;
3042 // long info;
3043 // long instance_size;
3044 // struct _objc_ivar_list *ivars;
3045 // struct _objc_method_list *methods;
3046 // struct _objc_cache *cache;
3047 // struct _objc_protocol_list *protocols;
3048 // char *ivar_layout;
3049 // struct _objc_class_ext *ext;
3050 // };
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003051 T = llvm::StructType::get(llvm::PointerType::getUnqual(ClassTyHolder),
3052 llvm::PointerType::getUnqual(ClassTyHolder),
3053 Int8PtrTy,
3054 LongTy,
3055 LongTy,
3056 LongTy,
3057 IvarListPtrTy,
3058 MethodListPtrTy,
3059 CachePtrTy,
3060 ProtocolListPtrTy,
3061 Int8PtrTy,
3062 ClassExtensionPtrTy,
3063 NULL);
3064 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
3065
3066 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
3067 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
3068 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
3069
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003070 // struct _objc_category {
3071 // char *category_name;
3072 // char *class_name;
3073 // struct _objc_method_list *instance_method;
3074 // struct _objc_method_list *class_method;
3075 // uint32_t size; // sizeof(struct _objc_category)
3076 // struct _objc_property_list *instance_properties;// category's @property
3077 // }
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00003078 CategoryTy = llvm::StructType::get(Int8PtrTy,
3079 Int8PtrTy,
3080 MethodListPtrTy,
3081 MethodListPtrTy,
3082 ProtocolListPtrTy,
3083 IntTy,
3084 PropertyListPtrTy,
3085 NULL);
3086 CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
3087
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003088 // Global metadata structures
3089
Fariborz Jahanianb5048aa2009-01-21 00:39:53 +00003090 // struct _objc_symtab {
3091 // long sel_ref_cnt;
3092 // SEL *refs;
3093 // short cls_def_cnt;
3094 // short cat_def_cnt;
3095 // char *defs[cls_def_cnt + cat_def_cnt];
3096 // }
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003097 SymtabTy = llvm::StructType::get(LongTy,
3098 SelectorPtrTy,
3099 ShortTy,
3100 ShortTy,
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00003101 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003102 NULL);
3103 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
3104 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
3105
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003106 // struct _objc_module {
3107 // long version;
3108 // long size; // sizeof(struct _objc_module)
3109 // char *name;
3110 // struct _objc_symtab* symtab;
3111 // }
Daniel Dunbarb050fa62008-08-21 04:36:09 +00003112 ModuleTy =
3113 llvm::StructType::get(LongTy,
3114 LongTy,
3115 Int8PtrTy,
3116 SymtabPtrTy,
3117 NULL);
3118 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003119
Daniel Dunbarf7103722008-09-24 03:38:44 +00003120 // Message send functions.
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003121
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003122 // id objc_msgSend (id, SEL, ...)
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003123 std::vector<const llvm::Type*> Params;
3124 Params.push_back(ObjectPtrTy);
3125 Params.push_back(SelectorPtrTy);
Daniel Dunbar4e19f4e2008-10-01 01:06:06 +00003126 MessageSendFn =
3127 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3128 Params,
3129 true),
3130 "objc_msgSend");
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003131
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003132 // id objc_msgSend_stret (id, SEL, ...)
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003133 Params.clear();
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003134 Params.push_back(ObjectPtrTy);
3135 Params.push_back(SelectorPtrTy);
3136 MessageSendStretFn =
Daniel Dunbar4e19f4e2008-10-01 01:06:06 +00003137 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
3138 Params,
3139 true),
3140 "objc_msgSend_stret");
Daniel Dunbaraecef4c2008-10-17 03:24:53 +00003141
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003142 //
Daniel Dunbaraecef4c2008-10-17 03:24:53 +00003143 Params.clear();
3144 Params.push_back(ObjectPtrTy);
3145 Params.push_back(SelectorPtrTy);
3146 // FIXME: This should be long double on x86_64?
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003147 // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
Daniel Dunbaraecef4c2008-10-17 03:24:53 +00003148 MessageSendFpretFn =
3149 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::DoubleTy,
3150 Params,
3151 true),
3152 "objc_msgSend_fpret");
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003153
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003154 // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003155 Params.clear();
3156 Params.push_back(SuperPtrTy);
3157 Params.push_back(SelectorPtrTy);
3158 MessageSendSuperFn =
Daniel Dunbar4e19f4e2008-10-01 01:06:06 +00003159 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3160 Params,
3161 true),
3162 "objc_msgSendSuper");
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003163
Fariborz Jahanian4b161702009-01-22 00:37:21 +00003164 // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
3165 // SEL op, ...)
Daniel Dunbar87062ff2008-08-23 09:25:55 +00003166 Params.clear();
3167 Params.push_back(Int8PtrTy);
3168 Params.push_back(SuperPtrTy);
3169 Params.push_back(SelectorPtrTy);
3170 MessageSendSuperStretFn =
Daniel Dunbar4e19f4e2008-10-01 01:06:06 +00003171 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
3172 Params,
3173 true),
3174 "objc_msgSendSuper_stret");
Daniel Dunbaraecef4c2008-10-17 03:24:53 +00003175
3176 // There is no objc_msgSendSuper_fpret? How can that work?
3177 MessageSendSuperFpretFn = MessageSendSuperFn;
Anders Carlsson58d16242008-08-31 04:05:03 +00003178
Anders Carlsson9acb0a42008-09-09 10:10:21 +00003179 // FIXME: This is the size of the setjmp buffer and should be
3180 // target specific. 18 is what's used on 32-bit X86.
3181 uint64_t SetJmpBufferSize = 18;
3182
3183 // Exceptions
3184 const llvm::Type *StackPtrTy =
Daniel Dunbar1c5e4632008-09-27 06:32:25 +00003185 llvm::ArrayType::get(llvm::PointerType::getUnqual(llvm::Type::Int8Ty), 4);
Anders Carlsson9acb0a42008-09-09 10:10:21 +00003186
3187 ExceptionDataTy =
3188 llvm::StructType::get(llvm::ArrayType::get(llvm::Type::Int32Ty,
3189 SetJmpBufferSize),
3190 StackPtrTy, NULL);
3191 CGM.getModule().addTypeName("struct._objc_exception_data",
3192 ExceptionDataTy);
3193
3194 Params.clear();
Anders Carlsson9acb0a42008-09-09 10:10:21 +00003195 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
3196 ExceptionTryEnterFn =
Daniel Dunbar4e19f4e2008-10-01 01:06:06 +00003197 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
3198 Params,
3199 false),
3200 "objc_exception_try_enter");
Anders Carlsson9acb0a42008-09-09 10:10:21 +00003201 ExceptionTryExitFn =
Daniel Dunbar4e19f4e2008-10-01 01:06:06 +00003202 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
3203 Params,
3204 false),
3205 "objc_exception_try_exit");
Anders Carlsson9acb0a42008-09-09 10:10:21 +00003206 ExceptionExtractFn =
Daniel Dunbar4e19f4e2008-10-01 01:06:06 +00003207 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3208 Params,
3209 false),
3210 "objc_exception_extract");
Anders Carlsson9acb0a42008-09-09 10:10:21 +00003211
3212 Params.clear();
3213 Params.push_back(ClassPtrTy);
3214 Params.push_back(ObjectPtrTy);
3215 ExceptionMatchFn =
Daniel Dunbar4e19f4e2008-10-01 01:06:06 +00003216 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty,
3217 Params,
3218 false),
3219 "objc_exception_match");
Chris Lattnerdd978702008-11-15 21:26:17 +00003220
Anders Carlsson9acb0a42008-09-09 10:10:21 +00003221 Params.clear();
3222 Params.push_back(llvm::PointerType::getUnqual(llvm::Type::Int32Ty));
3223 SetJmpFn =
Daniel Dunbar4e19f4e2008-10-01 01:06:06 +00003224 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty,
3225 Params,
3226 false),
3227 "_setjmp");
Fariborz Jahanianc192d4d2008-11-18 20:18:11 +00003228
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00003229}
3230
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003231ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Fariborz Jahanian48543f52009-01-21 22:04:16 +00003232: ObjCCommonTypesHelper(cgm)
3233{
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003234 // struct _method_list_t {
3235 // uint32_t entsize; // sizeof(struct _objc_method)
3236 // uint32_t method_count;
3237 // struct _objc_method method_list[method_count];
3238 // }
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003239 MethodListnfABITy = llvm::StructType::get(IntTy,
3240 IntTy,
3241 llvm::ArrayType::get(MethodTy, 0),
3242 NULL);
3243 CGM.getModule().addTypeName("struct.__method_list_t",
3244 MethodListnfABITy);
3245 // struct method_list_t *
3246 MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003247
3248 // struct _protocol_t {
3249 // id isa; // NULL
3250 // const char * const protocol_name;
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003251 // const struct _protocol_list_t * protocol_list; // super protocols
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003252 // const struct method_list_t * const instance_methods;
3253 // const struct method_list_t * const class_methods;
3254 // const struct method_list_t *optionalInstanceMethods;
3255 // const struct method_list_t *optionalClassMethods;
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003256 // const struct _prop_list_t * properties;
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003257 // const uint32_t size; // sizeof(struct _protocol_t)
3258 // const uint32_t flags; // = 0
3259 // }
3260
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003261 // Holder for struct _protocol_list_t *
3262 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get();
3263
3264 ProtocolnfABITy = llvm::StructType::get(ObjectPtrTy,
3265 Int8PtrTy,
3266 llvm::PointerType::getUnqual(
3267 ProtocolListTyHolder),
3268 MethodListnfABIPtrTy,
3269 MethodListnfABIPtrTy,
3270 MethodListnfABIPtrTy,
3271 MethodListnfABIPtrTy,
3272 PropertyListPtrTy,
3273 IntTy,
3274 IntTy,
3275 NULL);
3276 CGM.getModule().addTypeName("struct._protocol_t",
3277 ProtocolnfABITy);
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00003278
3279 // struct _protocol_t*
3280 ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003281
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00003282 // struct _protocol_list_t {
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003283 // long protocol_count; // Note, this is 32/64 bit
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00003284 // struct _protocol_t *[protocol_count];
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003285 // }
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003286 ProtocolListnfABITy = llvm::StructType::get(LongTy,
3287 llvm::ArrayType::get(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00003288 ProtocolnfABIPtrTy, 0),
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003289 NULL);
3290 CGM.getModule().addTypeName("struct._objc_protocol_list",
3291 ProtocolListnfABITy);
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00003292 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
3293 ProtocolListnfABITy);
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003294
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003295 // struct _objc_protocol_list*
3296 ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003297
3298 // struct _ivar_t {
3299 // unsigned long int *offset; // pointer to ivar offset location
3300 // char *name;
3301 // char *type;
3302 // uint32_t alignment;
3303 // uint32_t size;
3304 // }
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003305 IvarnfABITy = llvm::StructType::get(llvm::PointerType::getUnqual(LongTy),
3306 Int8PtrTy,
3307 Int8PtrTy,
3308 IntTy,
3309 IntTy,
3310 NULL);
3311 CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
3312
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003313 // struct _ivar_list_t {
3314 // uint32 entsize; // sizeof(struct _ivar_t)
3315 // uint32 count;
3316 // struct _iver_t list[count];
3317 // }
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003318 IvarListnfABITy = llvm::StructType::get(IntTy,
3319 IntTy,
3320 llvm::ArrayType::get(
3321 IvarnfABITy, 0),
3322 NULL);
3323 CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
3324
3325 IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003326
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003327 // struct _class_ro_t {
Fariborz Jahaniand0374812009-01-22 23:02:58 +00003328 // uint32_t const flags;
3329 // uint32_t const instanceStart;
3330 // uint32_t const instanceSize;
3331 // uint32_t const reserved; // only when building for 64bit targets
3332 // const uint8_t * const ivarLayout;
3333 // const char *const name;
3334 // const struct _method_list_t * const baseMethods;
3335 // const struct _objc_protocol_list *const baseProtocols;
3336 // const struct _ivar_list_t *const ivars;
3337 // const uint8_t * const weakIvarLayout;
3338 // const struct _prop_list_t * const properties;
3339 // }
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003340
3341 // FIXME. Add 'reserved' field in 64bit abi mode!
3342 ClassRonfABITy = llvm::StructType::get(IntTy,
3343 IntTy,
3344 IntTy,
3345 Int8PtrTy,
3346 Int8PtrTy,
3347 MethodListnfABIPtrTy,
3348 ProtocolListnfABIPtrTy,
3349 IvarListnfABIPtrTy,
3350 Int8PtrTy,
3351 PropertyListPtrTy,
3352 NULL);
3353 CGM.getModule().addTypeName("struct._class_ro_t",
3354 ClassRonfABITy);
3355
3356 // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
3357 std::vector<const llvm::Type*> Params;
3358 Params.push_back(ObjectPtrTy);
3359 Params.push_back(SelectorPtrTy);
3360 ImpnfABITy = llvm::PointerType::getUnqual(
3361 llvm::FunctionType::get(ObjectPtrTy, Params, false));
3362
3363 // struct _class_t {
3364 // struct _class_t *isa;
3365 // struct _class_t * const superclass;
3366 // void *cache;
3367 // IMP *vtable;
3368 // struct class_ro_t *ro;
3369 // }
3370
3371 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get();
3372 ClassnfABITy = llvm::StructType::get(llvm::PointerType::getUnqual(ClassTyHolder),
3373 llvm::PointerType::getUnqual(ClassTyHolder),
3374 CachePtrTy,
3375 llvm::PointerType::getUnqual(ImpnfABITy),
3376 llvm::PointerType::getUnqual(
3377 ClassRonfABITy),
3378 NULL);
3379 CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
3380
3381 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
3382 ClassnfABITy);
3383
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003384 // LLVM for struct _class_t *
3385 ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
3386
Fariborz Jahanian781f2732009-01-23 01:46:23 +00003387 // struct _category_t {
3388 // const char * const name;
3389 // struct _class_t *const cls;
3390 // const struct _method_list_t * const instance_methods;
3391 // const struct _method_list_t * const class_methods;
3392 // const struct _protocol_list_t * const protocols;
3393 // const struct _prop_list_t * const properties;
Fariborz Jahanianb9459b72009-01-23 17:41:22 +00003394 // }
3395 CategorynfABITy = llvm::StructType::get(Int8PtrTy,
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003396 ClassnfABIPtrTy,
Fariborz Jahanianb9459b72009-01-23 17:41:22 +00003397 MethodListnfABIPtrTy,
3398 MethodListnfABIPtrTy,
3399 ProtocolListnfABIPtrTy,
3400 PropertyListPtrTy,
3401 NULL);
3402 CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003403
3404 // New types for nonfragile abi messaging.
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00003405 CodeGen::CodeGenTypes &Types = CGM.getTypes();
3406 ASTContext &Ctx = CGM.getContext();
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003407
3408 // MessageRefTy - LLVM for:
3409 // struct _message_ref_t {
3410 // IMP messenger;
3411 // SEL name;
3412 // };
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00003413
3414 // First the clang type for struct _message_ref_t
3415 RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
3416 SourceLocation(),
3417 &Ctx.Idents.get("_message_ref_t"));
3418 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
3419 Ctx.VoidPtrTy, 0, false));
3420 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
3421 Ctx.getObjCSelType(), 0, false));
3422 RD->completeDefinition(Ctx);
3423
3424 MessageRefCTy = Ctx.getTagDeclType(RD);
3425 MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
3426 MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003427
3428 // MessageRefPtrTy - LLVM for struct _message_ref_t*
3429 MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
3430
3431 // SuperMessageRefTy - LLVM for:
3432 // struct _super_message_ref_t {
3433 // SUPER_IMP messenger;
3434 // SEL name;
3435 // };
3436 SuperMessageRefTy = llvm::StructType::get(ImpnfABITy,
3437 SelectorPtrTy,
3438 NULL);
3439 CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
3440
3441 // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
3442 SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
3443
3444 // id objc_msgSend_fixup (id, struct message_ref_t*, ...)
3445 Params.clear();
3446 Params.push_back(ObjectPtrTy);
3447 Params.push_back(MessageRefPtrTy);
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00003448 MessengerTy = llvm::FunctionType::get(ObjectPtrTy,
3449 Params,
3450 true);
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003451 MessageSendFixupFn =
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00003452 CGM.CreateRuntimeFunction(MessengerTy,
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003453 "objc_msgSend_fixup");
3454
3455 // id objc_msgSend_fpret_fixup (id, struct message_ref_t*, ...)
3456 MessageSendFpretFixupFn =
3457 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3458 Params,
3459 true),
3460 "objc_msgSend_fpret_fixup");
3461
3462 // id objc_msgSend_stret_fixup (id, struct message_ref_t*, ...)
3463 MessageSendStretFixupFn =
3464 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3465 Params,
3466 true),
3467 "objc_msgSend_stret_fixup");
3468
3469 // id objc_msgSendId_fixup (id, struct message_ref_t*, ...)
3470 MessageSendIdFixupFn =
3471 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3472 Params,
3473 true),
3474 "objc_msgSendId_fixup");
3475
3476
3477 // id objc_msgSendId_stret_fixup (id, struct message_ref_t*, ...)
3478 MessageSendIdStretFixupFn =
3479 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3480 Params,
3481 true),
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00003482 "objc_msgSendId_stret_fixup");
Fariborz Jahanian711e8dd2009-02-03 23:49:23 +00003483
3484 // id objc_msgSendSuper2_fixup (struct objc_super *,
3485 // struct _super_message_ref_t*, ...)
3486 Params.clear();
3487 Params.push_back(SuperPtrTy);
3488 Params.push_back(SuperMessageRefPtrTy);
3489 MessageSendSuper2FixupFn =
3490 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3491 Params,
3492 true),
3493 "objc_msgSendSuper2_fixup");
3494
3495
3496 // id objc_msgSendSuper2_stret_fixup (struct objc_super *,
3497 // struct _super_message_ref_t*, ...)
3498 MessageSendSuper2StretFixupFn =
3499 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
3500 Params,
3501 true),
3502 "objc_msgSendSuper2_stret_fixup");
Daniel Dunbar75de89f2009-02-24 07:47:38 +00003503
3504 Params.clear();
3505 llvm::Constant *Personality =
3506 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty,
3507 Params,
3508 true),
3509 "__objc_personality_v0");
3510 EHPersonalityPtr = llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy);
3511
3512 Params.clear();
3513 Params.push_back(Int8PtrTy);
3514 UnwindResumeOrRethrowFn =
3515 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
3516 Params,
3517 false),
3518 "_Unwind_Resume_or_Rethrow");
Daniel Dunbar9c285e72009-03-01 04:46:24 +00003519 ObjCBeginCatchFn =
3520 CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
3521 Params,
3522 false),
3523 "objc_begin_catch");
3524
3525 Params.clear();
3526 ObjCEndCatchFn =
3527 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
3528 Params,
3529 false),
3530 "objc_end_catch");
3531
3532 // struct objc_typeinfo {
3533 // const void** vtable; // objc_ehtype_vtable + 2
3534 // const char* name; // c++ typeinfo string
3535 // Class cls;
3536 // };
3537 EHTypeTy = llvm::StructType::get(llvm::PointerType::getUnqual(Int8PtrTy),
3538 Int8PtrTy,
3539 ClassnfABIPtrTy,
3540 NULL);
Daniel Dunbarc0318b22009-03-02 06:08:11 +00003541 CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
Daniel Dunbar9c285e72009-03-01 04:46:24 +00003542 EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00003543}
3544
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003545llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
3546 FinishNonFragileABIModule();
3547
3548 return NULL;
3549}
3550
3551void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
3552 // nonfragile abi has no module definition.
Fariborz Jahanian11c93dd2009-01-30 20:55:31 +00003553
3554 // Build list of all implemented classe addresses in array
3555 // L_OBJC_LABEL_CLASS_$.
3556 // FIXME. Also generate in L_OBJC_LABEL_NONLAZY_CLASS_$
3557 // list of 'nonlazy' implementations (defined as those with a +load{}
3558 // method!!).
3559 unsigned NumClasses = DefinedClasses.size();
3560 if (NumClasses) {
3561 std::vector<llvm::Constant*> Symbols(NumClasses);
3562 for (unsigned i=0; i<NumClasses; i++)
3563 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
3564 ObjCTypes.Int8PtrTy);
3565 llvm::Constant* Init =
3566 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3567 NumClasses),
3568 Symbols);
3569
3570 llvm::GlobalVariable *GV =
3571 new llvm::GlobalVariable(Init->getType(), false,
3572 llvm::GlobalValue::InternalLinkage,
3573 Init,
3574 "\01L_OBJC_LABEL_CLASS_$",
3575 &CGM.getModule());
Fariborz Jahanianc5a02552009-02-28 00:54:00 +00003576 GV->setAlignment(
3577 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.Int8PtrTy));
Fariborz Jahanian11c93dd2009-01-30 20:55:31 +00003578 GV->setSection("__DATA, __objc_classlist, regular, no_dead_strip");
3579 UsedGlobals.push_back(GV);
3580 }
3581
3582 // Build list of all implemented category addresses in array
3583 // L_OBJC_LABEL_CATEGORY_$.
3584 // FIXME. Also generate in L_OBJC_LABEL_NONLAZY_CATEGORY_$
3585 // list of 'nonlazy' category implementations (defined as those with a +load{}
3586 // method!!).
3587 unsigned NumCategory = DefinedCategories.size();
3588 if (NumCategory) {
3589 std::vector<llvm::Constant*> Symbols(NumCategory);
3590 for (unsigned i=0; i<NumCategory; i++)
3591 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedCategories[i],
3592 ObjCTypes.Int8PtrTy);
3593 llvm::Constant* Init =
3594 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
3595 NumCategory),
3596 Symbols);
3597
3598 llvm::GlobalVariable *GV =
3599 new llvm::GlobalVariable(Init->getType(), false,
3600 llvm::GlobalValue::InternalLinkage,
3601 Init,
3602 "\01L_OBJC_LABEL_CATEGORY_$",
3603 &CGM.getModule());
3604 GV->setSection("__DATA, __objc_catlist, regular, no_dead_strip");
3605 UsedGlobals.push_back(GV);
3606 }
3607
Fariborz Jahanian5b2f5502009-01-30 22:07:48 +00003608 // static int L_OBJC_IMAGE_INFO[2] = { 0, flags };
3609 // FIXME. flags can be 0 | 1 | 2 | 6. For now just use 0
3610 std::vector<llvm::Constant*> Values(2);
3611 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, 0);
Fariborz Jahanian4d7933a2009-02-24 21:08:09 +00003612 unsigned int flags = 0;
Fariborz Jahanian27f58962009-02-24 23:34:44 +00003613 // FIXME: Fix and continue?
3614 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
3615 flags |= eImageInfo_GarbageCollected;
3616 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
3617 flags |= eImageInfo_GCOnly;
Fariborz Jahanian4d7933a2009-02-24 21:08:09 +00003618 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
Fariborz Jahanian5b2f5502009-01-30 22:07:48 +00003619 llvm::Constant* Init = llvm::ConstantArray::get(
3620 llvm::ArrayType::get(ObjCTypes.IntTy, 2),
3621 Values);
3622 llvm::GlobalVariable *IMGV =
3623 new llvm::GlobalVariable(Init->getType(), false,
3624 llvm::GlobalValue::InternalLinkage,
3625 Init,
3626 "\01L_OBJC_IMAGE_INFO",
3627 &CGM.getModule());
3628 IMGV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip");
3629 UsedGlobals.push_back(IMGV);
3630
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003631 std::vector<llvm::Constant*> Used;
3632 for (std::vector<llvm::GlobalVariable*>::iterator i = UsedGlobals.begin(),
3633 e = UsedGlobals.end(); i != e; ++i) {
3634 Used.push_back(llvm::ConstantExpr::getBitCast(*i, ObjCTypes.Int8PtrTy));
3635 }
3636
3637 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Used.size());
3638 llvm::GlobalValue *GV =
3639 new llvm::GlobalVariable(AT, false,
3640 llvm::GlobalValue::AppendingLinkage,
3641 llvm::ConstantArray::get(AT, Used),
3642 "llvm.used",
3643 &CGM.getModule());
3644
3645 GV->setSection("llvm.metadata");
3646
3647}
3648
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003649// Metadata flags
3650enum MetaDataDlags {
3651 CLS = 0x0,
3652 CLS_META = 0x1,
3653 CLS_ROOT = 0x2,
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00003654 OBJC2_CLS_HIDDEN = 0x10,
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003655 CLS_EXCEPTION = 0x20
3656};
3657/// BuildClassRoTInitializer - generate meta-data for:
3658/// struct _class_ro_t {
3659/// uint32_t const flags;
3660/// uint32_t const instanceStart;
3661/// uint32_t const instanceSize;
3662/// uint32_t const reserved; // only when building for 64bit targets
3663/// const uint8_t * const ivarLayout;
3664/// const char *const name;
3665/// const struct _method_list_t * const baseMethods;
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00003666/// const struct _protocol_list_t *const baseProtocols;
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003667/// const struct _ivar_list_t *const ivars;
3668/// const uint8_t * const weakIvarLayout;
3669/// const struct _prop_list_t * const properties;
3670/// }
3671///
3672llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
3673 unsigned flags,
3674 unsigned InstanceStart,
3675 unsigned InstanceSize,
3676 const ObjCImplementationDecl *ID) {
3677 std::string ClassName = ID->getNameAsString();
3678 std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
3679 Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
3680 Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
3681 Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
3682 // FIXME. For 64bit targets add 0 here.
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00003683 // FIXME. ivarLayout is currently null!
Fariborz Jahanian7345eba2009-03-05 19:17:31 +00003684 Values[ 3] = GetIvarLayoutName(0, ObjCTypes);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003685 Values[ 4] = GetClassName(ID->getIdentifier());
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00003686 // const struct _method_list_t * const baseMethods;
3687 std::vector<llvm::Constant*> Methods;
3688 std::string MethodListName("\01l_OBJC_$_");
3689 if (flags & CLS_META) {
3690 MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
3691 for (ObjCImplementationDecl::classmeth_iterator i = ID->classmeth_begin(),
3692 e = ID->classmeth_end(); i != e; ++i) {
3693 // Class methods should always be defined.
3694 Methods.push_back(GetMethodConstant(*i));
3695 }
3696 } else {
3697 MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
3698 for (ObjCImplementationDecl::instmeth_iterator i = ID->instmeth_begin(),
3699 e = ID->instmeth_end(); i != e; ++i) {
3700 // Instance methods should always be defined.
3701 Methods.push_back(GetMethodConstant(*i));
3702 }
Fariborz Jahanian78355ec2009-01-28 22:46:49 +00003703 for (ObjCImplementationDecl::propimpl_iterator i = ID->propimpl_begin(),
3704 e = ID->propimpl_end(); i != e; ++i) {
3705 ObjCPropertyImplDecl *PID = *i;
3706
3707 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
3708 ObjCPropertyDecl *PD = PID->getPropertyDecl();
3709
3710 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
3711 if (llvm::Constant *C = GetMethodConstant(MD))
3712 Methods.push_back(C);
3713 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
3714 if (llvm::Constant *C = GetMethodConstant(MD))
3715 Methods.push_back(C);
3716 }
3717 }
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00003718 }
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00003719 Values[ 5] = EmitMethodList(MethodListName,
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00003720 "__DATA, __objc_const", Methods);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00003721
3722 const ObjCInterfaceDecl *OID = ID->getClassInterface();
3723 assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
3724 Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
3725 + OID->getNameAsString(),
3726 OID->protocol_begin(),
3727 OID->protocol_end());
3728
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00003729 if (flags & CLS_META)
3730 Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
3731 else
3732 Values[ 7] = EmitIvarList(ID);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00003733 // FIXME. weakIvarLayout is currently null.
Fariborz Jahanian7345eba2009-03-05 19:17:31 +00003734 Values[ 8] = GetIvarLayoutName(0, ObjCTypes);
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00003735 if (flags & CLS_META)
3736 Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
3737 else
3738 Values[ 9] =
3739 EmitPropertyList(
3740 "\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
3741 ID, ID->getClassInterface(), ObjCTypes);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003742 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
3743 Values);
3744 llvm::GlobalVariable *CLASS_RO_GV =
3745 new llvm::GlobalVariable(ObjCTypes.ClassRonfABITy, false,
3746 llvm::GlobalValue::InternalLinkage,
3747 Init,
3748 (flags & CLS_META) ?
3749 std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
3750 std::string("\01l_OBJC_CLASS_RO_$_")+ClassName,
3751 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00003752 CLASS_RO_GV->setAlignment(
3753 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassRonfABITy));
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00003754 CLASS_RO_GV->setSection("__DATA, __objc_const");
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003755 UsedGlobals.push_back(CLASS_RO_GV);
3756 return CLASS_RO_GV;
Fariborz Jahanianc98c87b2009-01-26 22:58:07 +00003757
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003758}
3759
3760/// BuildClassMetaData - This routine defines that to-level meta-data
3761/// for the given ClassName for:
3762/// struct _class_t {
3763/// struct _class_t *isa;
3764/// struct _class_t * const superclass;
3765/// void *cache;
3766/// IMP *vtable;
3767/// struct class_ro_t *ro;
3768/// }
3769///
Fariborz Jahanian06726462009-01-24 21:21:53 +00003770llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
3771 std::string &ClassName,
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003772 llvm::Constant *IsAGV,
3773 llvm::Constant *SuperClassGV,
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00003774 llvm::Constant *ClassRoGV,
3775 bool HiddenVisibility) {
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003776 std::vector<llvm::Constant*> Values(5);
3777 Values[0] = IsAGV;
Fariborz Jahanian06726462009-01-24 21:21:53 +00003778 Values[1] = SuperClassGV
3779 ? SuperClassGV
3780 : llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003781 Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
3782 Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
3783 Values[4] = ClassRoGV; // &CLASS_RO_GV
3784 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
3785 Values);
Daniel Dunbarabbda222009-03-01 04:40:10 +00003786 llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
3787 GV->setInitializer(Init);
Fariborz Jahanian7c891592009-01-31 01:07:39 +00003788 GV->setSection("__DATA, __objc_data");
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00003789 GV->setAlignment(
3790 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ClassnfABITy));
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00003791 if (HiddenVisibility)
3792 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003793 UsedGlobals.push_back(GV);
Fariborz Jahanian06726462009-01-24 21:21:53 +00003794 return GV;
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003795}
3796
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003797void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
3798 std::string ClassName = ID->getNameAsString();
3799 if (!ObjCEmptyCacheVar) {
3800 ObjCEmptyCacheVar = new llvm::GlobalVariable(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00003801 ObjCTypes.CacheTy,
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003802 false,
3803 llvm::GlobalValue::ExternalLinkage,
3804 0,
Fariborz Jahaniane45fbce2009-02-03 17:34:34 +00003805 "\01__objc_empty_cache",
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003806 &CGM.getModule());
3807 UsedGlobals.push_back(ObjCEmptyCacheVar);
3808
3809 ObjCEmptyVtableVar = new llvm::GlobalVariable(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00003810 ObjCTypes.ImpnfABITy,
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003811 false,
3812 llvm::GlobalValue::ExternalLinkage,
3813 0,
Fariborz Jahaniane45fbce2009-02-03 17:34:34 +00003814 "\01__objc_empty_vtable",
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003815 &CGM.getModule());
3816 UsedGlobals.push_back(ObjCEmptyVtableVar);
3817 }
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00003818 assert(ID->getClassInterface() &&
3819 "CGObjCNonFragileABIMac::GenerateClass - class is 0");
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003820 uint32_t InstanceStart =
3821 CGM.getTargetData().getTypePaddedSize(ObjCTypes.ClassnfABITy);
3822 uint32_t InstanceSize = InstanceStart;
3823 uint32_t flags = CLS_META;
3824 std::string ObjCMetaClassName("\01_OBJC_METACLASS_$_");
3825 std::string ObjCClassName("\01_OBJC_CLASS_$_");
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003826
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003827 llvm::GlobalVariable *SuperClassGV, *IsAGV;
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003828
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00003829 bool classIsHidden = IsClassHidden(ID->getClassInterface());
3830 if (classIsHidden)
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00003831 flags |= OBJC2_CLS_HIDDEN;
3832 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003833 // class is root
3834 flags |= CLS_ROOT;
Daniel Dunbarabbda222009-03-01 04:40:10 +00003835 SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
3836 IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003837 } else {
Fariborz Jahanian06726462009-01-24 21:21:53 +00003838 // Has a root. Current class is not a root.
Fariborz Jahanian514c63b2009-02-26 18:23:47 +00003839 const ObjCInterfaceDecl *Root = ID->getClassInterface();
3840 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
3841 Root = Super;
Daniel Dunbarabbda222009-03-01 04:40:10 +00003842 IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
Fariborz Jahanian514c63b2009-02-26 18:23:47 +00003843 // work on super class metadata symbol.
3844 std::string SuperClassName =
3845 ObjCMetaClassName + ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarabbda222009-03-01 04:40:10 +00003846 SuperClassGV = GetClassGlobal(SuperClassName);
Fariborz Jahanian4c1e4612009-01-24 20:21:50 +00003847 }
3848 llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
3849 InstanceStart,
3850 InstanceSize,ID);
Fariborz Jahanian06726462009-01-24 21:21:53 +00003851 std::string TClassName = ObjCMetaClassName + ClassName;
3852 llvm::GlobalVariable *MetaTClass =
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00003853 BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
3854 classIsHidden);
Fariborz Jahanian06726462009-01-24 21:21:53 +00003855
3856 // Metadata for the class
3857 flags = CLS;
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00003858 if (classIsHidden)
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00003859 flags |= OBJC2_CLS_HIDDEN;
3860 if (!ID->getClassInterface()->getSuperClass()) {
Fariborz Jahanian06726462009-01-24 21:21:53 +00003861 flags |= CLS_ROOT;
3862 SuperClassGV = 0;
3863 }
3864 else {
3865 // Has a root. Current class is not a root.
Fariborz Jahanian514c63b2009-02-26 18:23:47 +00003866 std::string RootClassName =
Fariborz Jahanian06726462009-01-24 21:21:53 +00003867 ID->getClassInterface()->getSuperClass()->getNameAsString();
Daniel Dunbarabbda222009-03-01 04:40:10 +00003868 SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
Fariborz Jahanian06726462009-01-24 21:21:53 +00003869 }
3870
Fariborz Jahanianddd2fdd2009-01-24 23:43:01 +00003871 InstanceStart = InstanceSize = 0;
3872 if (ObjCInterfaceDecl *OID =
3873 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface())) {
3874 // FIXME. Share this with the one in EmitIvarList.
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00003875 const llvm::Type *InterfaceTy =
Fariborz Jahanian27ecc672009-02-14 20:13:28 +00003876 CGM.getTypes().ConvertType(CGM.getContext().buildObjCInterfaceType(OID));
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00003877 const llvm::StructLayout *Layout =
3878 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(InterfaceTy));
Fariborz Jahanianddd2fdd2009-01-24 23:43:01 +00003879
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00003880 RecordDecl::field_iterator firstField, lastField;
3881 const RecordDecl *RD = GetFirstIvarInRecord(OID, firstField, lastField);
Fariborz Jahanianddd2fdd2009-01-24 23:43:01 +00003882
3883 for (RecordDecl::field_iterator e = RD->field_end(),
3884 ifield = firstField; ifield != e; ++ifield)
3885 lastField = ifield;
3886
Fariborz Jahanianddd2fdd2009-01-24 23:43:01 +00003887 if (lastField != RD->field_end()) {
3888 FieldDecl *Field = *lastField;
3889 const llvm::Type *FieldTy =
3890 CGM.getTypes().ConvertTypeForMem(Field->getType());
3891 unsigned Size = CGM.getTargetData().getTypePaddedSize(FieldTy);
Fariborz Jahaniand65949b2009-03-08 20:18:37 +00003892 InstanceSize = GetIvarBaseOffset(Layout, Field) + Size;
Fariborz Jahanianddd2fdd2009-01-24 23:43:01 +00003893 if (firstField == RD->field_end())
3894 InstanceStart = InstanceSize;
Fariborz Jahaniand6d0c932009-03-07 19:43:20 +00003895 else {
3896 Field = *firstField;
Fariborz Jahaniand65949b2009-03-08 20:18:37 +00003897 InstanceStart = GetIvarBaseOffset(Layout, Field);
Fariborz Jahaniand6d0c932009-03-07 19:43:20 +00003898 }
Fariborz Jahanianddd2fdd2009-01-24 23:43:01 +00003899 }
3900 }
Fariborz Jahanian06726462009-01-24 21:21:53 +00003901 CLASS_RO_GV = BuildClassRoTInitializer(flags,
Fariborz Jahanianddd2fdd2009-01-24 23:43:01 +00003902 InstanceStart,
3903 InstanceSize,
3904 ID);
Fariborz Jahanian06726462009-01-24 21:21:53 +00003905
3906 TClassName = ObjCClassName + ClassName;
Fariborz Jahanian11c93dd2009-01-30 20:55:31 +00003907 llvm::GlobalVariable *ClassMD =
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00003908 BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
3909 classIsHidden);
Fariborz Jahanian11c93dd2009-01-30 20:55:31 +00003910 DefinedClasses.push_back(ClassMD);
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00003911}
3912
Fariborz Jahanian5d13ab12009-01-30 18:58:59 +00003913/// GenerateProtocolRef - This routine is called to generate code for
3914/// a protocol reference expression; as in:
3915/// @code
3916/// @protocol(Proto1);
3917/// @endcode
3918/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
3919/// which will hold address of the protocol meta-data.
3920///
3921llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
3922 const ObjCProtocolDecl *PD) {
3923
3924 llvm::Constant *Init = llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
3925 ObjCTypes.ExternalProtocolPtrTy);
3926
3927 std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
3928 ProtocolName += PD->getNameAsCString();
3929
3930 llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
3931 if (PTGV)
3932 return Builder.CreateLoad(PTGV, false, "tmp");
3933 PTGV = new llvm::GlobalVariable(
3934 Init->getType(), false,
Mike Stump36dbf222009-03-07 16:33:28 +00003935 // FIXME: review, was WeakLinkage,
3936 // also review all other WeakLinkage changes
3937 llvm::GlobalValue::WeakAnyLinkage,
Fariborz Jahanian5d13ab12009-01-30 18:58:59 +00003938 Init,
3939 ProtocolName,
3940 &CGM.getModule());
3941 PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
3942 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
3943 UsedGlobals.push_back(PTGV);
3944 return Builder.CreateLoad(PTGV, false, "tmp");
3945}
3946
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00003947/// GenerateCategory - Build metadata for a category implementation.
3948/// struct _category_t {
3949/// const char * const name;
3950/// struct _class_t *const cls;
3951/// const struct _method_list_t * const instance_methods;
3952/// const struct _method_list_t * const class_methods;
3953/// const struct _protocol_list_t * const protocols;
3954/// const struct _prop_list_t * const properties;
3955/// }
3956///
3957void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD)
3958{
3959 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Fariborz Jahanianc98c87b2009-01-26 22:58:07 +00003960 const char *Prefix = "\01l_OBJC_$_CATEGORY_";
3961 std::string ExtCatName(Prefix + Interface->getNameAsString()+
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00003962 "_$_" + OCD->getNameAsString());
3963 std::string ExtClassName("\01_OBJC_CLASS_$_" + Interface->getNameAsString());
3964
3965 std::vector<llvm::Constant*> Values(6);
3966 Values[0] = GetClassName(OCD->getIdentifier());
3967 // meta-class entry symbol
Daniel Dunbarabbda222009-03-01 04:40:10 +00003968 llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00003969 Values[1] = ClassGV;
Fariborz Jahanianc98c87b2009-01-26 22:58:07 +00003970 std::vector<llvm::Constant*> Methods;
3971 std::string MethodListName(Prefix);
3972 MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
3973 "_$_" + OCD->getNameAsString();
3974
3975 for (ObjCCategoryImplDecl::instmeth_iterator i = OCD->instmeth_begin(),
3976 e = OCD->instmeth_end(); i != e; ++i) {
3977 // Instance methods should always be defined.
3978 Methods.push_back(GetMethodConstant(*i));
3979 }
3980
3981 Values[2] = EmitMethodList(MethodListName,
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00003982 "__DATA, __objc_const",
Fariborz Jahanianc98c87b2009-01-26 22:58:07 +00003983 Methods);
3984
3985 MethodListName = Prefix;
3986 MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
3987 OCD->getNameAsString();
3988 Methods.clear();
3989 for (ObjCCategoryImplDecl::classmeth_iterator i = OCD->classmeth_begin(),
3990 e = OCD->classmeth_end(); i != e; ++i) {
3991 // Class methods should always be defined.
3992 Methods.push_back(GetMethodConstant(*i));
3993 }
3994
3995 Values[3] = EmitMethodList(MethodListName,
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00003996 "__DATA, __objc_const",
Fariborz Jahanianc98c87b2009-01-26 22:58:07 +00003997 Methods);
Fariborz Jahanian7b709bb2009-01-28 22:18:42 +00003998 const ObjCCategoryDecl *Category =
3999 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Fariborz Jahanian8c7904b2009-02-13 17:52:22 +00004000 if (Category) {
4001 std::string ExtName(Interface->getNameAsString() + "_$_" +
4002 OCD->getNameAsString());
4003 Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
4004 + Interface->getNameAsString() + "_$_"
4005 + Category->getNameAsString(),
4006 Category->protocol_begin(),
4007 Category->protocol_end());
4008 Values[5] =
4009 EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_") + ExtName,
4010 OCD, Category, ObjCTypes);
4011 }
4012 else {
4013 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
4014 Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
4015 }
4016
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00004017 llvm::Constant *Init =
4018 llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
4019 Values);
4020 llvm::GlobalVariable *GCATV
4021 = new llvm::GlobalVariable(ObjCTypes.CategorynfABITy,
4022 false,
4023 llvm::GlobalValue::InternalLinkage,
4024 Init,
4025 ExtCatName,
4026 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004027 GCATV->setAlignment(
4028 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.CategorynfABITy));
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004029 GCATV->setSection("__DATA, __objc_const");
Fariborz Jahanianfe49a092009-01-26 18:32:24 +00004030 UsedGlobals.push_back(GCATV);
4031 DefinedCategories.push_back(GCATV);
4032}
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004033
4034/// GetMethodConstant - Return a struct objc_method constant for the
4035/// given method if it has been defined. The result is null if the
4036/// method has not been defined. The return value has type MethodPtrTy.
4037llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
4038 const ObjCMethodDecl *MD) {
4039 // FIXME: Use DenseMap::lookup
4040 llvm::Function *Fn = MethodDefinitions[MD];
4041 if (!Fn)
4042 return 0;
4043
4044 std::vector<llvm::Constant*> Method(3);
4045 Method[0] =
4046 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
4047 ObjCTypes.SelectorPtrTy);
4048 Method[1] = GetMethodVarType(MD);
4049 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
4050 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
4051}
4052
4053/// EmitMethodList - Build meta-data for method declarations
4054/// struct _method_list_t {
4055/// uint32_t entsize; // sizeof(struct _objc_method)
4056/// uint32_t method_count;
4057/// struct _objc_method method_list[method_count];
4058/// }
4059///
4060llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(
4061 const std::string &Name,
4062 const char *Section,
4063 const ConstantVector &Methods) {
4064 // Return null for empty list.
4065 if (Methods.empty())
4066 return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
4067
4068 std::vector<llvm::Constant*> Values(3);
4069 // sizeof(struct _objc_method)
4070 unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.MethodTy);
4071 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4072 // method_count
4073 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
4074 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
4075 Methods.size());
4076 Values[2] = llvm::ConstantArray::get(AT, Methods);
4077 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
4078
4079 llvm::GlobalVariable *GV =
4080 new llvm::GlobalVariable(Init->getType(), false,
4081 llvm::GlobalValue::InternalLinkage,
4082 Init,
4083 Name,
4084 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004085 GV->setAlignment(
4086 CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
Fariborz Jahaniana9502ca2009-01-26 21:38:32 +00004087 GV->setSection(Section);
4088 UsedGlobals.push_back(GV);
4089 return llvm::ConstantExpr::getBitCast(GV,
4090 ObjCTypes.MethodListnfABIPtrTy);
4091}
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004092
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004093/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
4094/// the given ivar.
4095///
4096llvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(
4097 std::string &Name,
Fariborz Jahaniana09a5142009-02-12 18:51:23 +00004098 const ObjCInterfaceDecl *ID,
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004099 const ObjCIvarDecl *Ivar) {
Fariborz Jahaniana09a5142009-02-12 18:51:23 +00004100 Name += "\01_OBJC_IVAR_$_" +
4101 getInterfaceDeclForIvar(ID, Ivar)->getNameAsString() + '.'
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004102 + Ivar->getNameAsString();
4103 llvm::GlobalVariable *IvarOffsetGV =
4104 CGM.getModule().getGlobalVariable(Name);
4105 if (!IvarOffsetGV)
4106 IvarOffsetGV =
4107 new llvm::GlobalVariable(ObjCTypes.LongTy,
4108 false,
4109 llvm::GlobalValue::ExternalLinkage,
4110 0,
4111 Name,
4112 &CGM.getModule());
4113 return IvarOffsetGV;
4114}
4115
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004116llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar(
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004117 const ObjCInterfaceDecl *ID,
Fariborz Jahanian150f7732009-01-28 01:36:42 +00004118 const ObjCIvarDecl *Ivar,
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004119 unsigned long int Offset) {
4120
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004121 assert(ID && "EmitIvarOffsetVar - null interface decl.");
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004122 std::string ExternalName("\01_OBJC_IVAR_$_" + ID->getNameAsString() + '.'
Fariborz Jahanian150f7732009-01-28 01:36:42 +00004123 + Ivar->getNameAsString());
Fariborz Jahanian55343922009-02-03 00:09:52 +00004124 llvm::Constant *Init = llvm::ConstantInt::get(ObjCTypes.LongTy, Offset);
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004125
4126 llvm::GlobalVariable *IvarOffsetGV =
4127 CGM.getModule().getGlobalVariable(ExternalName);
4128 if (IvarOffsetGV) {
4129 // ivar offset symbol already built due to user code referencing it.
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004130 IvarOffsetGV->setAlignment(
Fariborz Jahanian55343922009-02-03 00:09:52 +00004131 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy));
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004132 IvarOffsetGV->setInitializer(Init);
Fariborz Jahanian55343922009-02-03 00:09:52 +00004133 IvarOffsetGV->setSection("__DATA, __objc_const");
Fariborz Jahanian150f7732009-01-28 01:36:42 +00004134 UsedGlobals.push_back(IvarOffsetGV);
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004135 return IvarOffsetGV;
4136 }
4137
4138 IvarOffsetGV =
4139 new llvm::GlobalVariable(Init->getType(),
4140 false,
4141 llvm::GlobalValue::ExternalLinkage,
4142 Init,
4143 ExternalName,
4144 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004145 IvarOffsetGV->setAlignment(
Fariborz Jahanian55343922009-02-03 00:09:52 +00004146 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy));
Fariborz Jahanian150f7732009-01-28 01:36:42 +00004147 // @private and @package have hidden visibility.
4148 bool globalVisibility = (Ivar->getAccessControl() == ObjCIvarDecl::Public ||
4149 Ivar->getAccessControl() == ObjCIvarDecl::Protected);
4150 if (!globalVisibility)
4151 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00004152 else
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004153 if (IsClassHidden(ID))
4154 IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
Fariborz Jahanian51dcacb2009-01-31 00:59:10 +00004155
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004156 IvarOffsetGV->setSection("__DATA, __objc_const");
4157 UsedGlobals.push_back(IvarOffsetGV);
Fariborz Jahanian55343922009-02-03 00:09:52 +00004158 return IvarOffsetGV;
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004159}
4160
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004161/// EmitIvarList - Emit the ivar list for the given
4162/// implementation. If ForClass is true the list of class ivars
4163/// (i.e. metaclass ivars) is emitted, otherwise the list of
4164/// interface ivars will be emitted. The return value has type
4165/// IvarListnfABIPtrTy.
4166/// struct _ivar_t {
4167/// unsigned long int *offset; // pointer to ivar offset location
4168/// char *name;
4169/// char *type;
4170/// uint32_t alignment;
4171/// uint32_t size;
4172/// }
4173/// struct _ivar_list_t {
4174/// uint32 entsize; // sizeof(struct _ivar_t)
4175/// uint32 count;
4176/// struct _iver_t list[count];
4177/// }
4178///
4179llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
4180 const ObjCImplementationDecl *ID) {
4181
4182 std::vector<llvm::Constant*> Ivars, Ivar(5);
4183
4184 const ObjCInterfaceDecl *OID = ID->getClassInterface();
4185 assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
4186
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004187 // FIXME. Consolidate this with similar code in GenerateClass.
4188 const llvm::Type *InterfaceTy =
4189 CGM.getTypes().ConvertType(CGM.getContext().getObjCInterfaceType(
4190 const_cast<ObjCInterfaceDecl*>(OID)));
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004191 const llvm::StructLayout *Layout =
4192 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(InterfaceTy));
Fariborz Jahanianf2a94cd2009-01-28 19:12:34 +00004193
4194 RecordDecl::field_iterator i,p;
4195 const RecordDecl *RD = GetFirstIvarInRecord(OID, i,p);
Fariborz Jahanian150f7732009-01-28 01:36:42 +00004196 ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin();
4197
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004198 for (RecordDecl::field_iterator e = RD->field_end(); i != e; ++i) {
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004199 FieldDecl *Field = *i;
Fariborz Jahaniand65949b2009-03-08 20:18:37 +00004200 uint64_t offset = GetIvarBaseOffset(Layout, Field);
Fariborz Jahanian150f7732009-01-28 01:36:42 +00004201 const ObjCIvarDecl *ivarDecl = *I++;
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004202 Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), ivarDecl, offset);
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004203 if (Field->getIdentifier())
4204 Ivar[1] = GetMethodVarName(Field->getIdentifier());
4205 else
4206 Ivar[1] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Devang Patel593a07a2009-03-04 18:21:39 +00004207 Ivar[2] = GetMethodVarType(Field);
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004208 const llvm::Type *FieldTy =
4209 CGM.getTypes().ConvertTypeForMem(Field->getType());
4210 unsigned Size = CGM.getTargetData().getTypePaddedSize(FieldTy);
4211 unsigned Align = CGM.getContext().getPreferredTypeAlign(
4212 Field->getType().getTypePtr()) >> 3;
4213 Align = llvm::Log2_32(Align);
4214 Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
Fariborz Jahanian71bcf672009-01-27 22:27:56 +00004215 // NOTE. Size of a bitfield does not match gcc's, because of the way
4216 // bitfields are treated special in each. But I am told that 'size'
4217 // for bitfield ivars is ignored by the runtime so it does not matter.
4218 // (even if it matters, some day, there is enough info. to get the bitfield
4219 // right!
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004220 Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4221 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
4222 }
4223 // Return null for empty list.
4224 if (Ivars.empty())
4225 return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
4226 std::vector<llvm::Constant*> Values(3);
4227 unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.IvarnfABITy);
4228 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4229 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
4230 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
4231 Ivars.size());
4232 Values[2] = llvm::ConstantArray::get(AT, Ivars);
4233 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
4234 const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
4235 llvm::GlobalVariable *GV =
4236 new llvm::GlobalVariable(Init->getType(), false,
4237 llvm::GlobalValue::InternalLinkage,
4238 Init,
4239 Prefix + OID->getNameAsString(),
4240 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004241 GV->setAlignment(
4242 CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
Fariborz Jahanian3175ddd2009-01-28 01:05:23 +00004243 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian3f1cc562009-01-27 19:38:51 +00004244
4245 UsedGlobals.push_back(GV);
4246 return llvm::ConstantExpr::getBitCast(GV,
4247 ObjCTypes.IvarListnfABIPtrTy);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004248}
4249
4250llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
4251 const ObjCProtocolDecl *PD) {
4252 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
4253
4254 if (!Entry) {
4255 // We use the initializer as a marker of whether this is a forward
4256 // reference or not. At module finalization we add the empty
4257 // contents for protocols which were referenced but never defined.
4258 Entry =
4259 new llvm::GlobalVariable(ObjCTypes.ProtocolnfABITy, false,
4260 llvm::GlobalValue::ExternalLinkage,
4261 0,
4262 "\01l_OBJC_PROTOCOL_$_" + PD->getNameAsString(),
4263 &CGM.getModule());
4264 Entry->setSection("__DATA,__datacoal_nt,coalesced");
4265 UsedGlobals.push_back(Entry);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004266 }
4267
4268 return Entry;
4269}
4270
4271/// GetOrEmitProtocol - Generate the protocol meta-data:
4272/// @code
4273/// struct _protocol_t {
4274/// id isa; // NULL
4275/// const char * const protocol_name;
4276/// const struct _protocol_list_t * protocol_list; // super protocols
4277/// const struct method_list_t * const instance_methods;
4278/// const struct method_list_t * const class_methods;
4279/// const struct method_list_t *optionalInstanceMethods;
4280/// const struct method_list_t *optionalClassMethods;
4281/// const struct _prop_list_t * properties;
4282/// const uint32_t size; // sizeof(struct _protocol_t)
4283/// const uint32_t flags; // = 0
4284/// }
4285/// @endcode
4286///
4287
4288llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
4289 const ObjCProtocolDecl *PD) {
4290 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
4291
4292 // Early exit if a defining object has already been generated.
4293 if (Entry && Entry->hasInitializer())
4294 return Entry;
4295
4296 const char *ProtocolName = PD->getNameAsCString();
4297
4298 // Construct method lists.
4299 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
4300 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
4301 for (ObjCProtocolDecl::instmeth_iterator i = PD->instmeth_begin(),
4302 e = PD->instmeth_end(); i != e; ++i) {
4303 ObjCMethodDecl *MD = *i;
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004304 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004305 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
4306 OptInstanceMethods.push_back(C);
4307 } else {
4308 InstanceMethods.push_back(C);
4309 }
4310 }
4311
4312 for (ObjCProtocolDecl::classmeth_iterator i = PD->classmeth_begin(),
4313 e = PD->classmeth_end(); i != e; ++i) {
4314 ObjCMethodDecl *MD = *i;
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004315 llvm::Constant *C = GetMethodDescriptionConstant(MD);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004316 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
4317 OptClassMethods.push_back(C);
4318 } else {
4319 ClassMethods.push_back(C);
4320 }
4321 }
4322
4323 std::vector<llvm::Constant*> Values(10);
4324 // isa is NULL
4325 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
4326 Values[1] = GetClassName(PD->getIdentifier());
4327 Values[2] = EmitProtocolList(
4328 "\01l_OBJC_$_PROTOCOL_REFS_" + PD->getNameAsString(),
4329 PD->protocol_begin(),
4330 PD->protocol_end());
4331
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004332 Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004333 + PD->getNameAsString(),
4334 "__DATA, __objc_const",
4335 InstanceMethods);
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004336 Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004337 + PD->getNameAsString(),
4338 "__DATA, __objc_const",
4339 ClassMethods);
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004340 Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004341 + PD->getNameAsString(),
4342 "__DATA, __objc_const",
4343 OptInstanceMethods);
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004344 Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004345 + PD->getNameAsString(),
4346 "__DATA, __objc_const",
4347 OptClassMethods);
4348 Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getNameAsString(),
4349 0, PD, ObjCTypes);
4350 uint32_t Size =
4351 CGM.getTargetData().getTypePaddedSize(ObjCTypes.ProtocolnfABITy);
4352 Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
4353 Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
4354 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
4355 Values);
4356
4357 if (Entry) {
4358 // Already created, fix the linkage and update the initializer.
Mike Stump36dbf222009-03-07 16:33:28 +00004359 Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004360 Entry->setInitializer(Init);
4361 } else {
4362 Entry =
4363 new llvm::GlobalVariable(ObjCTypes.ProtocolnfABITy, false,
Mike Stump36dbf222009-03-07 16:33:28 +00004364 llvm::GlobalValue::WeakAnyLinkage,
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004365 Init,
4366 std::string("\01l_OBJC_PROTOCOL_$_")+ProtocolName,
4367 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004368 Entry->setAlignment(
4369 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy));
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004370 Entry->setSection("__DATA,__datacoal_nt,coalesced");
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004371 }
Fariborz Jahanianfd02a662009-01-29 20:10:59 +00004372 Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
4373
4374 // Use this protocol meta-data to build protocol list table in section
4375 // __DATA, __objc_protolist
Fariborz Jahanianfd02a662009-01-29 20:10:59 +00004376 llvm::GlobalVariable *PTGV = new llvm::GlobalVariable(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004377 ObjCTypes.ProtocolnfABIPtrTy, false,
Mike Stump36dbf222009-03-07 16:33:28 +00004378 llvm::GlobalValue::WeakAnyLinkage,
Fariborz Jahanianfd02a662009-01-29 20:10:59 +00004379 Entry,
4380 std::string("\01l_OBJC_LABEL_PROTOCOL_$_")
4381 +ProtocolName,
4382 &CGM.getModule());
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004383 PTGV->setAlignment(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004384 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
Fariborz Jahanianfd02a662009-01-29 20:10:59 +00004385 PTGV->setSection("__DATA, __objc_protolist");
4386 PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4387 UsedGlobals.push_back(PTGV);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004388 return Entry;
4389}
4390
4391/// EmitProtocolList - Generate protocol list meta-data:
4392/// @code
4393/// struct _protocol_list_t {
4394/// long protocol_count; // Note, this is 32/64 bit
4395/// struct _protocol_t[protocol_count];
4396/// }
4397/// @endcode
4398///
4399llvm::Constant *
4400CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name,
4401 ObjCProtocolDecl::protocol_iterator begin,
4402 ObjCProtocolDecl::protocol_iterator end) {
4403 std::vector<llvm::Constant*> ProtocolRefs;
4404
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004405 // Just return null for empty protocol lists
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004406 if (begin == end)
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004407 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
4408
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004409 // FIXME: We shouldn't need to do this lookup here, should we?
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004410 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
4411 if (GV)
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004412 return llvm::ConstantExpr::getBitCast(GV,
4413 ObjCTypes.ProtocolListnfABIPtrTy);
4414
4415 for (; begin != end; ++begin)
4416 ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
4417
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004418 // This list is null terminated.
4419 ProtocolRefs.push_back(llvm::Constant::getNullValue(
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004420 ObjCTypes.ProtocolnfABIPtrTy));
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004421
4422 std::vector<llvm::Constant*> Values(2);
4423 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
4424 Values[1] =
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004425 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004426 ProtocolRefs.size()),
4427 ProtocolRefs);
4428
4429 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
4430 GV = new llvm::GlobalVariable(Init->getType(), false,
4431 llvm::GlobalValue::InternalLinkage,
4432 Init,
4433 Name,
4434 &CGM.getModule());
4435 GV->setSection("__DATA, __objc_const");
Fariborz Jahanian2d6ecb22009-01-31 02:43:27 +00004436 GV->setAlignment(
4437 CGM.getTargetData().getPrefTypeAlignment(Init->getType()));
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004438 UsedGlobals.push_back(GV);
Daniel Dunbar1f42bb02009-02-15 07:36:20 +00004439 return llvm::ConstantExpr::getBitCast(GV,
4440 ObjCTypes.ProtocolListnfABIPtrTy);
Fariborz Jahanian5fedf4f2009-01-29 19:24:30 +00004441}
4442
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004443/// GetMethodDescriptionConstant - This routine build following meta-data:
4444/// struct _objc_method {
4445/// SEL _cmd;
4446/// char *method_type;
4447/// char *_imp;
4448/// }
4449
4450llvm::Constant *
4451CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
4452 std::vector<llvm::Constant*> Desc(3);
4453 Desc[0] = llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
4454 ObjCTypes.SelectorPtrTy);
4455 Desc[1] = GetMethodVarType(MD);
Fariborz Jahanian5d13ab12009-01-30 18:58:59 +00004456 // Protocol methods have no implementation. So, this entry is always NULL.
Fariborz Jahanian151747b2009-01-30 00:46:37 +00004457 Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
4458 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
4459}
Fariborz Jahanian55343922009-02-03 00:09:52 +00004460
4461/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
4462/// This code gen. amounts to generating code for:
4463/// @code
4464/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
4465/// @encode
4466///
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00004467LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
Fariborz Jahanian55343922009-02-03 00:09:52 +00004468 CodeGen::CodeGenFunction &CGF,
4469 QualType ObjectTy,
4470 llvm::Value *BaseValue,
4471 const ObjCIvarDecl *Ivar,
4472 const FieldDecl *Field,
4473 unsigned CVRQualifiers) {
4474 assert(ObjectTy->isObjCInterfaceType() &&
4475 "CGObjCNonFragileABIMac::EmitObjCValueForIvar");
Fariborz Jahaniana09a5142009-02-12 18:51:23 +00004476 ObjCInterfaceDecl *ID = ObjectTy->getAsObjCInterfaceType()->getDecl();
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004477 std::string ExternalName;
4478 llvm::GlobalVariable *IvarOffsetGV =
4479 ObjCIvarOffsetVariable(ExternalName, ID, Ivar);
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00004480
Fariborz Jahanian55343922009-02-03 00:09:52 +00004481 // (char *) BaseValue
4482 llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue,
4483 ObjCTypes.Int8PtrTy);
4484 llvm::Value *Offset = CGF.Builder.CreateLoad(IvarOffsetGV);
4485 // (char*)BaseValue + Offset_symbol
4486 V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
4487 // (type *)((char*)BaseValue + Offset_symbol)
4488 const llvm::Type *IvarTy =
4489 CGM.getTypes().ConvertType(Ivar->getType());
4490 llvm::Type *ptrIvarTy = llvm::PointerType::getUnqual(IvarTy);
4491 V = CGF.Builder.CreateBitCast(V, ptrIvarTy);
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00004492
Fariborz Jahanian40a94a92009-03-09 20:44:22 +00004493 if (Ivar->isBitField()) {
4494 CodeGenTypes::BitFieldInfo bitFieldInfo =
4495 CGM.getTypes().getBitFieldInfo(Field);
4496 return LValue::MakeBitfield(V, bitFieldInfo.Begin, bitFieldInfo.Size,
4497 Field->getType()->isSignedIntegerType(),
4498 Field->getType().getCVRQualifiers()|CVRQualifiers);
4499 }
4500
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00004501 LValue LV = LValue::MakeAddr(V,
Fariborz Jahanianbbd4ca92009-02-19 23:36:06 +00004502 Ivar->getType().getCVRQualifiers()|CVRQualifiers,
4503 CGM.getContext().getObjCGCAttrKind(Ivar->getType()));
Fariborz Jahanianc912eb72009-02-03 19:03:09 +00004504 LValue::SetObjCIvar(LV, true);
4505 return LV;
Fariborz Jahanian55343922009-02-03 00:09:52 +00004506}
4507
Fariborz Jahanian27cc6662009-02-10 19:02:04 +00004508llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
4509 CodeGen::CodeGenFunction &CGF,
4510 ObjCInterfaceDecl *Interface,
4511 const ObjCIvarDecl *Ivar) {
Fariborz Jahaniancc00f922009-02-10 20:21:06 +00004512 std::string ExternalName;
4513 llvm::GlobalVariable *IvarOffsetGV =
4514 ObjCIvarOffsetVariable(ExternalName, Interface, Ivar);
4515
4516 return CGF.Builder.CreateLoad(IvarOffsetGV, false, "ivar");
Fariborz Jahanian27cc6662009-02-10 19:02:04 +00004517}
4518
Fariborz Jahanian7e881162009-02-04 00:22:57 +00004519CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
4520 CodeGen::CodeGenFunction &CGF,
4521 QualType ResultType,
4522 Selector Sel,
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004523 llvm::Value *Receiver,
Fariborz Jahanian7e881162009-02-04 00:22:57 +00004524 QualType Arg0Ty,
4525 bool IsSuper,
4526 const CallArgList &CallArgs) {
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004527 // FIXME. Even though IsSuper is passes. This function doese not
4528 // handle calls to 'super' receivers.
4529 CodeGenTypes &Types = CGM.getTypes();
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004530 llvm::Value *Arg0 = Receiver;
4531 if (!IsSuper)
4532 Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004533
4534 // Find the message function name.
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00004535 // FIXME. This is too much work to get the ABI-specific result type
4536 // needed to find the message name.
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004537 const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType,
4538 llvm::SmallVector<QualType, 16>());
4539 llvm::Constant *Fn;
4540 std::string Name("\01l_");
4541 if (CGM.ReturnTypeUsesSret(FnInfo)) {
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00004542#if 0
4543 // unlike what is documented. gcc never generates this API!!
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004544 if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
4545 Fn = ObjCTypes.MessageSendIdStretFixupFn;
4546 // FIXME. Is there a better way of getting these names.
4547 // They are available in RuntimeFunctions vector pair.
4548 Name += "objc_msgSendId_stret_fixup";
4549 }
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00004550 else
4551#endif
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004552 if (IsSuper) {
4553 Fn = ObjCTypes.MessageSendSuper2StretFixupFn;
4554 Name += "objc_msgSendSuper2_stret_fixup";
4555 }
4556 else
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00004557 {
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004558 Fn = ObjCTypes.MessageSendStretFixupFn;
4559 Name += "objc_msgSend_stret_fixup";
4560 }
4561 }
Fariborz Jahanianbea03192009-02-05 19:35:43 +00004562 else if (ResultType->isFloatingType() &&
4563 // Selection of frret API only happens in 32bit nonfragile ABI.
4564 CGM.getTargetData().getTypePaddedSize(ObjCTypes.LongTy) == 4) {
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004565 Fn = ObjCTypes.MessageSendFpretFixupFn;
4566 Name += "objc_msgSend_fpret_fixup";
4567 }
4568 else {
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00004569#if 0
4570// unlike what is documented. gcc never generates this API!!
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004571 if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
4572 Fn = ObjCTypes.MessageSendIdFixupFn;
4573 Name += "objc_msgSendId_fixup";
4574 }
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00004575 else
4576#endif
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004577 if (IsSuper) {
4578 Fn = ObjCTypes.MessageSendSuper2FixupFn;
4579 Name += "objc_msgSendSuper2_fixup";
4580 }
4581 else
Fariborz Jahanian13ab25e2009-02-05 18:00:27 +00004582 {
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004583 Fn = ObjCTypes.MessageSendFixupFn;
4584 Name += "objc_msgSend_fixup";
4585 }
4586 }
4587 Name += '_';
4588 std::string SelName(Sel.getAsString());
4589 // Replace all ':' in selector name with '_' ouch!
4590 for(unsigned i = 0; i < SelName.size(); i++)
4591 if (SelName[i] == ':')
4592 SelName[i] = '_';
4593 Name += SelName;
4594 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
4595 if (!GV) {
4596 // Build messafe ref table entry.
4597 std::vector<llvm::Constant*> Values(2);
4598 Values[0] = Fn;
4599 Values[1] = GetMethodVarName(Sel);
4600 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
4601 GV = new llvm::GlobalVariable(Init->getType(), false,
Mike Stump36dbf222009-03-07 16:33:28 +00004602 llvm::GlobalValue::WeakAnyLinkage,
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004603 Init,
4604 Name,
4605 &CGM.getModule());
4606 GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
4607 GV->setAlignment(
4608 CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.MessageRefTy));
4609 GV->setSection("__DATA, __objc_msgrefs, coalesced");
4610 UsedGlobals.push_back(GV);
4611 }
4612 llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy);
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00004613
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004614 CallArgList ActualArgs;
4615 ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
4616 ActualArgs.push_back(std::make_pair(RValue::get(Arg1),
4617 ObjCTypes.MessageRefCPtrTy));
4618 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00004619 const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs);
4620 llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0);
4621 Callee = CGF.Builder.CreateLoad(Callee);
Fariborz Jahanianf3c17752009-02-14 21:25:36 +00004622 const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true);
Fariborz Jahanian10d69ea2009-02-05 01:13:09 +00004623 Callee = CGF.Builder.CreateBitCast(Callee,
4624 llvm::PointerType::getUnqual(FTy));
4625 return CGF.EmitCall(FnInfo1, Callee, ActualArgs);
Fariborz Jahanian7e881162009-02-04 00:22:57 +00004626}
4627
4628/// Generate code for a message send expression in the nonfragile abi.
4629CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend(
4630 CodeGen::CodeGenFunction &CGF,
4631 QualType ResultType,
4632 Selector Sel,
4633 llvm::Value *Receiver,
4634 bool IsClassMessage,
4635 const CallArgList &CallArgs) {
Fariborz Jahanian7e881162009-02-04 00:22:57 +00004636 return EmitMessageSend(CGF, ResultType, Sel,
Fariborz Jahanianf52110f2009-02-04 20:42:28 +00004637 Receiver, CGF.getContext().getObjCIdType(),
Fariborz Jahanian7e881162009-02-04 00:22:57 +00004638 false, CallArgs);
4639}
4640
Daniel Dunbarabbda222009-03-01 04:40:10 +00004641llvm::GlobalVariable *
4642CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
4643 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
4644
Daniel Dunbar66b47512009-03-02 05:18:14 +00004645 if (!GV) {
Daniel Dunbarabbda222009-03-01 04:40:10 +00004646 GV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false,
4647 llvm::GlobalValue::ExternalLinkage,
4648 0, Name, &CGM.getModule());
4649 UsedGlobals.push_back(GV);
4650 }
4651
4652 return GV;
4653}
4654
Fariborz Jahanian917c0402009-02-05 20:41:40 +00004655llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004656 const ObjCInterfaceDecl *ID,
4657 bool IsSuper) {
Fariborz Jahanian917c0402009-02-05 20:41:40 +00004658
4659 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
4660
4661 if (!Entry) {
4662 std::string ClassName("\01_OBJC_CLASS_$_" + ID->getNameAsString());
Daniel Dunbarabbda222009-03-01 04:40:10 +00004663 llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
Fariborz Jahanian917c0402009-02-05 20:41:40 +00004664 Entry =
4665 new llvm::GlobalVariable(ObjCTypes.ClassnfABIPtrTy, false,
4666 llvm::GlobalValue::InternalLinkage,
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004667 ClassGV,
4668 IsSuper ? "\01L_OBJC_CLASSLIST_SUP_REFS_$_"
4669 : "\01L_OBJC_CLASSLIST_REFERENCES_$_",
Fariborz Jahanian917c0402009-02-05 20:41:40 +00004670 &CGM.getModule());
4671 Entry->setAlignment(
4672 CGM.getTargetData().getPrefTypeAlignment(
4673 ObjCTypes.ClassnfABIPtrTy));
4674
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004675 if (IsSuper)
Fariborz Jahanianba825d72009-02-26 22:30:39 +00004676 Entry->setSection("__DATA,__objc_superrefs,regular,no_dead_strip");
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004677 else
Fariborz Jahanianba825d72009-02-26 22:30:39 +00004678 Entry->setSection("__DATA,__objc_classrefs,regular,no_dead_strip");
Fariborz Jahanian917c0402009-02-05 20:41:40 +00004679 UsedGlobals.push_back(Entry);
4680 }
4681
4682 return Builder.CreateLoad(Entry, false, "tmp");
4683}
4684
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004685/// EmitMetaClassRef - Return a Value * of the address of _class_t
4686/// meta-data
4687///
4688llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
4689 const ObjCInterfaceDecl *ID) {
4690 llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
4691 if (Entry)
4692 return Builder.CreateLoad(Entry, false, "tmp");
4693
4694 std::string MetaClassName("\01_OBJC_METACLASS_$_" + ID->getNameAsString());
Daniel Dunbar58e39bb2009-03-01 04:51:18 +00004695 llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004696 Entry =
4697 new llvm::GlobalVariable(ObjCTypes.ClassnfABIPtrTy, false,
4698 llvm::GlobalValue::InternalLinkage,
4699 MetaClassGV,
4700 "\01L_OBJC_CLASSLIST_SUP_REFS_$_",
4701 &CGM.getModule());
4702 Entry->setAlignment(
4703 CGM.getTargetData().getPrefTypeAlignment(
4704 ObjCTypes.ClassnfABIPtrTy));
4705
4706 Entry->setSection("__OBJC,__objc_superrefs,regular,no_dead_strip");
4707 UsedGlobals.push_back(Entry);
4708
4709 return Builder.CreateLoad(Entry, false, "tmp");
4710}
4711
Fariborz Jahanian917c0402009-02-05 20:41:40 +00004712/// GetClass - Return a reference to the class for the given interface
4713/// decl.
4714llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
4715 const ObjCInterfaceDecl *ID) {
4716 return EmitClassRef(Builder, ID);
4717}
4718
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004719/// Generates a message send where the super is the receiver. This is
4720/// a message send to self with special delivery semantics indicating
4721/// which class's method should be called.
4722CodeGen::RValue
4723CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
4724 QualType ResultType,
4725 Selector Sel,
4726 const ObjCInterfaceDecl *Class,
Fariborz Jahanian17636fa2009-02-28 20:07:56 +00004727 bool isCategoryImpl,
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004728 llvm::Value *Receiver,
4729 bool IsClassMessage,
4730 const CodeGen::CallArgList &CallArgs) {
4731 // ...
4732 // Create and init a super structure; this is a (receiver, class)
4733 // pair we will pass to objc_msgSendSuper.
4734 llvm::Value *ObjCSuper =
4735 CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
4736
4737 llvm::Value *ReceiverAsObject =
4738 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
4739 CGF.Builder.CreateStore(ReceiverAsObject,
4740 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
4741
4742 // If this is a class message the metaclass is passed as the target.
Fariborz Jahanian17636fa2009-02-28 20:07:56 +00004743 llvm::Value *Target;
4744 if (IsClassMessage) {
4745 if (isCategoryImpl) {
4746 // Message sent to "super' in a class method defined in
4747 // a category implementation.
4748 Target = EmitClassRef(CGF.Builder, Class, false);
4749 Target = CGF.Builder.CreateStructGEP(Target, 0);
4750 Target = CGF.Builder.CreateLoad(Target);
4751 }
4752 else
4753 Target = EmitMetaClassRef(CGF.Builder, Class);
4754 }
4755 else
4756 Target = EmitClassRef(CGF.Builder, Class, true);
Fariborz Jahanianf3a44012009-02-06 20:09:23 +00004757
4758 // FIXME: We shouldn't need to do this cast, rectify the ASTContext
4759 // and ObjCTypes types.
4760 const llvm::Type *ClassTy =
4761 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
4762 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
4763 CGF.Builder.CreateStore(Target,
4764 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
4765
4766 return EmitMessageSend(CGF, ResultType, Sel,
4767 ObjCSuper, ObjCTypes.SuperPtrCTy,
4768 true, CallArgs);
4769}
Fariborz Jahanianebb82c62009-02-11 20:51:17 +00004770
4771llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
4772 Selector Sel) {
4773 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
4774
4775 if (!Entry) {
4776 llvm::Constant *Casted =
4777 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
4778 ObjCTypes.SelectorPtrTy);
4779 Entry =
4780 new llvm::GlobalVariable(ObjCTypes.SelectorPtrTy, false,
4781 llvm::GlobalValue::InternalLinkage,
4782 Casted, "\01L_OBJC_SELECTOR_REFERENCES_",
4783 &CGM.getModule());
4784 Entry->setSection("__DATA,__objc_selrefs,literal_pointers,no_dead_strip");
4785 UsedGlobals.push_back(Entry);
4786 }
4787
4788 return Builder.CreateLoad(Entry, false, "tmp");
4789}
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00004790/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
4791/// objc_assign_ivar (id src, id *dst)
4792///
4793void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
4794 llvm::Value *src, llvm::Value *dst)
4795{
4796 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4797 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
4798 CGF.Builder.CreateCall2(ObjCTypes.GcAssignIvarFn,
4799 src, dst, "assignivar");
4800 return;
4801}
4802
4803/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
4804/// objc_assign_strongCast (id src, id *dst)
4805///
4806void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
4807 CodeGen::CodeGenFunction &CGF,
4808 llvm::Value *src, llvm::Value *dst)
4809{
4810 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4811 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
4812 CGF.Builder.CreateCall2(ObjCTypes.GcAssignStrongCastFn,
4813 src, dst, "weakassign");
4814 return;
4815}
4816
4817/// EmitObjCWeakRead - Code gen for loading value of a __weak
4818/// object: objc_read_weak (id *src)
4819///
4820llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
4821 CodeGen::CodeGenFunction &CGF,
4822 llvm::Value *AddrWeakObj)
4823{
Eli Friedmanf8466232009-03-07 03:57:15 +00004824 const llvm::Type* DestTy =
4825 cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00004826 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
4827 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.GcReadWeakFn,
4828 AddrWeakObj, "weakread");
Eli Friedmanf8466232009-03-07 03:57:15 +00004829 read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
Fariborz Jahanian5eefb432009-02-16 22:52:32 +00004830 return read_weak;
4831}
4832
4833/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
4834/// objc_assign_weak (id src, id *dst)
4835///
4836void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
4837 llvm::Value *src, llvm::Value *dst)
4838{
4839 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4840 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
4841 CGF.Builder.CreateCall2(ObjCTypes.GcAssignWeakFn,
4842 src, dst, "weakassign");
4843 return;
4844}
4845
4846/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
4847/// objc_assign_global (id src, id *dst)
4848///
4849void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
4850 llvm::Value *src, llvm::Value *dst)
4851{
4852 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
4853 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
4854 CGF.Builder.CreateCall2(ObjCTypes.GcAssignGlobalFn,
4855 src, dst, "globalassign");
4856 return;
4857}
Fariborz Jahanianebb82c62009-02-11 20:51:17 +00004858
Daniel Dunbar75de89f2009-02-24 07:47:38 +00004859void
4860CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
4861 const Stmt &S) {
Daniel Dunbar75de89f2009-02-24 07:47:38 +00004862 bool isTry = isa<ObjCAtTryStmt>(S);
4863 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
4864 llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest();
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004865 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
Daniel Dunbar75de89f2009-02-24 07:47:38 +00004866 llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004867 llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
Daniel Dunbar75de89f2009-02-24 07:47:38 +00004868 llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
4869
4870 // For @synchronized, call objc_sync_enter(sync.expr). The
4871 // evaluation of the expression must occur before we enter the
4872 // @synchronized. We can safely avoid a temp here because jumps into
4873 // @synchronized are illegal & this will dominate uses.
4874 llvm::Value *SyncArg = 0;
4875 if (!isTry) {
4876 SyncArg =
4877 CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
4878 SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
4879 CGF.Builder.CreateCall(ObjCTypes.SyncEnterFn, SyncArg);
4880 }
4881
4882 // Push an EH context entry, used for handling rethrows and jumps
4883 // through finally.
4884 CGF.PushCleanupBlock(FinallyBlock);
4885
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004886 CGF.setInvokeDest(TryHandler);
Daniel Dunbar75de89f2009-02-24 07:47:38 +00004887
4888 CGF.EmitBlock(TryBlock);
4889 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
4890 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
4891 CGF.EmitBranchThroughCleanup(FinallyEnd);
4892
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004893 // Emit the exception handler.
4894
4895 CGF.EmitBlock(TryHandler);
4896
4897 llvm::Value *llvm_eh_exception =
4898 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
4899 llvm::Value *llvm_eh_selector_i64 =
4900 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector_i64);
4901 llvm::Value *llvm_eh_typeid_for_i64 =
4902 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for_i64);
4903 llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
4904 llvm::Value *RethrowPtr = CGF.CreateTempAlloca(Exc->getType(), "_rethrow");
4905
4906 llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
4907 SelectorArgs.push_back(Exc);
4908 SelectorArgs.push_back(ObjCTypes.EHPersonalityPtr);
4909
4910 // Construct the lists of (type, catch body) to handle.
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00004911 llvm::SmallVector<std::pair<const ParmVarDecl*, const Stmt*>, 8> Handlers;
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004912 bool HasCatchAll = false;
4913 if (isTry) {
4914 if (const ObjCAtCatchStmt* CatchStmt =
4915 cast<ObjCAtTryStmt>(S).getCatchStmts()) {
4916 for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00004917 const ParmVarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
Steve Naroff0e8b96a2009-03-03 19:52:17 +00004918 Handlers.push_back(std::make_pair(CatchDecl, CatchStmt->getCatchBody()));
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004919
4920 // catch(...) always matches.
Steve Naroff0e8b96a2009-03-03 19:52:17 +00004921 if (!CatchDecl) {
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004922 // Use i8* null here to signal this is a catch all, not a cleanup.
4923 llvm::Value *Null = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
4924 SelectorArgs.push_back(Null);
4925 HasCatchAll = true;
4926 break;
4927 }
4928
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00004929 if (CGF.getContext().isObjCIdType(CatchDecl->getType()) ||
4930 CatchDecl->getType()->isObjCQualifiedIdType()) {
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004931 llvm::Value *IDEHType =
4932 CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
4933 if (!IDEHType)
4934 IDEHType =
4935 new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
4936 llvm::GlobalValue::ExternalLinkage,
4937 0, "OBJC_EHTYPE_id", &CGM.getModule());
4938 SelectorArgs.push_back(IDEHType);
4939 HasCatchAll = true;
4940 break;
4941 }
4942
4943 // All other types should be Objective-C interface pointer types.
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00004944 const PointerType *PT = CatchDecl->getType()->getAsPointerType();
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004945 assert(PT && "Invalid @catch type.");
4946 const ObjCInterfaceType *IT =
4947 PT->getPointeeType()->getAsObjCInterfaceType();
4948 assert(IT && "Invalid @catch type.");
4949 llvm::Value *EHType = GetInterfaceEHType(IT);
4950 SelectorArgs.push_back(EHType);
4951 }
4952 }
4953 }
4954
4955 // We use a cleanup unless there was already a catch all.
4956 if (!HasCatchAll) {
4957 SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0));
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00004958 Handlers.push_back(std::make_pair((const ParmVarDecl*) 0, (const Stmt*) 0));
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004959 }
4960
4961 llvm::Value *Selector =
4962 CGF.Builder.CreateCall(llvm_eh_selector_i64,
4963 SelectorArgs.begin(), SelectorArgs.end(),
4964 "selector");
4965 for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00004966 const ParmVarDecl *CatchParam = Handlers[i].first;
Daniel Dunbarc0318b22009-03-02 06:08:11 +00004967 const Stmt *CatchBody = Handlers[i].second;
4968
4969 llvm::BasicBlock *Next = 0;
4970
4971 // The last handler always matches.
4972 if (i + 1 != e) {
4973 assert(CatchParam && "Only last handler can be a catch all.");
4974
4975 llvm::BasicBlock *Match = CGF.createBasicBlock("match");
4976 Next = CGF.createBasicBlock("catch.next");
4977 llvm::Value *Id =
4978 CGF.Builder.CreateCall(llvm_eh_typeid_for_i64,
4979 CGF.Builder.CreateBitCast(SelectorArgs[i+2],
4980 ObjCTypes.Int8PtrTy));
4981 CGF.Builder.CreateCondBr(CGF.Builder.CreateICmpEQ(Selector, Id),
4982 Match, Next);
4983
4984 CGF.EmitBlock(Match);
4985 }
4986
4987 if (CatchBody) {
4988 llvm::BasicBlock *MatchEnd = CGF.createBasicBlock("match.end");
4989 llvm::BasicBlock *MatchHandler = CGF.createBasicBlock("match.handler");
4990
4991 // Cleanups must call objc_end_catch.
4992 //
4993 // FIXME: It seems incorrect for objc_begin_catch to be inside
4994 // this context, but this matches gcc.
4995 CGF.PushCleanupBlock(MatchEnd);
4996 CGF.setInvokeDest(MatchHandler);
4997
4998 llvm::Value *ExcObject =
4999 CGF.Builder.CreateCall(ObjCTypes.ObjCBeginCatchFn, Exc);
5000
5001 // Bind the catch parameter if it exists.
5002 if (CatchParam) {
Daniel Dunbar0098e7a2009-03-06 00:01:21 +00005003 ExcObject =
5004 CGF.Builder.CreateBitCast(ExcObject,
5005 CGF.ConvertType(CatchParam->getType()));
5006 // CatchParam is a ParmVarDecl because of the grammar
5007 // construction used to handle this, but for codegen purposes
5008 // we treat this as a local decl.
5009 CGF.EmitLocalBlockVarDecl(*CatchParam);
5010 CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(CatchParam));
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005011 }
5012
5013 CGF.ObjCEHValueStack.push_back(ExcObject);
5014 CGF.EmitStmt(CatchBody);
5015 CGF.ObjCEHValueStack.pop_back();
5016
5017 CGF.EmitBranchThroughCleanup(FinallyEnd);
5018
5019 CGF.EmitBlock(MatchHandler);
5020
5021 llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5022 // We are required to emit this call to satisfy LLVM, even
5023 // though we don't use the result.
5024 llvm::SmallVector<llvm::Value*, 8> Args;
5025 Args.push_back(Exc);
5026 Args.push_back(ObjCTypes.EHPersonalityPtr);
5027 Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty,
5028 0));
5029 CGF.Builder.CreateCall(llvm_eh_selector_i64, Args.begin(), Args.end());
5030 CGF.Builder.CreateStore(Exc, RethrowPtr);
5031 CGF.EmitBranchThroughCleanup(FinallyRethrow);
5032
5033 CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
5034
5035 CGF.EmitBlock(MatchEnd);
5036
5037 // Unfortunately, we also have to generate another EH frame here
5038 // in case this throws.
5039 llvm::BasicBlock *MatchEndHandler =
5040 CGF.createBasicBlock("match.end.handler");
5041 llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
5042 CGF.Builder.CreateInvoke(ObjCTypes.ObjCEndCatchFn,
5043 Cont, MatchEndHandler,
5044 Args.begin(), Args.begin());
5045
5046 CGF.EmitBlock(Cont);
5047 if (Info.SwitchBlock)
5048 CGF.EmitBlock(Info.SwitchBlock);
5049 if (Info.EndBlock)
5050 CGF.EmitBlock(Info.EndBlock);
5051
5052 CGF.EmitBlock(MatchEndHandler);
5053 Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
5054 // We are required to emit this call to satisfy LLVM, even
5055 // though we don't use the result.
5056 Args.clear();
5057 Args.push_back(Exc);
5058 Args.push_back(ObjCTypes.EHPersonalityPtr);
5059 Args.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty,
5060 0));
5061 CGF.Builder.CreateCall(llvm_eh_selector_i64, Args.begin(), Args.end());
5062 CGF.Builder.CreateStore(Exc, RethrowPtr);
5063 CGF.EmitBranchThroughCleanup(FinallyRethrow);
5064
5065 if (Next)
5066 CGF.EmitBlock(Next);
5067 } else {
5068 assert(!Next && "catchup should be last handler.");
5069
5070 CGF.Builder.CreateStore(Exc, RethrowPtr);
5071 CGF.EmitBranchThroughCleanup(FinallyRethrow);
5072 }
5073 }
5074
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005075 // Pop the cleanup entry, the @finally is outside this cleanup
5076 // scope.
5077 CodeGenFunction::CleanupBlockInfo Info = CGF.PopCleanupBlock();
5078 CGF.setInvokeDest(PrevLandingPad);
5079
5080 CGF.EmitBlock(FinallyBlock);
5081
5082 if (isTry) {
5083 if (const ObjCAtFinallyStmt* FinallyStmt =
5084 cast<ObjCAtTryStmt>(S).getFinallyStmt())
5085 CGF.EmitStmt(FinallyStmt->getFinallyBody());
5086 } else {
5087 // Emit 'objc_sync_exit(expr)' as finally's sole statement for
5088 // @synchronized.
5089 CGF.Builder.CreateCall(ObjCTypes.SyncExitFn, SyncArg);
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005090 }
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005091
5092 if (Info.SwitchBlock)
5093 CGF.EmitBlock(Info.SwitchBlock);
5094 if (Info.EndBlock)
5095 CGF.EmitBlock(Info.EndBlock);
5096
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005097 // Branch around the rethrow code.
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005098 CGF.EmitBranch(FinallyEnd);
5099
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005100 CGF.EmitBlock(FinallyRethrow);
5101 CGF.Builder.CreateCall(ObjCTypes.UnwindResumeOrRethrowFn,
5102 CGF.Builder.CreateLoad(RethrowPtr));
Daniel Dunbar75de89f2009-02-24 07:47:38 +00005103 CGF.Builder.CreateUnreachable();
5104
5105 CGF.EmitBlock(FinallyEnd);
5106}
5107
Anders Carlsson1cf75362009-02-16 22:59:18 +00005108/// EmitThrowStmt - Generate code for a throw statement.
5109void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
5110 const ObjCAtThrowStmt &S) {
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005111 llvm::Value *Exception;
Anders Carlsson1cf75362009-02-16 22:59:18 +00005112 if (const Expr *ThrowExpr = S.getThrowExpr()) {
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005113 Exception = CGF.EmitScalarExpr(ThrowExpr);
Anders Carlsson1cf75362009-02-16 22:59:18 +00005114 } else {
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005115 assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
5116 "Unexpected rethrow outside @catch block.");
5117 Exception = CGF.ObjCEHValueStack.back();
Anders Carlsson1cf75362009-02-16 22:59:18 +00005118 }
5119
Daniel Dunbarc0318b22009-03-02 06:08:11 +00005120 llvm::Value *ExceptionAsObject =
5121 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
5122 llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
5123 if (InvokeDest) {
5124 llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
5125 CGF.Builder.CreateInvoke(ObjCTypes.ExceptionThrowFn,
5126 Cont, InvokeDest,
5127 &ExceptionAsObject, &ExceptionAsObject + 1);
5128 CGF.EmitBlock(Cont);
5129 } else
5130 CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn, ExceptionAsObject);
5131 CGF.Builder.CreateUnreachable();
5132
Anders Carlsson1cf75362009-02-16 22:59:18 +00005133 // Clear the insertion point to indicate we are in unreachable code.
5134 CGF.Builder.ClearInsertionPoint();
5135}
Daniel Dunbar9c285e72009-03-01 04:46:24 +00005136
5137llvm::Value *
5138CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceType *IT) {
5139 const ObjCInterfaceDecl *ID = IT->getDecl();
5140 llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
5141 if (Entry)
5142 return Entry;
5143
5144 std::string ClassName("\01_OBJC_CLASS_$_" + ID->getNameAsString());
5145 std::string VTableName = "objc_ehtype_vtable";
5146 llvm::GlobalVariable *VTableGV =
5147 CGM.getModule().getGlobalVariable(VTableName);
5148 if (!VTableGV)
5149 VTableGV = new llvm::GlobalVariable(ObjCTypes.Int8PtrTy, false,
5150 llvm::GlobalValue::ExternalLinkage,
5151 0, VTableName, &CGM.getModule());
5152
5153 llvm::Value *VTableIdx = llvm::ConstantInt::get(llvm::Type::Int32Ty, 2);
5154
5155 std::vector<llvm::Constant*> Values(3);
5156 Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
5157 Values[1] = GetClassName(ID->getIdentifier());
5158 Values[2] = GetClassGlobal(ClassName);
5159 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
5160
5161 Entry =
5162 new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
Mike Stump36dbf222009-03-07 16:33:28 +00005163 llvm::GlobalValue::WeakAnyLinkage,
Daniel Dunbar9c285e72009-03-01 04:46:24 +00005164 Init,
5165 (std::string("OBJC_EHTYPE_$_") +
5166 ID->getIdentifier()->getName()),
5167 &CGM.getModule());
5168
5169 return Entry;
5170}
Anders Carlsson1cf75362009-02-16 22:59:18 +00005171
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00005172/* *** */
5173
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00005174CodeGen::CGObjCRuntime *
5175CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00005176 return new CGObjCMac(CGM);
5177}
Fariborz Jahanian48543f52009-01-21 22:04:16 +00005178
5179CodeGen::CGObjCRuntime *
Fariborz Jahaniand0374812009-01-22 23:02:58 +00005180CodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) {
Fariborz Jahanianc2a1c3e2009-01-23 23:53:38 +00005181 return new CGObjCNonFragileABIMac(CGM);
Fariborz Jahanian48543f52009-01-21 22:04:16 +00005182}