blob: 133c9fd9691da2faff78c2a9c74e56a718c9a192 [file] [log] [blame]
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides Objective-C code generation targetting the Apple runtime.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000015
16#include "CodeGenModule.h"
Daniel Dunbarb7ec2462008-08-16 03:19:19 +000017#include "CodeGenFunction.h"
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000018#include "clang/AST/ASTContext.h"
Daniel Dunbare91593e2008-08-11 04:54:23 +000019#include "clang/AST/Decl.h"
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000020#include "clang/AST/DeclObjC.h"
Daniel Dunbarf77ac862008-08-11 21:35:06 +000021#include "clang/Basic/LangOptions.h"
22
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000023#include "llvm/Module.h"
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +000024#include "llvm/ADT/DenseSet.h"
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +000025#include "llvm/Target/TargetData.h"
Daniel Dunbarb7ec2462008-08-16 03:19:19 +000026#include <sstream>
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000027
28using namespace clang;
Daniel Dunbar46f45b92008-09-09 01:06:48 +000029using namespace CodeGen;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +000030
31namespace {
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000032
Daniel Dunbarae226fa2008-08-27 02:31:56 +000033 typedef std::vector<llvm::Constant*> ConstantVector;
34
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000035 // FIXME: We should find a nicer way to make the labels for
36 // metadata, string concatenation is lame.
37
Fariborz Jahanianee0af742009-01-21 22:04:16 +000038class ObjCCommonTypesHelper {
39protected:
40 CodeGen::CodeGenModule &CGM;
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000041
Daniel Dunbarbbce49b2008-08-12 00:12:39 +000042public:
Daniel Dunbar27f9d772008-08-21 04:36:09 +000043 const llvm::Type *ShortTy, *IntTy, *LongTy;
44 const llvm::Type *Int8PtrTy;
Fariborz Jahanianee0af742009-01-21 22:04:16 +000045
Daniel Dunbar2bedbf82008-08-12 05:28:47 +000046 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
47 const llvm::Type *ObjectPtrTy;
Fariborz Jahanian6d657c42008-11-18 20:18:11 +000048
49 /// PtrObjectPtrTy - LLVM type for id *
50 const llvm::Type *PtrObjectPtrTy;
51
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +000052 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Daniel Dunbar2bedbf82008-08-12 05:28:47 +000053 const llvm::Type *SelectorPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +000054 /// ProtocolPtrTy - LLVM type for external protocol handles
55 /// (typeof(Protocol))
56 const llvm::Type *ExternalProtocolPtrTy;
Fariborz Jahanianee0af742009-01-21 22:04:16 +000057
Daniel Dunbar19cd87e2008-08-30 03:02:31 +000058 // SuperCTy - clang type for struct objc_super.
59 QualType SuperCTy;
60 // SuperPtrCTy - clang type for struct objc_super *.
61 QualType SuperPtrCTy;
Fariborz Jahanianee0af742009-01-21 22:04:16 +000062
Daniel Dunbare8b470d2008-08-23 04:28:29 +000063 /// SuperTy - LLVM type for struct objc_super.
64 const llvm::StructType *SuperTy;
Daniel Dunbar14c80b72008-08-23 09:25:55 +000065 /// SuperPtrTy - LLVM type for struct objc_super *.
66 const llvm::Type *SuperPtrTy;
Fariborz Jahanianee0af742009-01-21 22:04:16 +000067
Fariborz Jahanian30bc5712009-01-22 23:02:58 +000068 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
69 /// in GCC parlance).
70 const llvm::StructType *PropertyTy;
71
72 /// PropertyListTy - LLVM type for struct objc_property_list
73 /// (_prop_list_t in GCC parlance).
74 const llvm::StructType *PropertyListTy;
75 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
76 const llvm::Type *PropertyListPtrTy;
77
78 // MethodTy - LLVM type for struct objc_method.
79 const llvm::StructType *MethodTy;
80
Fariborz Jahaniandb286862009-01-22 00:37:21 +000081 llvm::Function *GetPropertyFn, *SetPropertyFn;
82
83 llvm::Function *EnumerationMutationFn;
84
85 /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
86 llvm::Function *GcReadWeakFn;
87
88 /// GcAssignWeakFn -- LLVM objc_assign_weak function.
89 llvm::Function *GcAssignWeakFn;
90
91 /// GcAssignGlobalFn -- LLVM objc_assign_global function.
92 llvm::Function *GcAssignGlobalFn;
93
94 /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
95 llvm::Function *GcAssignIvarFn;
96
97 /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
98 llvm::Function *GcAssignStrongCastFn;
99
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000100 ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
101 ~ObjCCommonTypesHelper(){}
102};
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000103
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000104/// ObjCTypesHelper - Helper class that encapsulates lazy
105/// construction of varies types used during ObjC generation.
106class ObjCTypesHelper : public ObjCCommonTypesHelper {
107private:
108
109 llvm::Function *MessageSendFn, *MessageSendStretFn, *MessageSendFpretFn;
110 llvm::Function *MessageSendSuperFn, *MessageSendSuperStretFn,
111 *MessageSendSuperFpretFn;
112
113public:
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000114 /// SymtabTy - LLVM type for struct objc_symtab.
115 const llvm::StructType *SymtabTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000116 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
117 const llvm::Type *SymtabPtrTy;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000118 /// ModuleTy - LLVM type for struct objc_module.
119 const llvm::StructType *ModuleTy;
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000120
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000121 /// ProtocolTy - LLVM type for struct objc_protocol.
122 const llvm::StructType *ProtocolTy;
123 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
124 const llvm::Type *ProtocolPtrTy;
125 /// ProtocolExtensionTy - LLVM type for struct
126 /// objc_protocol_extension.
127 const llvm::StructType *ProtocolExtensionTy;
128 /// ProtocolExtensionTy - LLVM type for struct
129 /// objc_protocol_extension *.
130 const llvm::Type *ProtocolExtensionPtrTy;
131 /// MethodDescriptionTy - LLVM type for struct
132 /// objc_method_description.
133 const llvm::StructType *MethodDescriptionTy;
134 /// MethodDescriptionListTy - LLVM type for struct
135 /// objc_method_description_list.
136 const llvm::StructType *MethodDescriptionListTy;
137 /// MethodDescriptionListPtrTy - LLVM type for struct
138 /// objc_method_description_list *.
139 const llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000140 /// ProtocolListTy - LLVM type for struct objc_property_list.
141 const llvm::Type *ProtocolListTy;
142 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
143 const llvm::Type *ProtocolListPtrTy;
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000144 /// CategoryTy - LLVM type for struct objc_category.
145 const llvm::StructType *CategoryTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000146 /// ClassTy - LLVM type for struct objc_class.
147 const llvm::StructType *ClassTy;
148 /// ClassPtrTy - LLVM type for struct objc_class *.
149 const llvm::Type *ClassPtrTy;
150 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
151 const llvm::StructType *ClassExtensionTy;
152 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
153 const llvm::Type *ClassExtensionPtrTy;
154 /// CacheTy - LLVM type for struct objc_cache.
155 const llvm::Type *CacheTy;
156 /// CachePtrTy - LLVM type for struct objc_cache *.
157 const llvm::Type *CachePtrTy;
158 // IvarTy - LLVM type for struct objc_ivar.
159 const llvm::StructType *IvarTy;
160 /// IvarListTy - LLVM type for struct objc_ivar_list.
161 const llvm::Type *IvarListTy;
162 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
163 const llvm::Type *IvarListPtrTy;
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000164 /// MethodListTy - LLVM type for struct objc_method_list.
165 const llvm::Type *MethodListTy;
166 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
167 const llvm::Type *MethodListPtrTy;
Anders Carlsson124526b2008-09-09 10:10:21 +0000168
169 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
170 const llvm::Type *ExceptionDataTy;
171
172 /// ExceptionThrowFn - LLVM objc_exception_throw function.
173 llvm::Function *ExceptionThrowFn;
174
175 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
176 llvm::Function *ExceptionTryEnterFn;
177
178 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
179 llvm::Function *ExceptionTryExitFn;
180
181 /// ExceptionExtractFn - LLVM objc_exception_extract function.
182 llvm::Function *ExceptionExtractFn;
183
184 /// ExceptionMatchFn - LLVM objc_exception_match function.
185 llvm::Function *ExceptionMatchFn;
186
187 /// SetJmpFn - LLVM _setjmp function.
188 llvm::Function *SetJmpFn;
Chris Lattner10cac6f2008-11-15 21:26:17 +0000189
190 /// SyncEnterFn - LLVM object_sync_enter function.
191 llvm::Function *SyncEnterFn;
192
193 /// SyncExitFn - LLVM object_sync_exit function.
194 llvm::Function *SyncExitFn;
195
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000196public:
197 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000198 ~ObjCTypesHelper() {}
Daniel Dunbar5669e572008-10-17 03:24:53 +0000199
200
201 llvm::Function *getSendFn(bool IsSuper) {
202 return IsSuper ? MessageSendSuperFn : MessageSendFn;
203 }
204
205 llvm::Function *getSendStretFn(bool IsSuper) {
206 return IsSuper ? MessageSendSuperStretFn : MessageSendStretFn;
207 }
208
209 llvm::Function *getSendFpretFn(bool IsSuper) {
210 return IsSuper ? MessageSendSuperFpretFn : MessageSendFpretFn;
211 }
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000212};
213
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000214/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000215/// modern abi
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000216class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000217public:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000218 ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
219 ~ObjCNonFragileABITypesHelper(){}
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000220};
221
222class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
223protected:
224 CodeGen::CodeGenModule &CGM;
225 // FIXME! May not be needing this after all.
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000226 unsigned ObjCABI;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000227
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000228 /// LazySymbols - Symbols to generate a lazy reference for. See
229 /// DefinedSymbols and FinishModule().
230 std::set<IdentifierInfo*> LazySymbols;
231
232 /// DefinedSymbols - External symbols which are defined by this
233 /// module. The symbols in this list and LazySymbols are used to add
234 /// special linker symbols which ensure that Objective-C modules are
235 /// linked properly.
236 std::set<IdentifierInfo*> DefinedSymbols;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000237
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000238 /// ClassNames - uniqued class names.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000239 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000240
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000241 /// MethodVarNames - uniqued method variable names.
242 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000243
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000244 /// MethodVarTypes - uniqued method type signatures. We have to use
245 /// a StringMap here because have no other unique reference.
246 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000247
Daniel Dunbarc45ef602008-08-26 21:51:14 +0000248 /// MethodDefinitions - map of methods which have been defined in
249 /// this translation unit.
250 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000251
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000252 /// PropertyNames - uniqued method variable names.
253 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000254
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000255 /// ClassReferences - uniqued class references.
256 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000257
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000258 /// SelectorReferences - uniqued selector references.
259 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000260
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000261 /// Protocols - Protocols for which an objc_protocol structure has
262 /// been emitted. Forward declarations are handled by creating an
263 /// empty structure whose initializer is filled in when/if defined.
264 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000265
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000266 /// DefinedProtocols - Protocols which have actually been
267 /// defined. We should not need this, see FIXME in GenerateProtocol.
268 llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000269
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000270 /// DefinedClasses - List of defined classes.
271 std::vector<llvm::GlobalValue*> DefinedClasses;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000272
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000273 /// DefinedCategories - List of defined categories.
274 std::vector<llvm::GlobalValue*> DefinedCategories;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000275
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000276 /// UsedGlobals - List of globals to pack into the llvm.used metadata
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000277 /// to prevent them from being clobbered.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000278 std::vector<llvm::GlobalVariable*> UsedGlobals;
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000279
Fariborz Jahanian56210f72009-01-21 23:34:32 +0000280 /// GetNameForMethod - Return a name for the given method.
281 /// \param[out] NameOut - The return value.
282 void GetNameForMethod(const ObjCMethodDecl *OMD,
283 const ObjCContainerDecl *CD,
284 std::string &NameOut);
285
286 /// GetMethodVarName - Return a unique constant for the given
287 /// selector's name. The return value has type char *.
288 llvm::Constant *GetMethodVarName(Selector Sel);
289 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
290 llvm::Constant *GetMethodVarName(const std::string &Name);
291
292 /// GetMethodVarType - Return a unique constant for the given
293 /// selector's name. The return value has type char *.
294
295 // FIXME: This is a horrible name.
296 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
297 llvm::Constant *GetMethodVarType(const std::string &Name);
298
299 /// GetPropertyName - Return a unique constant for the given
300 /// name. The return value has type char *.
301 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
302
303 // FIXME: This can be dropped once string functions are unified.
304 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
305 const Decl *Container);
306
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000307public:
308 CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGM(cgm)
309 { }
310};
311
312class CGObjCMac : public CGObjCCommonMac {
313private:
314 ObjCTypesHelper ObjCTypes;
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000315 /// EmitImageInfo - Emit the image info marker used to encode some module
316 /// level information.
317 void EmitImageInfo();
318
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000319 /// EmitModuleInfo - Another marker encoding module level
320 /// information.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000321 void EmitModuleInfo();
322
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000323 /// EmitModuleSymols - Emit module symbols, the list of defined
324 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000325 llvm::Constant *EmitModuleSymbols();
326
Daniel Dunbarf77ac862008-08-11 21:35:06 +0000327 /// FinishModule - Write out global data structures at the end of
328 /// processing a translation unit.
329 void FinishModule();
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000330
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000331 /// EmitClassExtension - Generate the class extension structure used
332 /// to store the weak ivar layout and properties. The return value
333 /// has type ClassExtensionPtrTy.
334 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
335
336 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
337 /// for the given class.
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000338 llvm::Value *EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000339 const ObjCInterfaceDecl *ID);
340
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000341 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000342 QualType ResultType,
343 Selector Sel,
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000344 llvm::Value *Arg0,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000345 QualType Arg0Ty,
346 bool IsSuper,
347 const CallArgList &CallArgs);
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000348
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000349 /// EmitIvarList - Emit the ivar list for the given
350 /// implementation. If ForClass is true the list of class ivars
351 /// (i.e. metaclass ivars) is emitted, otherwise the list of
352 /// interface ivars will be emitted. The return value has type
353 /// IvarListPtrTy.
354 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
355 bool ForClass,
356 const llvm::Type *InterfaceTy);
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000357
358 /// EmitMetaClass - Emit a forward reference to the class structure
359 /// for the metaclass of the given interface. The return value has
360 /// type ClassPtrTy.
361 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
362
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000363 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000364 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000365 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
366 llvm::Constant *Protocols,
Daniel Dunbarc45ef602008-08-26 21:51:14 +0000367 const llvm::Type *InterfaceTy,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000368 const ConstantVector &Methods);
369
370 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
371
372 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000373
374 /// EmitMethodList - Emit the method list for the given
Daniel Dunbaraf05bb92008-08-26 08:29:31 +0000375 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000376 llvm::Constant *EmitMethodList(const std::string &Name,
377 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000378 const ConstantVector &Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000379
380 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000381 /// method declarations.
382 /// - TypeName: The name for the type containing the methods.
383 /// - IsProtocol: True iff these methods are for a protocol.
384 /// - ClassMethds: True iff these are class methods.
385 /// - Required: When true, only "required" methods are
386 /// listed. Similarly, when false only "optional" methods are
387 /// listed. For classes this should always be true.
388 /// - begin, end: The method list to output.
389 ///
390 /// The return value has type MethodDescriptionListPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000391 llvm::Constant *EmitMethodDescList(const std::string &Name,
392 const char *Section,
393 const ConstantVector &Methods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000394
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000395 /// EmitPropertyList - Emit the given property list. The return
396 /// value has type PropertyListPtrTy.
397 llvm::Constant *EmitPropertyList(const std::string &Name,
Steve Naroff93983f82009-01-11 12:47:58 +0000398 const Decl *Container,
399 const ObjCContainerDecl *OCD);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000400
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000401 /// GetOrEmitProtocol - Get the protocol object for the given
402 /// declaration, emitting it if necessary. The return value has type
403 /// ProtocolPtrTy.
404 llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
405
406 /// GetOrEmitProtocolRef - Get a forward reference to the protocol
407 /// object for the given declaration, emitting it if needed. These
408 /// forward references will be filled in with empty bodies if no
409 /// definition is seen. The return value has type ProtocolPtrTy.
410 llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
411
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000412 /// EmitProtocolExtension - Generate the protocol extension
413 /// structure used to store optional instance and class methods, and
414 /// protocol properties. The return value has type
415 /// ProtocolExtensionPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000416 llvm::Constant *
417 EmitProtocolExtension(const ObjCProtocolDecl *PD,
418 const ConstantVector &OptInstanceMethods,
419 const ConstantVector &OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000420
421 /// EmitProtocolList - Generate the list of referenced
422 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbardbc93372008-08-21 21:57:41 +0000423 llvm::Constant *EmitProtocolList(const std::string &Name,
424 ObjCProtocolDecl::protocol_iterator begin,
425 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000426
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000427 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
428 /// for the given selector.
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000429 llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000430
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000431 /// GetProtocolRef - Return a reference to the internal protocol
432 /// description, creating an empty one if it has not been
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000433 /// defined. The return value has type ProtocolPtrTy.
434 llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000435
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000436 /// GetClassName - Return a unique constant for the given selector's
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000437 /// name. The return value has type char *.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000438 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +0000439
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000440public:
441 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000442 virtual llvm::Constant *GenerateConstantString(const std::string &String);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000443
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000444 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000445 QualType ResultType,
446 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000447 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000448 bool IsClassMessage,
449 const CallArgList &CallArgs);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000450
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000451 virtual CodeGen::RValue
452 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000453 QualType ResultType,
454 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000455 const ObjCInterfaceDecl *Class,
456 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000457 bool IsClassMessage,
458 const CallArgList &CallArgs);
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +0000459
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000460 virtual llvm::Value *GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000461 const ObjCInterfaceDecl *ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000462
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000463 virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000464
Fariborz Jahanian679a5022009-01-10 21:06:09 +0000465 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
466 const ObjCContainerDecl *CD=0);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000467
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000468 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000469
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000470 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000471
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000472 virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000473 const ObjCProtocolDecl *PD);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000474
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000475 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000476
477 virtual llvm::Function *ModuleInitFunction();
Daniel Dunbar49f66022008-09-24 03:38:44 +0000478 virtual llvm::Function *GetPropertyGetFunction();
479 virtual llvm::Function *GetPropertySetFunction();
Anders Carlsson2abd89c2008-08-31 04:05:03 +0000480 virtual llvm::Function *EnumerationMutationFunction();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +0000481
Fariborz Jahanianbd71be42008-11-21 00:49:24 +0000482 virtual void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
483 const Stmt &S);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +0000484 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
485 const ObjCAtThrowStmt &S);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +0000486 virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6dc23172008-11-18 21:45:40 +0000487 llvm::Value *AddrWeakObj);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +0000488 virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
489 llvm::Value *src, llvm::Value *dst);
Fariborz Jahanian58626502008-11-19 00:59:10 +0000490 virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
491 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian7eda8362008-11-20 19:23:36 +0000492 virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
493 llvm::Value *src, llvm::Value *dest);
Fariborz Jahanian58626502008-11-19 00:59:10 +0000494 virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
495 llvm::Value *src, llvm::Value *dest);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000496};
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000497
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000498class CGObjCNonFragileABIMac : public CGObjCCommonMac {
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000499private:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000500 ObjCNonFragileABITypesHelper ObjCTypes;
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000501public:
Fariborz Jahanian30bc5712009-01-22 23:02:58 +0000502 CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000503};
504
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000505} // end anonymous namespace
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000506
507/* *** Helper Functions *** */
508
509/// getConstantGEP() - Help routine to construct simple GEPs.
510static llvm::Constant *getConstantGEP(llvm::Constant *C,
511 unsigned idx0,
512 unsigned idx1) {
513 llvm::Value *Idxs[] = {
514 llvm::ConstantInt::get(llvm::Type::Int32Ty, idx0),
515 llvm::ConstantInt::get(llvm::Type::Int32Ty, idx1)
516 };
517 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
518}
519
520/* *** CGObjCMac Public Interface *** */
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000521
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000522CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
523 ObjCTypes(cgm)
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000524{
Fariborz Jahanianee0af742009-01-21 22:04:16 +0000525 ObjCABI = 1;
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000526 EmitImageInfo();
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000527}
528
Daniel Dunbarddb2a3d2008-08-16 00:25:02 +0000529/// GetClass - Return a reference to the class for the given interface
530/// decl.
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000531llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000532 const ObjCInterfaceDecl *ID) {
533 return EmitClassRef(Builder, ID);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000534}
535
536/// GetSelector - Return the pointer to the unique'd string for this selector.
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000537llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +0000538 return EmitSelector(Builder, Sel);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000539}
540
Daniel Dunbarbbce49b2008-08-12 00:12:39 +0000541/// Generate a constant CFString object.
542/*
543 struct __builtin_CFString {
544 const int *isa; // point to __CFConstantStringClassReference
545 int flags;
546 const char *str;
547 long length;
548 };
549*/
550
551llvm::Constant *CGObjCMac::GenerateConstantString(const std::string &String) {
Daniel Dunbar3e9df992008-08-23 18:37:06 +0000552 return CGM.GetAddrOfConstantCFString(String);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000553}
554
555/// Generates a message send where the super is the receiver. This is
556/// a message send to self with special delivery semantics indicating
557/// which class's method should be called.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000558CodeGen::RValue
559CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000560 QualType ResultType,
561 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000562 const ObjCInterfaceDecl *Class,
563 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000564 bool IsClassMessage,
Daniel Dunbar46f45b92008-09-09 01:06:48 +0000565 const CodeGen::CallArgList &CallArgs) {
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000566 // Create and init a super structure; this is a (receiver, class)
567 // pair we will pass to objc_msgSendSuper.
568 llvm::Value *ObjCSuper =
569 CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
570 llvm::Value *ReceiverAsObject =
571 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
572 CGF.Builder.CreateStore(ReceiverAsObject,
573 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbare8b470d2008-08-23 04:28:29 +0000574
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000575 // If this is a class message the metaclass is passed as the target.
576 llvm::Value *Target;
577 if (IsClassMessage) {
578 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
579 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
580 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
581 Target = Super;
582 } else {
583 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
584 }
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000585 // FIXME: We shouldn't need to do this cast, rectify the ASTContext
586 // and ObjCTypes types.
587 const llvm::Type *ClassTy =
588 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000589 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000590 CGF.Builder.CreateStore(Target,
591 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
592
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000593 return EmitMessageSend(CGF, ResultType, Sel,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000594 ObjCSuper, ObjCTypes.SuperPtrCTy,
595 true, CallArgs);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000596}
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000597
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000598/// Generate code for a message send expression.
Daniel Dunbar8f2926b2008-08-23 03:46:30 +0000599CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000600 QualType ResultType,
601 Selector Sel,
Daniel Dunbarf56f1912008-08-25 08:19:24 +0000602 llvm::Value *Receiver,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000603 bool IsClassMessage,
604 const CallArgList &CallArgs) {
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000605 llvm::Value *Arg0 =
606 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000607 return EmitMessageSend(CGF, ResultType, Sel,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000608 Arg0, CGF.getContext().getObjCIdType(),
609 false, CallArgs);
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000610}
611
612CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar7f8ea5c2008-08-30 05:35:15 +0000613 QualType ResultType,
614 Selector Sel,
Daniel Dunbar14c80b72008-08-23 09:25:55 +0000615 llvm::Value *Arg0,
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000616 QualType Arg0Ty,
617 bool IsSuper,
618 const CallArgList &CallArgs) {
619 CallArgList ActualArgs;
Daniel Dunbar46f45b92008-09-09 01:06:48 +0000620 ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
621 ActualArgs.push_back(std::make_pair(RValue::get(EmitSelector(CGF.Builder,
622 Sel)),
Daniel Dunbar19cd87e2008-08-30 03:02:31 +0000623 CGF.getContext().getObjCSelType()));
624 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000625
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000626 const llvm::FunctionType *FTy =
627 CGM.getTypes().GetFunctionType(CGCallInfo(ResultType, ActualArgs),
628 false);
Daniel Dunbar5669e572008-10-17 03:24:53 +0000629
630 llvm::Constant *Fn;
631 if (CGM.ReturnTypeUsesSret(ResultType)) {
632 Fn = ObjCTypes.getSendStretFn(IsSuper);
633 } else if (ResultType->isFloatingType()) {
634 // FIXME: Sadly, this is wrong. This actually depends on the
635 // architecture. This happens to be right for x86-32 though.
636 Fn = ObjCTypes.getSendFpretFn(IsSuper);
637 } else {
638 Fn = ObjCTypes.getSendFn(IsSuper);
639 }
Daniel Dunbar62d5c1b2008-09-10 07:00:50 +0000640 Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
Daniel Dunbar3913f182008-09-09 23:48:28 +0000641 return CGF.EmitCall(Fn, ResultType, ActualArgs);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000642}
643
Daniel Dunbar45d196b2008-11-01 01:53:16 +0000644llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
Daniel Dunbaraf2f62c2008-08-13 00:59:25 +0000645 const ObjCProtocolDecl *PD) {
Daniel Dunbarc67876d2008-09-04 04:33:15 +0000646 // FIXME: I don't understand why gcc generates this, or where it is
647 // resolved. Investigate. Its also wasteful to look this up over and
648 // over.
649 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
650
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000651 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
652 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000653}
654
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000655void CGObjCMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
656 // FIXME: We shouldn't need this, the protocol decl should contain
657 // enough information to tell us whether this was a declaration or a
658 // definition.
659 DefinedProtocols.insert(PD->getIdentifier());
660
661 // If we have generated a forward reference to this protocol, emit
662 // it now. Otherwise do nothing, the protocol objects are lazily
663 // emitted.
664 if (Protocols.count(PD->getIdentifier()))
665 GetOrEmitProtocol(PD);
666}
667
668llvm::Constant *CGObjCMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
669 if (DefinedProtocols.count(PD->getIdentifier()))
670 return GetOrEmitProtocol(PD);
671 return GetOrEmitProtocolRef(PD);
672}
673
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000674/*
675 // APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
676 struct _objc_protocol {
677 struct _objc_protocol_extension *isa;
678 char *protocol_name;
679 struct _objc_protocol_list *protocol_list;
680 struct _objc__method_prototype_list *instance_methods;
681 struct _objc__method_prototype_list *class_methods
682 };
683
684 See EmitProtocolExtension().
685*/
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000686llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
687 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
688
689 // Early exit if a defining object has already been generated.
690 if (Entry && Entry->hasInitializer())
691 return Entry;
692
Daniel Dunbar242d4dc2008-08-25 06:02:07 +0000693 // FIXME: I don't understand why gcc generates this, or where it is
694 // resolved. Investigate. Its also wasteful to look this up over and
695 // over.
696 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
697
Chris Lattner8ec03f52008-11-24 03:54:41 +0000698 const char *ProtocolName = PD->getNameAsCString();
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000699
700 // Construct method lists.
701 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
702 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
703 for (ObjCProtocolDecl::instmeth_iterator i = PD->instmeth_begin(),
704 e = PD->instmeth_end(); i != e; ++i) {
705 ObjCMethodDecl *MD = *i;
706 llvm::Constant *C = GetMethodDescriptionConstant(MD);
707 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
708 OptInstanceMethods.push_back(C);
709 } else {
710 InstanceMethods.push_back(C);
711 }
712 }
713
714 for (ObjCProtocolDecl::classmeth_iterator i = PD->classmeth_begin(),
715 e = PD->classmeth_end(); i != e; ++i) {
716 ObjCMethodDecl *MD = *i;
717 llvm::Constant *C = GetMethodDescriptionConstant(MD);
718 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
719 OptClassMethods.push_back(C);
720 } else {
721 ClassMethods.push_back(C);
722 }
723 }
724
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000725 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000726 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000727 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbardbc93372008-08-21 21:57:41 +0000728 Values[2] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000729 EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getNameAsString(),
Daniel Dunbardbc93372008-08-21 21:57:41 +0000730 PD->protocol_begin(),
731 PD->protocol_end());
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000732 Values[3] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000733 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_"
734 + PD->getNameAsString(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000735 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
736 InstanceMethods);
737 Values[4] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000738 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_"
739 + PD->getNameAsString(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000740 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
741 ClassMethods);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000742 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
743 Values);
744
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000745 if (Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000746 // Already created, fix the linkage and update the initializer.
747 Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000748 Entry->setInitializer(Init);
749 } else {
750 Entry =
751 new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false,
752 llvm::GlobalValue::InternalLinkage,
753 Init,
754 std::string("\01L_OBJC_PROTOCOL_")+ProtocolName,
755 &CGM.getModule());
756 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
757 UsedGlobals.push_back(Entry);
758 // FIXME: Is this necessary? Why only for protocol?
759 Entry->setAlignment(4);
760 }
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000761
762 return Entry;
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000763}
764
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000765llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000766 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
767
768 if (!Entry) {
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000769 // We use the initializer as a marker of whether this is a forward
770 // reference or not. At module finalization we add the empty
771 // contents for protocols which were referenced but never defined.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000772 Entry =
773 new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false,
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +0000774 llvm::GlobalValue::ExternalLinkage,
775 0,
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000776 "\01L_OBJC_PROTOCOL_" + PD->getNameAsString(),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000777 &CGM.getModule());
778 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
779 UsedGlobals.push_back(Entry);
780 // FIXME: Is this necessary? Why only for protocol?
781 Entry->setAlignment(4);
782 }
783
784 return Entry;
785}
786
787/*
788 struct _objc_protocol_extension {
789 uint32_t size;
790 struct objc_method_description_list *optional_instance_methods;
791 struct objc_method_description_list *optional_class_methods;
792 struct objc_property_list *instance_properties;
793 };
794*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000795llvm::Constant *
796CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
797 const ConstantVector &OptInstanceMethods,
798 const ConstantVector &OptClassMethods) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000799 uint64_t Size =
Daniel Dunbar491c7b72009-01-12 21:08:18 +0000800 CGM.getTargetData().getTypePaddedSize(ObjCTypes.ProtocolExtensionTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000801 std::vector<llvm::Constant*> Values(4);
802 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000803 Values[1] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000804 EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
805 + PD->getNameAsString(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000806 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
807 OptInstanceMethods);
808 Values[2] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000809 EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_"
810 + PD->getNameAsString(),
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000811 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
812 OptClassMethods);
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000813 Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" +
814 PD->getNameAsString(),
Steve Naroff93983f82009-01-11 12:47:58 +0000815 0, PD);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000816
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000817 // Return null if no extension bits are used.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000818 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
819 Values[3]->isNullValue())
820 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
821
822 llvm::Constant *Init =
823 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
824 llvm::GlobalVariable *GV =
825 new llvm::GlobalVariable(ObjCTypes.ProtocolExtensionTy, false,
826 llvm::GlobalValue::InternalLinkage,
827 Init,
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000828 "\01L_OBJC_PROTOCOLEXT_" + PD->getNameAsString(),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000829 &CGM.getModule());
830 // No special section, but goes in llvm.used
831 UsedGlobals.push_back(GV);
832
833 return GV;
834}
835
836/*
837 struct objc_protocol_list {
838 struct objc_protocol_list *next;
839 long count;
840 Protocol *list[];
841 };
842*/
Daniel Dunbardbc93372008-08-21 21:57:41 +0000843llvm::Constant *
844CGObjCMac::EmitProtocolList(const std::string &Name,
845 ObjCProtocolDecl::protocol_iterator begin,
846 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000847 std::vector<llvm::Constant*> ProtocolRefs;
848
Daniel Dunbardbc93372008-08-21 21:57:41 +0000849 for (; begin != end; ++begin)
850 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000851
852 // Just return null for empty protocol lists
853 if (ProtocolRefs.empty())
854 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
855
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000856 // This list is null terminated.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000857 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
858
859 std::vector<llvm::Constant*> Values(3);
Daniel Dunbar27f9d772008-08-21 04:36:09 +0000860 // This field is only used by the runtime.
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000861 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
862 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
863 Values[2] =
864 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
865 ProtocolRefs.size()),
866 ProtocolRefs);
867
868 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
869 llvm::GlobalVariable *GV =
870 new llvm::GlobalVariable(Init->getType(), false,
871 llvm::GlobalValue::InternalLinkage,
872 Init,
Daniel Dunbardbc93372008-08-21 21:57:41 +0000873 Name,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000874 &CGM.getModule());
875 GV->setSection("__OBJC,__cat_cls_meth,regular,no_dead_strip");
876 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
877}
878
879/*
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000880 struct _objc_property {
881 const char * const name;
882 const char * const attributes;
883 };
884
885 struct _objc_property_list {
886 uint32_t entsize; // sizeof (struct _objc_property)
887 uint32_t prop_count;
888 struct _objc_property[prop_count];
889 };
890*/
891llvm::Constant *CGObjCMac::EmitPropertyList(const std::string &Name,
Daniel Dunbarc56f34a2008-08-28 04:38:10 +0000892 const Decl *Container,
Steve Naroff93983f82009-01-11 12:47:58 +0000893 const ObjCContainerDecl *OCD) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000894 std::vector<llvm::Constant*> Properties, Prop(2);
Steve Naroff93983f82009-01-11 12:47:58 +0000895 for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
896 E = OCD->prop_end(); I != E; ++I) {
897 const ObjCPropertyDecl *PD = *I;
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000898 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbarc56f34a2008-08-28 04:38:10 +0000899 Prop[1] = GetPropertyTypeString(PD, Container);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000900 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
901 Prop));
902 }
903
904 // Return null for empty list.
905 if (Properties.empty())
906 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
907
908 unsigned PropertySize =
Daniel Dunbar491c7b72009-01-12 21:08:18 +0000909 CGM.getTargetData().getTypePaddedSize(ObjCTypes.PropertyTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +0000910 std::vector<llvm::Constant*> Values(3);
911 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
912 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
913 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
914 Properties.size());
915 Values[2] = llvm::ConstantArray::get(AT, Properties);
916 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
917
918 llvm::GlobalVariable *GV =
919 new llvm::GlobalVariable(Init->getType(), false,
920 llvm::GlobalValue::InternalLinkage,
921 Init,
922 Name,
923 &CGM.getModule());
924 // No special section on property lists?
925 UsedGlobals.push_back(GV);
926 return llvm::ConstantExpr::getBitCast(GV,
927 ObjCTypes.PropertyListPtrTy);
928
929}
930
931/*
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000932 struct objc_method_description_list {
933 int count;
934 struct objc_method_description list[];
935 };
936*/
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000937llvm::Constant *
938CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
939 std::vector<llvm::Constant*> Desc(2);
940 Desc[0] = llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
941 ObjCTypes.SelectorPtrTy);
942 Desc[1] = GetMethodVarType(MD);
943 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
944 Desc);
945}
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000946
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000947llvm::Constant *CGObjCMac::EmitMethodDescList(const std::string &Name,
948 const char *Section,
949 const ConstantVector &Methods) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000950 // Return null for empty list.
951 if (Methods.empty())
952 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
953
954 std::vector<llvm::Constant*> Values(2);
955 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
956 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
957 Methods.size());
958 Values[1] = llvm::ConstantArray::get(AT, Methods);
959 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
960
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000961 llvm::GlobalVariable *GV =
962 new llvm::GlobalVariable(Init->getType(), false,
963 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarae226fa2008-08-27 02:31:56 +0000964 Init, Name, &CGM.getModule());
965 GV->setSection(Section);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +0000966 UsedGlobals.push_back(GV);
967 return llvm::ConstantExpr::getBitCast(GV,
968 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +0000969}
970
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000971/*
972 struct _objc_category {
973 char *category_name;
974 char *class_name;
975 struct _objc_method_list *instance_methods;
976 struct _objc_method_list *class_methods;
977 struct _objc_protocol_list *protocols;
978 uint32_t size; // <rdar://4585769>
979 struct _objc_property_list *instance_properties;
980 };
981 */
Daniel Dunbar7ded7f42008-08-15 22:20:32 +0000982void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Daniel Dunbar491c7b72009-01-12 21:08:18 +0000983 unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.CategoryTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000984
Daniel Dunbar86e2f402008-08-26 23:03:11 +0000985 // FIXME: This is poor design, the OCD should have a pointer to the
986 // category decl. Additionally, note that Category can be null for
987 // the @implementation w/o an @interface case. Sema should just
988 // create one for us as it does for @implementation so everyone else
989 // can live life under a clear blue sky.
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000990 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar86e2f402008-08-26 23:03:11 +0000991 const ObjCCategoryDecl *Category =
992 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Chris Lattnerd9d22dd2008-11-24 05:29:24 +0000993 std::string ExtName(Interface->getNameAsString() + "_" +
994 OCD->getNameAsString());
Daniel Dunbar86e253a2008-08-22 20:34:54 +0000995
Daniel Dunbarc45ef602008-08-26 21:51:14 +0000996 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
997 for (ObjCCategoryImplDecl::instmeth_iterator i = OCD->instmeth_begin(),
998 e = OCD->instmeth_end(); i != e; ++i) {
999 // Instance methods should always be defined.
1000 InstanceMethods.push_back(GetMethodConstant(*i));
1001 }
1002 for (ObjCCategoryImplDecl::classmeth_iterator i = OCD->classmeth_begin(),
1003 e = OCD->classmeth_end(); i != e; ++i) {
1004 // Class methods should always be defined.
1005 ClassMethods.push_back(GetMethodConstant(*i));
1006 }
1007
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001008 std::vector<llvm::Constant*> Values(7);
1009 Values[0] = GetClassName(OCD->getIdentifier());
1010 Values[1] = GetClassName(Interface->getIdentifier());
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001011 Values[2] =
1012 EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") +
1013 ExtName,
1014 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00001015 InstanceMethods);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001016 Values[3] =
1017 EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName,
1018 "__OBJC,__cat_class_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00001019 ClassMethods);
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001020 if (Category) {
1021 Values[4] =
1022 EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName,
1023 Category->protocol_begin(),
1024 Category->protocol_end());
1025 } else {
1026 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
1027 }
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001028 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00001029
1030 // If there is no category @interface then there can be no properties.
1031 if (Category) {
1032 Values[6] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_LIST_") + ExtName,
Steve Naroff93983f82009-01-11 12:47:58 +00001033 OCD, Category);
Daniel Dunbar86e2f402008-08-26 23:03:11 +00001034 } else {
1035 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
1036 }
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001037
1038 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
1039 Values);
1040
1041 llvm::GlobalVariable *GV =
1042 new llvm::GlobalVariable(ObjCTypes.CategoryTy, false,
1043 llvm::GlobalValue::InternalLinkage,
1044 Init,
1045 std::string("\01L_OBJC_CATEGORY_")+ExtName,
1046 &CGM.getModule());
1047 GV->setSection("__OBJC,__category,regular,no_dead_strip");
1048 UsedGlobals.push_back(GV);
1049 DefinedCategories.push_back(GV);
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001050}
1051
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001052// FIXME: Get from somewhere?
1053enum ClassFlags {
1054 eClassFlags_Factory = 0x00001,
1055 eClassFlags_Meta = 0x00002,
1056 // <rdr://5142207>
1057 eClassFlags_HasCXXStructors = 0x02000,
1058 eClassFlags_Hidden = 0x20000,
1059 eClassFlags_ABI2_Hidden = 0x00010,
1060 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
1061};
1062
1063// <rdr://5142207&4705298&4843145>
1064static bool IsClassHidden(const ObjCInterfaceDecl *ID) {
1065 if (const VisibilityAttr *attr = ID->getAttr<VisibilityAttr>()) {
1066 // FIXME: Support -fvisibility
1067 switch (attr->getVisibility()) {
1068 default:
1069 assert(0 && "Unknown visibility");
1070 return false;
1071 case VisibilityAttr::DefaultVisibility:
1072 case VisibilityAttr::ProtectedVisibility: // FIXME: What do we do here?
1073 return false;
1074 case VisibilityAttr::HiddenVisibility:
1075 return true;
1076 }
1077 } else {
1078 return false; // FIXME: Support -fvisibility
1079 }
1080}
1081
1082/*
1083 struct _objc_class {
1084 Class isa;
1085 Class super_class;
1086 const char *name;
1087 long version;
1088 long info;
1089 long instance_size;
1090 struct _objc_ivar_list *ivars;
1091 struct _objc_method_list *methods;
1092 struct _objc_cache *cache;
1093 struct _objc_protocol_list *protocols;
1094 // Objective-C 1.0 extensions (<rdr://4585769>)
1095 const char *ivar_layout;
1096 struct _objc_class_ext *ext;
1097 };
1098
1099 See EmitClassExtension();
1100 */
1101void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00001102 DefinedSymbols.insert(ID->getIdentifier());
1103
Chris Lattner8ec03f52008-11-24 03:54:41 +00001104 std::string ClassName = ID->getNameAsString();
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001105 // FIXME: Gross
1106 ObjCInterfaceDecl *Interface =
1107 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbardbc93372008-08-21 21:57:41 +00001108 llvm::Constant *Protocols =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00001109 EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getNameAsString(),
Daniel Dunbardbc93372008-08-21 21:57:41 +00001110 Interface->protocol_begin(),
1111 Interface->protocol_end());
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001112 const llvm::Type *InterfaceTy =
1113 CGM.getTypes().ConvertType(CGM.getContext().getObjCInterfaceType(Interface));
1114 unsigned Flags = eClassFlags_Factory;
Daniel Dunbar491c7b72009-01-12 21:08:18 +00001115 unsigned Size = CGM.getTargetData().getTypePaddedSize(InterfaceTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001116
1117 // FIXME: Set CXX-structors flag.
1118 if (IsClassHidden(ID->getClassInterface()))
1119 Flags |= eClassFlags_Hidden;
1120
Daniel Dunbarc45ef602008-08-26 21:51:14 +00001121 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1122 for (ObjCImplementationDecl::instmeth_iterator i = ID->instmeth_begin(),
1123 e = ID->instmeth_end(); i != e; ++i) {
1124 // Instance methods should always be defined.
1125 InstanceMethods.push_back(GetMethodConstant(*i));
1126 }
1127 for (ObjCImplementationDecl::classmeth_iterator i = ID->classmeth_begin(),
1128 e = ID->classmeth_end(); i != e; ++i) {
1129 // Class methods should always be defined.
1130 ClassMethods.push_back(GetMethodConstant(*i));
1131 }
1132
1133 for (ObjCImplementationDecl::propimpl_iterator i = ID->propimpl_begin(),
1134 e = ID->propimpl_end(); i != e; ++i) {
1135 ObjCPropertyImplDecl *PID = *i;
1136
1137 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
1138 ObjCPropertyDecl *PD = PID->getPropertyDecl();
1139
1140 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
1141 if (llvm::Constant *C = GetMethodConstant(MD))
1142 InstanceMethods.push_back(C);
1143 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
1144 if (llvm::Constant *C = GetMethodConstant(MD))
1145 InstanceMethods.push_back(C);
1146 }
1147 }
1148
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001149 std::vector<llvm::Constant*> Values(12);
Daniel Dunbarc45ef602008-08-26 21:51:14 +00001150 Values[ 0] = EmitMetaClass(ID, Protocols, InterfaceTy, ClassMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001151 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00001152 // Record a reference to the super class.
1153 LazySymbols.insert(Super->getIdentifier());
1154
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001155 Values[ 1] =
1156 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
1157 ObjCTypes.ClassPtrTy);
1158 } else {
1159 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
1160 }
1161 Values[ 2] = GetClassName(ID->getIdentifier());
1162 // Version is always 0.
1163 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
1164 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
1165 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
1166 Values[ 6] = EmitIvarList(ID, false, InterfaceTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001167 Values[ 7] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00001168 EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getNameAsString(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001169 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00001170 InstanceMethods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001171 // cache is always NULL.
1172 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
1173 Values[ 9] = Protocols;
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001174 // FIXME: Set ivar_layout
1175 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001176 Values[11] = EmitClassExtension(ID);
1177 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
1178 Values);
1179
1180 llvm::GlobalVariable *GV =
1181 new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1182 llvm::GlobalValue::InternalLinkage,
1183 Init,
1184 std::string("\01L_OBJC_CLASS_")+ClassName,
1185 &CGM.getModule());
1186 GV->setSection("__OBJC,__class,regular,no_dead_strip");
1187 UsedGlobals.push_back(GV);
1188 // FIXME: Why?
1189 GV->setAlignment(32);
1190 DefinedClasses.push_back(GV);
1191}
1192
1193llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
1194 llvm::Constant *Protocols,
Daniel Dunbarc45ef602008-08-26 21:51:14 +00001195 const llvm::Type *InterfaceTy,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001196 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001197 unsigned Flags = eClassFlags_Meta;
Daniel Dunbar491c7b72009-01-12 21:08:18 +00001198 unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.ClassTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001199
1200 if (IsClassHidden(ID->getClassInterface()))
1201 Flags |= eClassFlags_Hidden;
1202
1203 std::vector<llvm::Constant*> Values(12);
1204 // The isa for the metaclass is the root of the hierarchy.
1205 const ObjCInterfaceDecl *Root = ID->getClassInterface();
1206 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
1207 Root = Super;
1208 Values[ 0] =
1209 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
1210 ObjCTypes.ClassPtrTy);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001211 // The super class for the metaclass is emitted as the name of the
1212 // super class. The runtime fixes this up to point to the
1213 // *metaclass* for the super class.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001214 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
1215 Values[ 1] =
1216 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
1217 ObjCTypes.ClassPtrTy);
1218 } else {
1219 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
1220 }
1221 Values[ 2] = GetClassName(ID->getIdentifier());
1222 // Version is always 0.
1223 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
1224 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
1225 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
1226 Values[ 6] = EmitIvarList(ID, true, InterfaceTy);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001227 Values[ 7] =
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00001228 EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00001229 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbarc45ef602008-08-26 21:51:14 +00001230 Methods);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001231 // cache is always NULL.
1232 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
1233 Values[ 9] = Protocols;
1234 // ivar_layout for metaclass is always NULL.
1235 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
1236 // The class extension is always unused for metaclasses.
1237 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
1238 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
1239 Values);
1240
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001241 std::string Name("\01L_OBJC_METACLASS_");
Chris Lattner8ec03f52008-11-24 03:54:41 +00001242 Name += ID->getNameAsCString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001243
1244 // Check for a forward reference.
1245 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
1246 if (GV) {
1247 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
1248 "Forward metaclass reference has incorrect type.");
1249 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
1250 GV->setInitializer(Init);
1251 } else {
1252 GV = new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1253 llvm::GlobalValue::InternalLinkage,
1254 Init, Name,
1255 &CGM.getModule());
1256 }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001257 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
1258 UsedGlobals.push_back(GV);
1259 // FIXME: Why?
1260 GV->setAlignment(32);
1261
1262 return GV;
1263}
1264
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001265llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00001266 std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001267
1268 // FIXME: Should we look these up somewhere other than the
1269 // module. Its a bit silly since we only generate these while
1270 // processing an implementation, so exactly one pointer would work
1271 // if know when we entered/exitted an implementation block.
1272
1273 // Check for an existing forward reference.
Fariborz Jahanianb0d27942009-01-07 20:11:22 +00001274 // Previously, metaclass with internal linkage may have been defined.
1275 // pass 'true' as 2nd argument so it is returned.
1276 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true)) {
Daniel Dunbarf56f1912008-08-25 08:19:24 +00001277 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
1278 "Forward metaclass reference has incorrect type.");
1279 return GV;
1280 } else {
1281 // Generate as an external reference to keep a consistent
1282 // module. This will be patched up when we emit the metaclass.
1283 return new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1284 llvm::GlobalValue::ExternalLinkage,
1285 0,
1286 Name,
1287 &CGM.getModule());
1288 }
1289}
1290
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001291/*
1292 struct objc_class_ext {
1293 uint32_t size;
1294 const char *weak_ivar_layout;
1295 struct _objc_property_list *properties;
1296 };
1297*/
1298llvm::Constant *
1299CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
1300 uint64_t Size =
Daniel Dunbar491c7b72009-01-12 21:08:18 +00001301 CGM.getTargetData().getTypePaddedSize(ObjCTypes.ClassExtensionTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001302
1303 std::vector<llvm::Constant*> Values(3);
1304 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001305 // FIXME: Output weak_ivar_layout string.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001306 Values[1] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00001307 Values[2] = EmitPropertyList("\01L_OBJC_$_PROP_LIST_" + ID->getNameAsString(),
Steve Naroff93983f82009-01-11 12:47:58 +00001308 ID, ID->getClassInterface());
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001309
1310 // Return null if no extension bits are used.
1311 if (Values[1]->isNullValue() && Values[2]->isNullValue())
1312 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
1313
1314 llvm::Constant *Init =
1315 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
1316 llvm::GlobalVariable *GV =
1317 new llvm::GlobalVariable(ObjCTypes.ClassExtensionTy, false,
1318 llvm::GlobalValue::InternalLinkage,
1319 Init,
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00001320 "\01L_OBJC_CLASSEXT_" + ID->getNameAsString(),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001321 &CGM.getModule());
1322 // No special section, but goes in llvm.used
1323 UsedGlobals.push_back(GV);
1324
1325 return GV;
1326}
1327
Fariborz Jahanianf54b1942009-01-17 19:36:33 +00001328/// countInheritedIvars - count number of ivars in class and its super class(s)
1329///
1330static int countInheritedIvars(const ObjCInterfaceDecl *OI) {
1331 int count = 0;
1332 if (!OI)
1333 return 0;
1334 const ObjCInterfaceDecl *SuperClass = OI->getSuperClass();
1335 if (SuperClass)
1336 count += countInheritedIvars(SuperClass);
1337 for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(),
1338 E = OI->ivar_end(); I != E; ++I)
1339 ++count;
1340 return count;
1341}
1342
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001343/*
1344 struct objc_ivar {
1345 char *ivar_name;
1346 char *ivar_type;
1347 int ivar_offset;
1348 };
1349
1350 struct objc_ivar_list {
1351 int ivar_count;
1352 struct objc_ivar list[count];
1353 };
1354 */
1355llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
1356 bool ForClass,
1357 const llvm::Type *InterfaceTy) {
1358 std::vector<llvm::Constant*> Ivars, Ivar(3);
1359
1360 // When emitting the root class GCC emits ivar entries for the
1361 // actual class structure. It is not clear if we need to follow this
1362 // behavior; for now lets try and get away with not doing it. If so,
1363 // the cleanest solution would be to make up an ObjCInterfaceDecl
1364 // for the class.
1365 if (ForClass)
1366 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
1367
1368 const llvm::StructLayout *Layout =
1369 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(InterfaceTy));
Fariborz Jahanianf54b1942009-01-17 19:36:33 +00001370 ObjCInterfaceDecl *OID =
1371 const_cast<ObjCInterfaceDecl *>(ID->getClassInterface());
1372 int countSuperClassIvars = countInheritedIvars(OID->getSuperClass());
1373 const RecordDecl *RD = CGM.getContext().addRecordToClass(OID);
1374 RecordDecl::field_iterator ifield = RD->field_begin();
1375 while (countSuperClassIvars-- > 0)
1376 ++ifield;
1377 for (RecordDecl::field_iterator e = RD->field_end(); ifield != e; ++ifield) {
1378 FieldDecl *Field = *ifield;
1379 unsigned Offset = Layout->getElementOffset(CGM.getTypes().
1380 getLLVMFieldNo(Field));
1381 if (Field->getIdentifier())
1382 Ivar[0] = GetMethodVarName(Field->getIdentifier());
1383 else
1384 Ivar[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001385 std::string TypeStr;
Fariborz Jahanianf54b1942009-01-17 19:36:33 +00001386 CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001387 Ivar[1] = GetMethodVarType(TypeStr);
1388 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, Offset);
Daniel Dunbar0d504c12008-10-17 20:21:44 +00001389 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001390 }
1391
1392 // Return null for empty list.
1393 if (Ivars.empty())
1394 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
1395
1396 std::vector<llvm::Constant*> Values(2);
1397 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
1398 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
1399 Ivars.size());
1400 Values[1] = llvm::ConstantArray::get(AT, Ivars);
1401 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1402
1403 const char *Prefix = (ForClass ? "\01L_OBJC_CLASS_VARIABLES_" :
1404 "\01L_OBJC_INSTANCE_VARIABLES_");
1405 llvm::GlobalVariable *GV =
1406 new llvm::GlobalVariable(Init->getType(), false,
1407 llvm::GlobalValue::InternalLinkage,
1408 Init,
Chris Lattnerd9d22dd2008-11-24 05:29:24 +00001409 Prefix + ID->getNameAsString(),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001410 &CGM.getModule());
1411 if (ForClass) {
1412 GV->setSection("__OBJC,__cls_vars,regular,no_dead_strip");
1413 // FIXME: Why is this only here?
1414 GV->setAlignment(32);
1415 } else {
1416 GV->setSection("__OBJC,__instance_vars,regular,no_dead_strip");
1417 }
1418 UsedGlobals.push_back(GV);
1419 return llvm::ConstantExpr::getBitCast(GV,
1420 ObjCTypes.IvarListPtrTy);
1421}
1422
1423/*
1424 struct objc_method {
1425 SEL method_name;
1426 char *method_types;
1427 void *method;
1428 };
1429
1430 struct objc_method_list {
1431 struct objc_method_list *obsolete;
1432 int count;
1433 struct objc_method methods_list[count];
1434 };
1435*/
Daniel Dunbarc45ef602008-08-26 21:51:14 +00001436
1437/// GetMethodConstant - Return a struct objc_method constant for the
1438/// given method if it has been defined. The result is null if the
1439/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001440llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Daniel Dunbarc45ef602008-08-26 21:51:14 +00001441 // FIXME: Use DenseMap::lookup
1442 llvm::Function *Fn = MethodDefinitions[MD];
1443 if (!Fn)
1444 return 0;
1445
1446 std::vector<llvm::Constant*> Method(3);
1447 Method[0] =
1448 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1449 ObjCTypes.SelectorPtrTy);
1450 Method[1] = GetMethodVarType(MD);
1451 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
1452 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
1453}
1454
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001455llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
1456 const char *Section,
Daniel Dunbarae226fa2008-08-27 02:31:56 +00001457 const ConstantVector &Methods) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001458 // Return null for empty list.
1459 if (Methods.empty())
1460 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
1461
1462 std::vector<llvm::Constant*> Values(3);
1463 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
1464 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
1465 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
1466 Methods.size());
1467 Values[2] = llvm::ConstantArray::get(AT, Methods);
1468 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1469
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001470 llvm::GlobalVariable *GV =
1471 new llvm::GlobalVariable(Init->getType(), false,
1472 llvm::GlobalValue::InternalLinkage,
1473 Init,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001474 Name,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001475 &CGM.getModule());
Daniel Dunbar86e253a2008-08-22 20:34:54 +00001476 GV->setSection(Section);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00001477 UsedGlobals.push_back(GV);
1478 return llvm::ConstantExpr::getBitCast(GV,
1479 ObjCTypes.MethodListPtrTy);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00001480}
1481
Fariborz Jahanian679a5022009-01-10 21:06:09 +00001482llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD,
1483 const ObjCContainerDecl *CD) {
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00001484 std::string Name;
Fariborz Jahanian679a5022009-01-10 21:06:09 +00001485 GetNameForMethod(OMD, CD, Name);
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00001486
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00001487 const llvm::FunctionType *MethodTy =
1488 CGM.getTypes().GetFunctionType(CGFunctionInfo(OMD, CGM.getContext()));
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00001489 llvm::Function *Method =
Daniel Dunbar45c25ba2008-09-10 04:01:49 +00001490 llvm::Function::Create(MethodTy,
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00001491 llvm::GlobalValue::InternalLinkage,
1492 Name,
1493 &CGM.getModule());
Daniel Dunbarc45ef602008-08-26 21:51:14 +00001494 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00001495
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00001496 return Method;
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001497}
1498
1499llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbarf77ac862008-08-11 21:35:06 +00001500 // Abuse this interface function as a place to finalize.
1501 FinishModule();
1502
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00001503 return NULL;
1504}
1505
Daniel Dunbar49f66022008-09-24 03:38:44 +00001506llvm::Function *CGObjCMac::GetPropertyGetFunction() {
1507 return ObjCTypes.GetPropertyFn;
1508}
1509
1510llvm::Function *CGObjCMac::GetPropertySetFunction() {
1511 return ObjCTypes.SetPropertyFn;
1512}
1513
Anders Carlsson2abd89c2008-08-31 04:05:03 +00001514llvm::Function *CGObjCMac::EnumerationMutationFunction()
1515{
1516 return ObjCTypes.EnumerationMutationFn;
1517}
1518
Daniel Dunbar18ccc772008-09-28 01:03:14 +00001519/*
1520
1521Objective-C setjmp-longjmp (sjlj) Exception Handling
1522--
1523
1524The basic framework for a @try-catch-finally is as follows:
1525{
1526 objc_exception_data d;
1527 id _rethrow = null;
1528
1529 objc_exception_try_enter(&d);
1530 if (!setjmp(d.jmp_buf)) {
1531 ... try body ...
1532 } else {
1533 // exception path
1534 id _caught = objc_exception_extract(&d);
1535
1536 // enter new try scope for handlers
1537 if (!setjmp(d.jmp_buf)) {
1538 ... match exception and execute catch blocks ...
1539
1540 // fell off end, rethrow.
1541 _rethrow = _caught;
Daniel Dunbar898d5082008-09-30 01:06:03 +00001542 ... jump-through-finally to finally_rethrow ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00001543 } else {
1544 // exception in catch block
1545 _rethrow = objc_exception_extract(&d);
Daniel Dunbar898d5082008-09-30 01:06:03 +00001546 ... jump-through-finally_no_exit to finally_rethrow ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00001547 }
1548 }
Daniel Dunbar898d5082008-09-30 01:06:03 +00001549 ... jump-through-finally to finally_end ...
Daniel Dunbar18ccc772008-09-28 01:03:14 +00001550
1551finally:
1552 // match either the initial try_enter or the catch try_enter,
1553 // depending on the path followed.
1554 objc_exception_try_exit(&d);
1555finally_no_exit:
1556 ... finally block ....
Daniel Dunbar898d5082008-09-30 01:06:03 +00001557 ... dispatch to finally destination ...
1558
1559finally_rethrow:
1560 objc_exception_throw(_rethrow);
1561
1562finally_end:
Daniel Dunbar18ccc772008-09-28 01:03:14 +00001563}
1564
1565This framework differs slightly from the one gcc uses, in that gcc
Daniel Dunbar898d5082008-09-30 01:06:03 +00001566uses _rethrow to determine if objc_exception_try_exit should be called
1567and if the object should be rethrown. This breaks in the face of
1568throwing nil and introduces unnecessary branches.
Daniel Dunbar18ccc772008-09-28 01:03:14 +00001569
1570We specialize this framework for a few particular circumstances:
1571
1572 - If there are no catch blocks, then we avoid emitting the second
1573 exception handling context.
1574
1575 - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
1576 e)) we avoid emitting the code to rethrow an uncaught exception.
1577
1578 - FIXME: If there is no @finally block we can do a few more
1579 simplifications.
1580
1581Rethrows and Jumps-Through-Finally
1582--
1583
1584Support for implicit rethrows and jumping through the finally block is
1585handled by storing the current exception-handling context in
1586ObjCEHStack.
1587
Daniel Dunbar898d5082008-09-30 01:06:03 +00001588In order to implement proper @finally semantics, we support one basic
1589mechanism for jumping through the finally block to an arbitrary
1590destination. Constructs which generate exits from a @try or @catch
1591block use this mechanism to implement the proper semantics by chaining
1592jumps, as necessary.
1593
1594This mechanism works like the one used for indirect goto: we
1595arbitrarily assign an ID to each destination and store the ID for the
1596destination in a variable prior to entering the finally block. At the
1597end of the finally block we simply create a switch to the proper
1598destination.
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00001599
1600Code gen for @synchronized(expr) stmt;
1601Effectively generating code for:
1602objc_sync_enter(expr);
1603@try stmt @finally { objc_sync_exit(expr); }
Daniel Dunbar18ccc772008-09-28 01:03:14 +00001604*/
1605
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00001606void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
1607 const Stmt &S) {
1608 bool isTry = isa<ObjCAtTryStmt>(S);
Daniel Dunbar898d5082008-09-30 01:06:03 +00001609 // Create various blocks we refer to for handling @finally.
Daniel Dunbar55e87422008-11-11 02:29:29 +00001610 llvm::BasicBlock *FinallyBlock = CGF.createBasicBlock("finally");
1611 llvm::BasicBlock *FinallyNoExit = CGF.createBasicBlock("finally.noexit");
1612 llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
1613 llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
Daniel Dunbar898d5082008-09-30 01:06:03 +00001614 llvm::Value *DestCode =
1615 CGF.CreateTempAlloca(llvm::Type::Int32Ty, "finally.dst");
1616
1617 // Generate jump code. Done here so we can directly add things to
1618 // the switch instruction.
Daniel Dunbar55e87422008-11-11 02:29:29 +00001619 llvm::BasicBlock *FinallyJump = CGF.createBasicBlock("finally.jump");
Daniel Dunbar898d5082008-09-30 01:06:03 +00001620 llvm::SwitchInst *FinallySwitch =
1621 llvm::SwitchInst::Create(new llvm::LoadInst(DestCode, "", FinallyJump),
1622 FinallyEnd, 10, FinallyJump);
1623
1624 // Push an EH context entry, used for handling rethrows and jumps
1625 // through finally.
1626 CodeGenFunction::ObjCEHEntry EHEntry(FinallyBlock, FinallyNoExit,
1627 FinallySwitch, DestCode);
1628 CGF.ObjCEHStack.push_back(&EHEntry);
1629
1630 // Allocate memory for the exception data and rethrow pointer.
Anders Carlsson80f25672008-09-09 17:59:25 +00001631 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
1632 "exceptiondata.ptr");
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00001633 llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy,
1634 "_rethrow");
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00001635 if (!isTry) {
1636 // For @synchronized, call objc_sync_enter(sync.expr)
Fariborz Jahanianf2878e52008-11-21 19:21:53 +00001637 llvm::Value *Arg = CGF.EmitScalarExpr(
1638 cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
1639 Arg = CGF.Builder.CreateBitCast(Arg, ObjCTypes.ObjectPtrTy);
1640 CGF.Builder.CreateCall(ObjCTypes.SyncEnterFn, Arg);
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00001641 }
Anders Carlsson80f25672008-09-09 17:59:25 +00001642
1643 // Enter a new try block and call setjmp.
1644 CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
1645 llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0,
1646 "jmpbufarray");
1647 JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp");
1648 llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn,
1649 JmpBufPtr, "result");
Daniel Dunbar898d5082008-09-30 01:06:03 +00001650
Daniel Dunbar55e87422008-11-11 02:29:29 +00001651 llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
1652 llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
Daniel Dunbar91cd3202008-10-02 17:05:36 +00001653 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(SetJmpResult, "threw"),
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00001654 TryHandler, TryBlock);
Anders Carlsson80f25672008-09-09 17:59:25 +00001655
1656 // Emit the @try block.
1657 CGF.EmitBlock(TryBlock);
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00001658 CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
1659 : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
Daniel Dunbar898d5082008-09-30 01:06:03 +00001660 CGF.EmitJumpThroughFinally(&EHEntry, FinallyEnd);
Anders Carlsson80f25672008-09-09 17:59:25 +00001661
1662 // Emit the "exception in @try" block.
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00001663 CGF.EmitBlock(TryHandler);
Daniel Dunbar55e40722008-09-27 07:03:52 +00001664
1665 // Retrieve the exception object. We may emit multiple blocks but
1666 // nothing can cross this so the value is already in SSA form.
1667 llvm::Value *Caught = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
1668 ExceptionData,
1669 "caught");
Daniel Dunbar898d5082008-09-30 01:06:03 +00001670 EHEntry.Exception = Caught;
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00001671 if (!isTry)
1672 {
1673 CGF.Builder.CreateStore(Caught, RethrowPtr);
1674 CGF.EmitJumpThroughFinally(&EHEntry, FinallyRethrow, false);
1675 }
1676 else if (const ObjCAtCatchStmt* CatchStmt =
1677 cast<ObjCAtTryStmt>(S).getCatchStmts())
1678 {
Daniel Dunbar55e40722008-09-27 07:03:52 +00001679 // Enter a new exception try block (in case a @catch block throws
1680 // an exception).
Anders Carlsson80f25672008-09-09 17:59:25 +00001681 CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
Daniel Dunbar55e40722008-09-27 07:03:52 +00001682
Anders Carlsson80f25672008-09-09 17:59:25 +00001683 llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn,
1684 JmpBufPtr, "result");
Daniel Dunbar91cd3202008-10-02 17:05:36 +00001685 llvm::Value *Threw = CGF.Builder.CreateIsNotNull(SetJmpResult, "threw");
Anders Carlsson80f25672008-09-09 17:59:25 +00001686
Daniel Dunbar55e87422008-11-11 02:29:29 +00001687 llvm::BasicBlock *CatchBlock = CGF.createBasicBlock("catch");
1688 llvm::BasicBlock *CatchHandler = CGF.createBasicBlock("catch.handler");
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00001689 CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
Anders Carlsson80f25672008-09-09 17:59:25 +00001690
1691 CGF.EmitBlock(CatchBlock);
1692
Daniel Dunbar55e40722008-09-27 07:03:52 +00001693 // Handle catch list. As a special case we check if everything is
1694 // matched and avoid generating code for falling off the end if
1695 // so.
1696 bool AllMatched = false;
Anders Carlsson80f25672008-09-09 17:59:25 +00001697 for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
Daniel Dunbar55e87422008-11-11 02:29:29 +00001698 llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch");
Anders Carlsson80f25672008-09-09 17:59:25 +00001699
Anders Carlssondde0a942008-09-11 09:15:33 +00001700 const DeclStmt *CatchParam =
1701 cast_or_null<DeclStmt>(CatchStmt->getCatchParamStmt());
Daniel Dunbar129271a2008-09-27 07:36:24 +00001702 const VarDecl *VD = 0;
1703 const PointerType *PT = 0;
1704
Anders Carlsson80f25672008-09-09 17:59:25 +00001705 // catch(...) always matches.
Daniel Dunbar55e40722008-09-27 07:03:52 +00001706 if (!CatchParam) {
1707 AllMatched = true;
1708 } else {
Ted Kremenekde3b8fb2008-10-06 20:58:56 +00001709 VD = cast<VarDecl>(CatchParam->getSolitaryDecl());
Daniel Dunbar129271a2008-09-27 07:36:24 +00001710 PT = VD->getType()->getAsPointerType();
Anders Carlsson80f25672008-09-09 17:59:25 +00001711
Daniel Dunbar97f61d12008-09-27 22:21:14 +00001712 // catch(id e) always matches.
1713 // FIXME: For the time being we also match id<X>; this should
1714 // be rejected by Sema instead.
1715 if ((PT && CGF.getContext().isObjCIdType(PT->getPointeeType())) ||
1716 VD->getType()->isObjCQualifiedIdType())
Daniel Dunbar55e40722008-09-27 07:03:52 +00001717 AllMatched = true;
Anders Carlsson80f25672008-09-09 17:59:25 +00001718 }
1719
Daniel Dunbar55e40722008-09-27 07:03:52 +00001720 if (AllMatched) {
Anders Carlssondde0a942008-09-11 09:15:33 +00001721 if (CatchParam) {
1722 CGF.EmitStmt(CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00001723 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar129271a2008-09-27 07:36:24 +00001724 CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(VD));
Anders Carlssondde0a942008-09-11 09:15:33 +00001725 }
Anders Carlsson1452f552008-09-11 08:21:54 +00001726
Anders Carlssondde0a942008-09-11 09:15:33 +00001727 CGF.EmitStmt(CatchStmt->getCatchBody());
Daniel Dunbar898d5082008-09-30 01:06:03 +00001728 CGF.EmitJumpThroughFinally(&EHEntry, FinallyEnd);
Anders Carlsson80f25672008-09-09 17:59:25 +00001729 break;
1730 }
1731
Daniel Dunbar129271a2008-09-27 07:36:24 +00001732 assert(PT && "Unexpected non-pointer type in @catch");
1733 QualType T = PT->getPointeeType();
Anders Carlsson4b7ff6e2008-09-11 06:35:14 +00001734 const ObjCInterfaceType *ObjCType = T->getAsObjCInterfaceType();
Anders Carlsson80f25672008-09-09 17:59:25 +00001735 assert(ObjCType && "Catch parameter must have Objective-C type!");
1736
1737 // Check if the @catch block matches the exception object.
1738 llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl());
1739
Anders Carlsson80f25672008-09-09 17:59:25 +00001740 llvm::Value *Match = CGF.Builder.CreateCall2(ObjCTypes.ExceptionMatchFn,
1741 Class, Caught, "match");
Anders Carlsson80f25672008-09-09 17:59:25 +00001742
Daniel Dunbar55e87422008-11-11 02:29:29 +00001743 llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("matched");
Anders Carlsson80f25672008-09-09 17:59:25 +00001744
Daniel Dunbar91cd3202008-10-02 17:05:36 +00001745 CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00001746 MatchedBlock, NextCatchBlock);
Anders Carlsson80f25672008-09-09 17:59:25 +00001747
1748 // Emit the @catch block.
1749 CGF.EmitBlock(MatchedBlock);
Daniel Dunbar18ccc772008-09-28 01:03:14 +00001750 CGF.EmitStmt(CatchParam);
Daniel Dunbara448fb22008-11-11 23:11:34 +00001751 assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
Daniel Dunbar18ccc772008-09-28 01:03:14 +00001752
1753 llvm::Value *Tmp =
1754 CGF.Builder.CreateBitCast(Caught, CGF.ConvertType(VD->getType()),
1755 "tmp");
1756 CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(VD));
Anders Carlssondde0a942008-09-11 09:15:33 +00001757
1758 CGF.EmitStmt(CatchStmt->getCatchBody());
Daniel Dunbar898d5082008-09-30 01:06:03 +00001759 CGF.EmitJumpThroughFinally(&EHEntry, FinallyEnd);
Anders Carlsson80f25672008-09-09 17:59:25 +00001760
1761 CGF.EmitBlock(NextCatchBlock);
1762 }
1763
Daniel Dunbar55e40722008-09-27 07:03:52 +00001764 if (!AllMatched) {
1765 // None of the handlers caught the exception, so store it to be
1766 // rethrown at the end of the @finally block.
1767 CGF.Builder.CreateStore(Caught, RethrowPtr);
Daniel Dunbar898d5082008-09-30 01:06:03 +00001768 CGF.EmitJumpThroughFinally(&EHEntry, FinallyRethrow);
Daniel Dunbar55e40722008-09-27 07:03:52 +00001769 }
1770
1771 // Emit the exception handler for the @catch blocks.
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00001772 CGF.EmitBlock(CatchHandler);
Daniel Dunbar55e40722008-09-27 07:03:52 +00001773 CGF.Builder.CreateStore(CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
1774 ExceptionData),
1775 RethrowPtr);
Daniel Dunbar898d5082008-09-30 01:06:03 +00001776 CGF.EmitJumpThroughFinally(&EHEntry, FinallyRethrow, false);
Daniel Dunbar55e40722008-09-27 07:03:52 +00001777 } else {
Anders Carlsson80f25672008-09-09 17:59:25 +00001778 CGF.Builder.CreateStore(Caught, RethrowPtr);
Daniel Dunbar898d5082008-09-30 01:06:03 +00001779 CGF.EmitJumpThroughFinally(&EHEntry, FinallyRethrow, false);
Anders Carlsson80f25672008-09-09 17:59:25 +00001780 }
1781
Daniel Dunbar898d5082008-09-30 01:06:03 +00001782 // Pop the exception-handling stack entry. It is important to do
1783 // this now, because the code in the @finally block is not in this
1784 // context.
1785 CGF.ObjCEHStack.pop_back();
1786
Anders Carlsson80f25672008-09-09 17:59:25 +00001787 // Emit the @finally block.
1788 CGF.EmitBlock(FinallyBlock);
Anders Carlsson80f25672008-09-09 17:59:25 +00001789 CGF.Builder.CreateCall(ObjCTypes.ExceptionTryExitFn, ExceptionData);
Daniel Dunbar129271a2008-09-27 07:36:24 +00001790
1791 CGF.EmitBlock(FinallyNoExit);
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00001792 if (isTry) {
1793 if (const ObjCAtFinallyStmt* FinallyStmt =
1794 cast<ObjCAtTryStmt>(S).getFinallyStmt())
1795 CGF.EmitStmt(FinallyStmt->getFinallyBody());
1796 }
Fariborz Jahanianf2878e52008-11-21 19:21:53 +00001797 else {
Fariborz Jahanianbd71be42008-11-21 00:49:24 +00001798 // For @synchronized objc_sync_exit(expr); As finally's sole statement.
Fariborz Jahanianf2878e52008-11-21 19:21:53 +00001799 // For @synchronized, call objc_sync_enter(sync.expr)
1800 llvm::Value *Arg = CGF.EmitScalarExpr(
1801 cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
1802 Arg = CGF.Builder.CreateBitCast(Arg, ObjCTypes.ObjectPtrTy);
1803 CGF.Builder.CreateCall(ObjCTypes.SyncExitFn, Arg);
1804 }
Anders Carlsson80f25672008-09-09 17:59:25 +00001805
Daniel Dunbar898d5082008-09-30 01:06:03 +00001806 CGF.EmitBlock(FinallyJump);
1807
1808 CGF.EmitBlock(FinallyRethrow);
1809 CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn,
1810 CGF.Builder.CreateLoad(RethrowPtr));
Daniel Dunbare4b5ee02008-09-27 23:30:04 +00001811 CGF.Builder.CreateUnreachable();
Daniel Dunbar898d5082008-09-30 01:06:03 +00001812
1813 CGF.EmitBlock(FinallyEnd);
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00001814}
1815
1816void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
Daniel Dunbar898d5082008-09-30 01:06:03 +00001817 const ObjCAtThrowStmt &S) {
Anders Carlsson2b1e3112008-09-09 16:16:55 +00001818 llvm::Value *ExceptionAsObject;
1819
1820 if (const Expr *ThrowExpr = S.getThrowExpr()) {
1821 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
1822 ExceptionAsObject =
1823 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
1824 } else {
Daniel Dunbar898d5082008-09-30 01:06:03 +00001825 assert((!CGF.ObjCEHStack.empty() && CGF.ObjCEHStack.back()->Exception) &&
Daniel Dunbar18ccc772008-09-28 01:03:14 +00001826 "Unexpected rethrow outside @catch block.");
Daniel Dunbar898d5082008-09-30 01:06:03 +00001827 ExceptionAsObject = CGF.ObjCEHStack.back()->Exception;
Anders Carlsson2b1e3112008-09-09 16:16:55 +00001828 }
1829
1830 CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn, ExceptionAsObject);
Anders Carlsson80f25672008-09-09 17:59:25 +00001831 CGF.Builder.CreateUnreachable();
Daniel Dunbara448fb22008-11-11 23:11:34 +00001832
1833 // Clear the insertion point to indicate we are in unreachable code.
1834 CGF.Builder.ClearInsertionPoint();
Anders Carlsson64d5d6c2008-09-09 10:04:29 +00001835}
1836
Daniel Dunbar898d5082008-09-30 01:06:03 +00001837void CodeGenFunction::EmitJumpThroughFinally(ObjCEHEntry *E,
1838 llvm::BasicBlock *Dst,
1839 bool ExecuteTryExit) {
Daniel Dunbara448fb22008-11-11 23:11:34 +00001840 if (!HaveInsertPoint())
Daniel Dunbar898d5082008-09-30 01:06:03 +00001841 return;
1842
1843 // Find the destination code for this block. We always use 0 for the
1844 // fallthrough block (default destination).
1845 llvm::SwitchInst *SI = E->FinallySwitch;
1846 llvm::ConstantInt *ID;
1847 if (Dst == SI->getDefaultDest()) {
1848 ID = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
1849 } else {
1850 ID = SI->findCaseDest(Dst);
1851 if (!ID) {
1852 // No code found, get a new unique one by just using the number
1853 // of switch successors.
1854 ID = llvm::ConstantInt::get(llvm::Type::Int32Ty, SI->getNumSuccessors());
1855 SI->addCase(ID, Dst);
1856 }
1857 }
1858
1859 // Set the destination code and branch.
1860 Builder.CreateStore(ID, E->DestCode);
Daniel Dunbara448fb22008-11-11 23:11:34 +00001861 EmitBranch(ExecuteTryExit ? E->FinallyBlock : E->FinallyNoExit);
Daniel Dunbar898d5082008-09-30 01:06:03 +00001862}
1863
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001864/// EmitObjCWeakRead - Code gen for loading value of a __weak
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00001865/// object: objc_read_weak (id *src)
1866///
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001867llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00001868 llvm::Value *AddrWeakObj)
1869{
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00001870 AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00001871 llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.GcReadWeakFn,
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001872 AddrWeakObj, "weakread");
Fariborz Jahanian6dc23172008-11-18 21:45:40 +00001873 return read_weak;
1874}
1875
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001876/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
1877/// objc_assign_weak (id src, id *dst)
1878///
1879void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
1880 llvm::Value *src, llvm::Value *dst)
1881{
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00001882 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
1883 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian3e283e32008-11-18 22:37:34 +00001884 CGF.Builder.CreateCall2(ObjCTypes.GcAssignWeakFn,
1885 src, dst, "weakassign");
1886 return;
1887}
1888
Fariborz Jahanian58626502008-11-19 00:59:10 +00001889/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
1890/// objc_assign_global (id src, id *dst)
1891///
1892void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
1893 llvm::Value *src, llvm::Value *dst)
1894{
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00001895 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
1896 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001897 CGF.Builder.CreateCall2(ObjCTypes.GcAssignGlobalFn,
1898 src, dst, "globalassign");
1899 return;
1900}
1901
Fariborz Jahanian7eda8362008-11-20 19:23:36 +00001902/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
1903/// objc_assign_ivar (id src, id *dst)
1904///
1905void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
1906 llvm::Value *src, llvm::Value *dst)
1907{
1908 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
1909 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
1910 CGF.Builder.CreateCall2(ObjCTypes.GcAssignIvarFn,
1911 src, dst, "assignivar");
1912 return;
1913}
1914
Fariborz Jahanian58626502008-11-19 00:59:10 +00001915/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
1916/// objc_assign_strongCast (id src, id *dst)
1917///
1918void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
1919 llvm::Value *src, llvm::Value *dst)
1920{
Fariborz Jahaniandbd32c22008-11-19 17:34:06 +00001921 src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
1922 dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
Fariborz Jahanian58626502008-11-19 00:59:10 +00001923 CGF.Builder.CreateCall2(ObjCTypes.GcAssignStrongCastFn,
1924 src, dst, "weakassign");
1925 return;
1926}
1927
Daniel Dunbarf77ac862008-08-11 21:35:06 +00001928/* *** Private Interface *** */
1929
1930/// EmitImageInfo - Emit the image info marker used to encode some module
1931/// level information.
1932///
1933/// See: <rdr://4810609&4810587&4810587>
1934/// struct IMAGE_INFO {
1935/// unsigned version;
1936/// unsigned flags;
1937/// };
1938enum ImageInfoFlags {
1939 eImageInfo_FixAndContinue = (1 << 0), // FIXME: Not sure what this implies
1940 eImageInfo_GarbageCollected = (1 << 1),
1941 eImageInfo_GCOnly = (1 << 2)
1942};
1943
1944void CGObjCMac::EmitImageInfo() {
1945 unsigned version = 0; // Version is unused?
1946 unsigned flags = 0;
1947
1948 // FIXME: Fix and continue?
1949 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
1950 flags |= eImageInfo_GarbageCollected;
1951 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
1952 flags |= eImageInfo_GCOnly;
1953
Daniel Dunbarf77ac862008-08-11 21:35:06 +00001954 // Emitted as int[2];
1955 llvm::Constant *values[2] = {
1956 llvm::ConstantInt::get(llvm::Type::Int32Ty, version),
1957 llvm::ConstantInt::get(llvm::Type::Int32Ty, flags)
1958 };
1959 llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::Int32Ty, 2);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001960 llvm::GlobalVariable *GV =
Daniel Dunbarf77ac862008-08-11 21:35:06 +00001961 new llvm::GlobalVariable(AT, true,
1962 llvm::GlobalValue::InternalLinkage,
1963 llvm::ConstantArray::get(AT, values, 2),
1964 "\01L_OBJC_IMAGE_INFO",
1965 &CGM.getModule());
1966
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00001967 if (ObjCABI == 1) {
1968 GV->setSection("__OBJC, __image_info,regular");
1969 } else {
1970 GV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip");
1971 }
Daniel Dunbarf77ac862008-08-11 21:35:06 +00001972
1973 UsedGlobals.push_back(GV);
1974}
1975
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001976
1977// struct objc_module {
1978// unsigned long version;
1979// unsigned long size;
1980// const char *name;
1981// Symtab symtab;
1982// };
1983
1984// FIXME: Get from somewhere
1985static const int ModuleVersion = 7;
1986
1987void CGObjCMac::EmitModuleInfo() {
Daniel Dunbar491c7b72009-01-12 21:08:18 +00001988 uint64_t Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.ModuleTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001989
1990 std::vector<llvm::Constant*> Values(4);
1991 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
1992 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbar7ded7f42008-08-15 22:20:32 +00001993 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00001994 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00001995 Values[3] = EmitModuleSymbols();
1996
1997 llvm::GlobalVariable *GV =
1998 new llvm::GlobalVariable(ObjCTypes.ModuleTy, false,
1999 llvm::GlobalValue::InternalLinkage,
2000 llvm::ConstantStruct::get(ObjCTypes.ModuleTy,
2001 Values),
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002002 "\01L_OBJC_MODULES",
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002003 &CGM.getModule());
2004 GV->setSection("__OBJC,__module_info,regular,no_dead_strip");
2005 UsedGlobals.push_back(GV);
2006}
2007
2008llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002009 unsigned NumClasses = DefinedClasses.size();
2010 unsigned NumCategories = DefinedCategories.size();
2011
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002012 // Return null if no symbols were defined.
2013 if (!NumClasses && !NumCategories)
2014 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
2015
2016 std::vector<llvm::Constant*> Values(5);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002017 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
2018 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
2019 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
2020 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
2021
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002022 // The runtime expects exactly the list of defined classes followed
2023 // by the list of defined categories, in a single array.
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002024 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002025 for (unsigned i=0; i<NumClasses; i++)
2026 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
2027 ObjCTypes.Int8PtrTy);
2028 for (unsigned i=0; i<NumCategories; i++)
2029 Symbols[NumClasses + i] =
2030 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
2031 ObjCTypes.Int8PtrTy);
2032
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002033 Values[4] =
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002034 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002035 NumClasses + NumCategories),
2036 Symbols);
2037
2038 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
2039
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002040 llvm::GlobalVariable *GV =
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002041 new llvm::GlobalVariable(Init->getType(), false,
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002042 llvm::GlobalValue::InternalLinkage,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002043 Init,
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002044 "\01L_OBJC_SYMBOLS",
2045 &CGM.getModule());
2046 GV->setSection("__OBJC,__symbols,regular,no_dead_strip");
2047 UsedGlobals.push_back(GV);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002048 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
2049}
2050
Daniel Dunbar45d196b2008-11-01 01:53:16 +00002051llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002052 const ObjCInterfaceDecl *ID) {
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002053 LazySymbols.insert(ID->getIdentifier());
2054
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002055 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
2056
2057 if (!Entry) {
2058 llvm::Constant *Casted =
2059 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
2060 ObjCTypes.ClassPtrTy);
2061 Entry =
2062 new llvm::GlobalVariable(ObjCTypes.ClassPtrTy, false,
2063 llvm::GlobalValue::InternalLinkage,
2064 Casted, "\01L_OBJC_CLASS_REFERENCES_",
2065 &CGM.getModule());
2066 Entry->setSection("__OBJC,__cls_refs,literal_pointers,no_dead_strip");
2067 UsedGlobals.push_back(Entry);
2068 }
2069
2070 return Builder.CreateLoad(Entry, false, "tmp");
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002071}
2072
Daniel Dunbar45d196b2008-11-01 01:53:16 +00002073llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00002074 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
2075
2076 if (!Entry) {
2077 llvm::Constant *Casted =
2078 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
2079 ObjCTypes.SelectorPtrTy);
2080 Entry =
2081 new llvm::GlobalVariable(ObjCTypes.SelectorPtrTy, false,
2082 llvm::GlobalValue::InternalLinkage,
2083 Casted, "\01L_OBJC_SELECTOR_REFERENCES_",
2084 &CGM.getModule());
2085 Entry->setSection("__OBJC,__message_refs,literal_pointers,no_dead_strip");
2086 UsedGlobals.push_back(Entry);
2087 }
2088
2089 return Builder.CreateLoad(Entry, false, "tmp");
2090}
2091
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002092llvm::Constant *CGObjCMac::GetClassName(IdentifierInfo *Ident) {
2093 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002094
2095 if (!Entry) {
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002096 llvm::Constant *C = llvm::ConstantArray::get(Ident->getName());
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002097 Entry =
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002098 new llvm::GlobalVariable(C->getType(), false,
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002099 llvm::GlobalValue::InternalLinkage,
2100 C, "\01L_OBJC_CLASS_NAME_",
2101 &CGM.getModule());
2102 Entry->setSection("__TEXT,__cstring,cstring_literals");
2103 UsedGlobals.push_back(Entry);
2104 }
2105
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002106 return getConstantGEP(Entry, 0, 0);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002107}
2108
Fariborz Jahanian56210f72009-01-21 23:34:32 +00002109llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
Daniel Dunbar259d93d2008-08-12 03:39:23 +00002110 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
2111
2112 if (!Entry) {
Chris Lattner077bf5e2008-11-24 03:33:13 +00002113 // FIXME: Avoid std::string copying.
2114 llvm::Constant *C = llvm::ConstantArray::get(Sel.getAsString());
Daniel Dunbar259d93d2008-08-12 03:39:23 +00002115 Entry =
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002116 new llvm::GlobalVariable(C->getType(), false,
Daniel Dunbar259d93d2008-08-12 03:39:23 +00002117 llvm::GlobalValue::InternalLinkage,
2118 C, "\01L_OBJC_METH_VAR_NAME_",
2119 &CGM.getModule());
2120 Entry->setSection("__TEXT,__cstring,cstring_literals");
2121 UsedGlobals.push_back(Entry);
2122 }
2123
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002124 return getConstantGEP(Entry, 0, 0);
2125}
2126
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002127// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00002128llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002129 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
2130}
2131
2132// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00002133llvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002134 return GetMethodVarName(&CGM.getContext().Idents.get(Name));
2135}
2136
Fariborz Jahanian56210f72009-01-21 23:34:32 +00002137llvm::Constant *CGObjCCommonMac::GetMethodVarType(const std::string &Name) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002138 llvm::GlobalVariable *&Entry = MethodVarTypes[Name];
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002139
2140 if (!Entry) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002141 llvm::Constant *C = llvm::ConstantArray::get(Name);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002142 Entry =
2143 new llvm::GlobalVariable(C->getType(), false,
2144 llvm::GlobalValue::InternalLinkage,
2145 C, "\01L_OBJC_METH_VAR_TYPE_",
2146 &CGM.getModule());
2147 Entry->setSection("__TEXT,__cstring,cstring_literals");
2148 UsedGlobals.push_back(Entry);
2149 }
2150
2151 return getConstantGEP(Entry, 0, 0);
Daniel Dunbar259d93d2008-08-12 03:39:23 +00002152}
2153
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002154// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00002155llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002156 std::string TypeStr;
Daniel Dunbarc45ef602008-08-26 21:51:14 +00002157 CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
2158 TypeStr);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002159 return GetMethodVarType(TypeStr);
2160}
2161
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002162// FIXME: Merge into a single cstring creation function.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00002163llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002164 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
2165
2166 if (!Entry) {
2167 llvm::Constant *C = llvm::ConstantArray::get(Ident->getName());
2168 Entry =
2169 new llvm::GlobalVariable(C->getType(), false,
2170 llvm::GlobalValue::InternalLinkage,
2171 C, "\01L_OBJC_PROP_NAME_ATTR_",
2172 &CGM.getModule());
2173 Entry->setSection("__TEXT,__cstring,cstring_literals");
2174 UsedGlobals.push_back(Entry);
2175 }
2176
2177 return getConstantGEP(Entry, 0, 0);
2178}
2179
2180// FIXME: Merge into a single cstring creation function.
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00002181// FIXME: This Decl should be more precise.
Fariborz Jahanian56210f72009-01-21 23:34:32 +00002182llvm::Constant *CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00002183 const Decl *Container) {
2184 std::string TypeStr;
2185 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbarc8ef5512008-08-23 00:19:03 +00002186 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
2187}
2188
Fariborz Jahanian56210f72009-01-21 23:34:32 +00002189void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
2190 const ObjCContainerDecl *CD,
2191 std::string &NameOut) {
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002192 // FIXME: Find the mangling GCC uses.
Douglas Gregorf8d49f62009-01-09 17:18:27 +00002193 NameOut = (D->isInstanceMethod() ? "-" : "+");
Chris Lattner077bf5e2008-11-24 03:33:13 +00002194 NameOut += '[';
Fariborz Jahanian679a5022009-01-10 21:06:09 +00002195 assert (CD && "Missing container decl in GetNameForMethod");
2196 NameOut += CD->getNameAsString();
Chris Lattner077bf5e2008-11-24 03:33:13 +00002197 NameOut += ' ';
2198 NameOut += D->getSelector().getAsString();
2199 NameOut += ']';
Daniel Dunbarb7ec2462008-08-16 03:19:19 +00002200}
2201
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002202void CGObjCMac::FinishModule() {
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002203 EmitModuleInfo();
2204
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002205 // Emit the dummy bodies for any protocols which were referenced but
2206 // never defined.
2207 for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
2208 i = Protocols.begin(), e = Protocols.end(); i != e; ++i) {
2209 if (i->second->hasInitializer())
2210 continue;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002211
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002212 std::vector<llvm::Constant*> Values(5);
2213 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
2214 Values[1] = GetClassName(i->first);
2215 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
2216 Values[3] = Values[4] =
2217 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
2218 i->second->setLinkage(llvm::GlobalValue::InternalLinkage);
2219 i->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
2220 Values));
2221 }
2222
2223 std::vector<llvm::Constant*> Used;
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002224 for (std::vector<llvm::GlobalVariable*>::iterator i = UsedGlobals.begin(),
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002225 e = UsedGlobals.end(); i != e; ++i) {
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002226 Used.push_back(llvm::ConstantExpr::getBitCast(*i, ObjCTypes.Int8PtrTy));
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002227 }
2228
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002229 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Used.size());
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002230 llvm::GlobalValue *GV =
2231 new llvm::GlobalVariable(AT, false,
2232 llvm::GlobalValue::AppendingLinkage,
2233 llvm::ConstantArray::get(AT, Used),
2234 "llvm.used",
2235 &CGM.getModule());
2236
2237 GV->setSection("llvm.metadata");
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002238
2239 // Add assembler directives to add lazy undefined symbol references
2240 // for classes which are referenced but not defined. This is
2241 // important for correct linker interaction.
2242
2243 // FIXME: Uh, this isn't particularly portable.
2244 std::stringstream s;
Anders Carlsson565c99f2008-12-10 02:21:04 +00002245
2246 if (!CGM.getModule().getModuleInlineAsm().empty())
2247 s << "\n";
2248
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002249 for (std::set<IdentifierInfo*>::iterator i = LazySymbols.begin(),
2250 e = LazySymbols.end(); i != e; ++i) {
2251 s << "\t.lazy_reference .objc_class_name_" << (*i)->getName() << "\n";
2252 }
2253 for (std::set<IdentifierInfo*>::iterator i = DefinedSymbols.begin(),
2254 e = DefinedSymbols.end(); i != e; ++i) {
Daniel Dunbarc56f34a2008-08-28 04:38:10 +00002255 s << "\t.objc_class_name_" << (*i)->getName() << "=0\n"
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002256 << "\t.globl .objc_class_name_" << (*i)->getName() << "\n";
2257 }
Anders Carlsson565c99f2008-12-10 02:21:04 +00002258
Daniel Dunbar242d4dc2008-08-25 06:02:07 +00002259 CGM.getModule().appendModuleInlineAsm(s.str());
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002260}
2261
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00002262CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002263 : CGObjCCommonMac(cgm),
2264 ObjCTypes(cgm)
2265{
2266 ObjCABI = 2;
2267}
2268
Daniel Dunbarf77ac862008-08-11 21:35:06 +00002269/* *** */
2270
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002271ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
2272: CGM(cgm)
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00002273{
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002274 CodeGen::CodeGenTypes &Types = CGM.getTypes();
2275 ASTContext &Ctx = CGM.getContext();
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002276
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002277 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002278 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002279 LongTy = Types.ConvertType(Ctx.LongTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002280 Int8PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
2281
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002282 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
Fariborz Jahanian6d657c42008-11-18 20:18:11 +00002283 PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002284 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002285
2286 // FIXME: It would be nice to unify this with the opaque type, so
2287 // that the IR comes out a bit cleaner.
2288 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
2289 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002290
2291 // I'm not sure I like this. The implicit coordination is a bit
2292 // gross. We should solve this in a reasonable fashion because this
2293 // is a pretty common task (match some runtime data structure with
2294 // an LLVM data structure).
2295
2296 // FIXME: This is leaked.
2297 // FIXME: Merge with rewriter code?
2298
2299 // struct _objc_super {
2300 // id self;
2301 // Class cls;
2302 // }
2303 RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
2304 SourceLocation(),
2305 &Ctx.Idents.get("_objc_super"));
2306 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
2307 Ctx.getObjCIdType(), 0, false));
2308 RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
2309 Ctx.getObjCClassType(), 0, false));
2310 RD->completeDefinition(Ctx);
2311
2312 SuperCTy = Ctx.getTagDeclType(RD);
2313 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
2314
2315 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Fariborz Jahaniandb286862009-01-22 00:37:21 +00002316 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
2317
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00002318 // struct _prop_t {
2319 // char *name;
2320 // char *attributes;
2321 // }
2322 PropertyTy = llvm::StructType::get(Int8PtrTy,
2323 Int8PtrTy,
2324 NULL);
2325 CGM.getModule().addTypeName("struct._prop_t",
2326 PropertyTy);
2327
2328 // struct _prop_list_t {
2329 // uint32_t entsize; // sizeof(struct _objc_property)
2330 // uint32_t count_of_properties;
2331 // struct _objc_property prop_list[count_of_properties];
2332 // }
2333 PropertyListTy = llvm::StructType::get(IntTy,
2334 IntTy,
2335 llvm::ArrayType::get(PropertyTy, 0),
2336 NULL);
2337 CGM.getModule().addTypeName("struct._prop_list_t",
2338 PropertyListTy);
2339 // struct _prop_list_t *
2340 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
2341
2342 // struct _objc_method {
2343 // SEL _cmd;
2344 // char *method_type;
2345 // char *_imp;
2346 // }
2347 MethodTy = llvm::StructType::get(SelectorPtrTy,
2348 Int8PtrTy,
2349 Int8PtrTy,
2350 NULL);
2351 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
2352
Fariborz Jahaniandb286862009-01-22 00:37:21 +00002353 // Property manipulation functions.
2354
2355 // id objc_getProperty (id, SEL, ptrdiff_t, bool)
2356 std::vector<const llvm::Type*> Params;
2357 Params.push_back(ObjectPtrTy);
2358 Params.push_back(SelectorPtrTy);
2359 Params.push_back(LongTy);
2360 Params.push_back(Types.ConvertTypeForMem(Ctx.BoolTy));
2361 GetPropertyFn =
2362 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
2363 Params,
2364 false),
2365 "objc_getProperty");
2366
2367 // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
2368 Params.clear();
2369 Params.push_back(ObjectPtrTy);
2370 Params.push_back(SelectorPtrTy);
2371 Params.push_back(LongTy);
2372 Params.push_back(ObjectPtrTy);
2373 Params.push_back(Types.ConvertTypeForMem(Ctx.BoolTy));
2374 Params.push_back(Types.ConvertTypeForMem(Ctx.BoolTy));
2375 SetPropertyFn =
2376 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
2377 Params,
2378 false),
2379 "objc_setProperty");
2380 // Enumeration mutation.
2381
2382 Params.clear();
2383 Params.push_back(ObjectPtrTy);
2384 EnumerationMutationFn =
2385 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
2386 Params,
2387 false),
2388 "objc_enumerationMutation");
2389
2390 // gc's API
2391 // id objc_read_weak (id *)
2392 Params.clear();
2393 Params.push_back(PtrObjectPtrTy);
2394 GcReadWeakFn =
2395 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
2396 Params,
2397 false),
2398 "objc_read_weak");
2399 // id objc_assign_weak (id, id *)
2400 Params.clear();
2401 Params.push_back(ObjectPtrTy);
2402 Params.push_back(PtrObjectPtrTy);
2403 GcAssignWeakFn =
2404 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
2405 Params,
2406 false),
2407 "objc_assign_weak");
2408 GcAssignGlobalFn =
2409 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
2410 Params,
2411 false),
2412 "objc_assign_global");
2413 GcAssignIvarFn =
2414 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
2415 Params,
2416 false),
2417 "objc_assign_ivar");
2418 GcAssignStrongCastFn =
2419 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
2420 Params,
2421 false),
2422 "objc_assign_strongCast");
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002423}
Daniel Dunbar4e2d7d02008-08-12 06:48:42 +00002424
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002425ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
2426 : ObjCCommonTypesHelper(cgm)
2427{
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002428 // struct _objc_method_description {
2429 // SEL name;
2430 // char *types;
2431 // }
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002432 MethodDescriptionTy =
2433 llvm::StructType::get(SelectorPtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002434 Int8PtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002435 NULL);
2436 CGM.getModule().addTypeName("struct._objc_method_description",
2437 MethodDescriptionTy);
2438
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002439 // struct _objc_method_description_list {
2440 // int count;
2441 // struct _objc_method_description[1];
2442 // }
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002443 MethodDescriptionListTy =
2444 llvm::StructType::get(IntTy,
2445 llvm::ArrayType::get(MethodDescriptionTy, 0),
2446 NULL);
2447 CGM.getModule().addTypeName("struct._objc_method_description_list",
2448 MethodDescriptionListTy);
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002449
2450 // struct _objc_method_description_list *
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002451 MethodDescriptionListPtrTy =
2452 llvm::PointerType::getUnqual(MethodDescriptionListTy);
2453
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002454 // Protocol description structures
2455
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002456 // struct _objc_protocol_extension {
2457 // uint32_t size; // sizeof(struct _objc_protocol_extension)
2458 // struct _objc_method_description_list *optional_instance_methods;
2459 // struct _objc_method_description_list *optional_class_methods;
2460 // struct _objc_property_list *instance_properties;
2461 // }
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002462 ProtocolExtensionTy =
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002463 llvm::StructType::get(IntTy,
2464 MethodDescriptionListPtrTy,
2465 MethodDescriptionListPtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002466 PropertyListPtrTy,
2467 NULL);
2468 CGM.getModule().addTypeName("struct._objc_protocol_extension",
2469 ProtocolExtensionTy);
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002470
2471 // struct _objc_protocol_extension *
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002472 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
2473
Daniel Dunbar0c0e7a62008-10-29 22:36:39 +00002474 // Handle recursive construction of Protocol and ProtocolList types
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002475
2476 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get();
2477 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get();
2478
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002479 const llvm::Type *T =
2480 llvm::StructType::get(llvm::PointerType::getUnqual(ProtocolListTyHolder),
2481 LongTy,
2482 llvm::ArrayType::get(ProtocolTyHolder, 0),
2483 NULL);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002484 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
2485
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002486 // struct _objc_protocol {
2487 // struct _objc_protocol_extension *isa;
2488 // char *protocol_name;
2489 // struct _objc_protocol **_objc_protocol_list;
2490 // struct _objc_method_description_list *instance_methods;
2491 // struct _objc_method_description_list *class_methods;
2492 // }
2493 T = llvm::StructType::get(ProtocolExtensionPtrTy,
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002494 Int8PtrTy,
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002495 llvm::PointerType::getUnqual(ProtocolListTyHolder),
2496 MethodDescriptionListPtrTy,
2497 MethodDescriptionListPtrTy,
2498 NULL);
2499 cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
2500
2501 ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
2502 CGM.getModule().addTypeName("struct._objc_protocol_list",
2503 ProtocolListTy);
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002504 // struct _objc_protocol_list *
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002505 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
2506
2507 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002508 CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002509 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002510
2511 // Class description structures
2512
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002513 // struct _objc_ivar {
2514 // char *ivar_name;
2515 // char *ivar_type;
2516 // int ivar_offset;
2517 // }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002518 IvarTy = llvm::StructType::get(Int8PtrTy,
2519 Int8PtrTy,
2520 IntTy,
2521 NULL);
2522 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
2523
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002524 // struct _objc_ivar_list *
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002525 IvarListTy = llvm::OpaqueType::get();
2526 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
2527 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
2528
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002529 // struct _objc_method_list *
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002530 MethodListTy = llvm::OpaqueType::get();
2531 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
2532 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
2533
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002534 // struct _objc_cache *
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002535 CacheTy = llvm::OpaqueType::get();
2536 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
2537 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
2538
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002539 // struct _objc_class_extension *
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002540 ClassExtensionTy =
2541 llvm::StructType::get(IntTy,
2542 Int8PtrTy,
2543 PropertyListPtrTy,
2544 NULL);
2545 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
2546 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
2547
2548 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get();
2549
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002550 // struct _objc_class {
2551 // Class isa;
2552 // Class super_class;
2553 // char *name;
2554 // long version;
2555 // long info;
2556 // long instance_size;
2557 // struct _objc_ivar_list *ivars;
2558 // struct _objc_method_list *methods;
2559 // struct _objc_cache *cache;
2560 // struct _objc_protocol_list *protocols;
2561 // char *ivar_layout;
2562 // struct _objc_class_ext *ext;
2563 // };
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002564 T = llvm::StructType::get(llvm::PointerType::getUnqual(ClassTyHolder),
2565 llvm::PointerType::getUnqual(ClassTyHolder),
2566 Int8PtrTy,
2567 LongTy,
2568 LongTy,
2569 LongTy,
2570 IvarListPtrTy,
2571 MethodListPtrTy,
2572 CachePtrTy,
2573 ProtocolListPtrTy,
2574 Int8PtrTy,
2575 ClassExtensionPtrTy,
2576 NULL);
2577 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
2578
2579 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
2580 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
2581 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
2582
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002583 // struct _objc_category {
2584 // char *category_name;
2585 // char *class_name;
2586 // struct _objc_method_list *instance_method;
2587 // struct _objc_method_list *class_method;
2588 // uint32_t size; // sizeof(struct _objc_category)
2589 // struct _objc_property_list *instance_properties;// category's @property
2590 // }
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002591 CategoryTy = llvm::StructType::get(Int8PtrTy,
2592 Int8PtrTy,
2593 MethodListPtrTy,
2594 MethodListPtrTy,
2595 ProtocolListPtrTy,
2596 IntTy,
2597 PropertyListPtrTy,
2598 NULL);
2599 CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
2600
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002601 // Global metadata structures
2602
Fariborz Jahanian10a42312009-01-21 00:39:53 +00002603 // struct _objc_symtab {
2604 // long sel_ref_cnt;
2605 // SEL *refs;
2606 // short cls_def_cnt;
2607 // short cat_def_cnt;
2608 // char *defs[cls_def_cnt + cat_def_cnt];
2609 // }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002610 SymtabTy = llvm::StructType::get(LongTy,
2611 SelectorPtrTy,
2612 ShortTy,
2613 ShortTy,
Daniel Dunbar86e253a2008-08-22 20:34:54 +00002614 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002615 NULL);
2616 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
2617 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
2618
Fariborz Jahaniandb286862009-01-22 00:37:21 +00002619 // struct _objc_module {
2620 // long version;
2621 // long size; // sizeof(struct _objc_module)
2622 // char *name;
2623 // struct _objc_symtab* symtab;
2624 // }
Daniel Dunbar27f9d772008-08-21 04:36:09 +00002625 ModuleTy =
2626 llvm::StructType::get(LongTy,
2627 LongTy,
2628 Int8PtrTy,
2629 SymtabPtrTy,
2630 NULL);
2631 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar14c80b72008-08-23 09:25:55 +00002632
Daniel Dunbar49f66022008-09-24 03:38:44 +00002633 // Message send functions.
Daniel Dunbar14c80b72008-08-23 09:25:55 +00002634
Fariborz Jahaniandb286862009-01-22 00:37:21 +00002635 // id objc_msgSend (id, SEL, ...)
Daniel Dunbar14c80b72008-08-23 09:25:55 +00002636 std::vector<const llvm::Type*> Params;
2637 Params.push_back(ObjectPtrTy);
2638 Params.push_back(SelectorPtrTy);
Daniel Dunbarad2dc712008-10-01 01:06:06 +00002639 MessageSendFn =
2640 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
2641 Params,
2642 true),
2643 "objc_msgSend");
Daniel Dunbar14c80b72008-08-23 09:25:55 +00002644
Fariborz Jahaniandb286862009-01-22 00:37:21 +00002645 // id objc_msgSend_stret (id, SEL, ...)
Daniel Dunbar14c80b72008-08-23 09:25:55 +00002646 Params.clear();
Daniel Dunbar14c80b72008-08-23 09:25:55 +00002647 Params.push_back(ObjectPtrTy);
2648 Params.push_back(SelectorPtrTy);
2649 MessageSendStretFn =
Daniel Dunbarad2dc712008-10-01 01:06:06 +00002650 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
2651 Params,
2652 true),
2653 "objc_msgSend_stret");
Daniel Dunbar5669e572008-10-17 03:24:53 +00002654
Fariborz Jahaniandb286862009-01-22 00:37:21 +00002655 //
Daniel Dunbar5669e572008-10-17 03:24:53 +00002656 Params.clear();
2657 Params.push_back(ObjectPtrTy);
2658 Params.push_back(SelectorPtrTy);
2659 // FIXME: This should be long double on x86_64?
Fariborz Jahaniandb286862009-01-22 00:37:21 +00002660 // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
Daniel Dunbar5669e572008-10-17 03:24:53 +00002661 MessageSendFpretFn =
2662 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::DoubleTy,
2663 Params,
2664 true),
2665 "objc_msgSend_fpret");
Daniel Dunbar14c80b72008-08-23 09:25:55 +00002666
Fariborz Jahaniandb286862009-01-22 00:37:21 +00002667 // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
Daniel Dunbar14c80b72008-08-23 09:25:55 +00002668 Params.clear();
2669 Params.push_back(SuperPtrTy);
2670 Params.push_back(SelectorPtrTy);
2671 MessageSendSuperFn =
Daniel Dunbarad2dc712008-10-01 01:06:06 +00002672 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
2673 Params,
2674 true),
2675 "objc_msgSendSuper");
Daniel Dunbar14c80b72008-08-23 09:25:55 +00002676
Fariborz Jahaniandb286862009-01-22 00:37:21 +00002677 // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
2678 // SEL op, ...)
Daniel Dunbar14c80b72008-08-23 09:25:55 +00002679 Params.clear();
2680 Params.push_back(Int8PtrTy);
2681 Params.push_back(SuperPtrTy);
2682 Params.push_back(SelectorPtrTy);
2683 MessageSendSuperStretFn =
Daniel Dunbarad2dc712008-10-01 01:06:06 +00002684 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
2685 Params,
2686 true),
2687 "objc_msgSendSuper_stret");
Daniel Dunbar5669e572008-10-17 03:24:53 +00002688
2689 // There is no objc_msgSendSuper_fpret? How can that work?
2690 MessageSendSuperFpretFn = MessageSendSuperFn;
Anders Carlsson2abd89c2008-08-31 04:05:03 +00002691
Anders Carlsson124526b2008-09-09 10:10:21 +00002692 // FIXME: This is the size of the setjmp buffer and should be
2693 // target specific. 18 is what's used on 32-bit X86.
2694 uint64_t SetJmpBufferSize = 18;
2695
2696 // Exceptions
2697 const llvm::Type *StackPtrTy =
Daniel Dunbar10004912008-09-27 06:32:25 +00002698 llvm::ArrayType::get(llvm::PointerType::getUnqual(llvm::Type::Int8Ty), 4);
Anders Carlsson124526b2008-09-09 10:10:21 +00002699
2700 ExceptionDataTy =
2701 llvm::StructType::get(llvm::ArrayType::get(llvm::Type::Int32Ty,
2702 SetJmpBufferSize),
2703 StackPtrTy, NULL);
2704 CGM.getModule().addTypeName("struct._objc_exception_data",
2705 ExceptionDataTy);
2706
2707 Params.clear();
2708 Params.push_back(ObjectPtrTy);
2709 ExceptionThrowFn =
Daniel Dunbarad2dc712008-10-01 01:06:06 +00002710 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
2711 Params,
2712 false),
2713 "objc_exception_throw");
Anders Carlsson124526b2008-09-09 10:10:21 +00002714
2715 Params.clear();
2716 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
2717 ExceptionTryEnterFn =
Daniel Dunbarad2dc712008-10-01 01:06:06 +00002718 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
2719 Params,
2720 false),
2721 "objc_exception_try_enter");
Anders Carlsson124526b2008-09-09 10:10:21 +00002722 ExceptionTryExitFn =
Daniel Dunbarad2dc712008-10-01 01:06:06 +00002723 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
2724 Params,
2725 false),
2726 "objc_exception_try_exit");
Anders Carlsson124526b2008-09-09 10:10:21 +00002727 ExceptionExtractFn =
Daniel Dunbarad2dc712008-10-01 01:06:06 +00002728 CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
2729 Params,
2730 false),
2731 "objc_exception_extract");
Anders Carlsson124526b2008-09-09 10:10:21 +00002732
2733 Params.clear();
2734 Params.push_back(ClassPtrTy);
2735 Params.push_back(ObjectPtrTy);
2736 ExceptionMatchFn =
Daniel Dunbarad2dc712008-10-01 01:06:06 +00002737 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty,
2738 Params,
2739 false),
2740 "objc_exception_match");
Chris Lattner10cac6f2008-11-15 21:26:17 +00002741
2742 // synchronized APIs
2743 // void objc_sync_enter (id)
2744 Params.clear();
2745 Params.push_back(ObjectPtrTy);
2746 SyncEnterFn =
2747 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
2748 Params,
2749 false),
2750 "objc_sync_enter");
2751 // void objc_sync_exit (id)
2752 SyncExitFn =
2753 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy,
2754 Params,
2755 false),
2756 "objc_sync_exit");
2757
Anders Carlsson124526b2008-09-09 10:10:21 +00002758
2759 Params.clear();
2760 Params.push_back(llvm::PointerType::getUnqual(llvm::Type::Int32Ty));
2761 SetJmpFn =
Daniel Dunbarad2dc712008-10-01 01:06:06 +00002762 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty,
2763 Params,
2764 false),
2765 "_setjmp");
Fariborz Jahanian6d657c42008-11-18 20:18:11 +00002766
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00002767}
2768
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00002769ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002770: ObjCCommonTypesHelper(cgm)
2771{
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00002772 // struct _method_list_t {
2773 // uint32_t entsize; // sizeof(struct _objc_method)
2774 // uint32_t method_count;
2775 // struct _objc_method method_list[method_count];
2776 // }
2777
2778 // struct _protocol_t {
2779 // id isa; // NULL
2780 // const char * const protocol_name;
2781 // const struct * _protocol_t const protocol_list;
2782 // const struct method_list_t * const instance_methods;
2783 // const struct method_list_t * const class_methods;
2784 // const struct method_list_t *optionalInstanceMethods;
2785 // const struct method_list_t *optionalClassMethods;
2786 // const struct _prop_list_t * const properties;
2787 // const uint32_t size; // sizeof(struct _protocol_t)
2788 // const uint32_t flags; // = 0
2789 // }
2790
2791 // struct _objc_protocol_list {
2792 // long protocol_count;
2793 // struct _protocol_t[protocol_count];
2794 // }
2795
2796 // struct _class_t {
2797 // struct _class_t *isa;
2798 // struct _class_t * const superclass;
2799 // void *cache;
2800 // IMP *vtable;
2801 // struct class_ro_t *ro;
2802 // }
2803
2804 // struct _ivar_t {
2805 // unsigned long int *offset; // pointer to ivar offset location
2806 // char *name;
2807 // char *type;
2808 // uint32_t alignment;
2809 // uint32_t size;
2810 // }
2811
2812 // struct _ivar_list_t {
2813 // uint32 entsize; // sizeof(struct _ivar_t)
2814 // uint32 count;
2815 // struct _iver_t list[count];
2816 // }
2817
2818 // struct class_ro_t {
2819 // uint32_t const flags;
2820 // uint32_t const instanceStart;
2821 // uint32_t const instanceSize;
2822 // uint32_t const reserved; // only when building for 64bit targets
2823 // const uint8_t * const ivarLayout;
2824 // const char *const name;
2825 // const struct _method_list_t * const baseMethods;
2826 // const struct _objc_protocol_list *const baseProtocols;
2827 // const struct _ivar_list_t *const ivars;
2828 // const uint8_t * const weakIvarLayout;
2829 // const struct _prop_list_t * const properties;
2830 // }
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00002831}
2832
Daniel Dunbarbbce49b2008-08-12 00:12:39 +00002833/* *** */
2834
Daniel Dunbar6efc0c52008-08-13 03:21:16 +00002835CodeGen::CGObjCRuntime *
2836CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
Daniel Dunbarc17a4d32008-08-11 02:45:11 +00002837 return new CGObjCMac(CGM);
2838}
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002839
2840CodeGen::CGObjCRuntime *
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00002841CodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) {
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002842 return 0;
Fariborz Jahanian30bc5712009-01-22 23:02:58 +00002843 // return new CGObjCNonFragileABIMac(CGM);
Fariborz Jahanianee0af742009-01-21 22:04:16 +00002844}