blob: ff7717dad33bffadb053c69ec143e1a8bf5ccc61 [file] [log] [blame]
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides Objective-C code generation targetting the Apple runtime.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CGObjCRuntime.h"
Daniel Dunbar1be1df32008-08-11 21:35:06 +000015
16#include "CodeGenModule.h"
Daniel Dunbarace33292008-08-16 03:19:19 +000017#include "CodeGenFunction.h"
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000018#include "clang/AST/ASTContext.h"
Daniel Dunbarde300732008-08-11 04:54:23 +000019#include "clang/AST/Decl.h"
Daniel Dunbarcffcdac2008-08-13 03:21:16 +000020#include "clang/AST/DeclObjC.h"
Daniel Dunbar1be1df32008-08-11 21:35:06 +000021#include "clang/Basic/LangOptions.h"
22
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000023#include "llvm/Module.h"
Daniel Dunbar8c85fac2008-08-11 02:45:11 +000024#include "llvm/Support/IRBuilder.h"
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +000025#include "llvm/Target/TargetData.h"
Daniel Dunbarace33292008-08-16 03:19:19 +000026#include <sstream>
Daniel Dunbar8c85fac2008-08-11 02:45:11 +000027
28using namespace clang;
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +000029using namespace CodeGen;
Daniel Dunbar8c85fac2008-08-11 02:45:11 +000030
31namespace {
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000032
Daniel Dunbarfe131f02008-08-27 02:31:56 +000033 typedef std::vector<llvm::Constant*> ConstantVector;
34
Daniel Dunbarcffcdac2008-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
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000038/// ObjCTypesHelper - Helper class that encapsulates lazy
39/// construction of varies types used during ObjC generation.
40class ObjCTypesHelper {
41private:
42 CodeGen::CodeGenModule &CGM;
43
Daniel Dunbar87062ff2008-08-23 09:25:55 +000044 llvm::Function *MessageSendFn, *MessageSendStretFn;
45 llvm::Function *MessageSendSuperFn, *MessageSendSuperStretFn;
Daniel Dunbar5eec6142008-08-12 03:39:23 +000046
Daniel Dunbardaf4ad42008-08-12 00:12:39 +000047public:
Daniel Dunbarb050fa62008-08-21 04:36:09 +000048 const llvm::Type *ShortTy, *IntTy, *LongTy;
49 const llvm::Type *Int8PtrTy;
Daniel Dunbar5eec6142008-08-12 03:39:23 +000050
Daniel Dunbar6fa3daf2008-08-12 05:28:47 +000051 /// ObjectPtrTy - LLVM type for object handles (typeof(id))
52 const llvm::Type *ObjectPtrTy;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +000053 /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
Daniel Dunbar6fa3daf2008-08-12 05:28:47 +000054 const llvm::Type *SelectorPtrTy;
Daniel Dunbarcffcdac2008-08-13 03:21:16 +000055 /// ProtocolPtrTy - LLVM type for external protocol handles
56 /// (typeof(Protocol))
57 const llvm::Type *ExternalProtocolPtrTy;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +000058
Daniel Dunbar0ed60b02008-08-30 03:02:31 +000059 // SuperCTy - clang type for struct objc_super.
60 QualType SuperCTy;
61 // SuperPtrCTy - clang type for struct objc_super *.
62 QualType SuperPtrCTy;
63
Daniel Dunbar15245e52008-08-23 04:28:29 +000064 /// SuperTy - LLVM type for struct objc_super.
65 const llvm::StructType *SuperTy;
Daniel Dunbar87062ff2008-08-23 09:25:55 +000066 /// SuperPtrTy - LLVM type for struct objc_super *.
67 const llvm::Type *SuperPtrTy;
Daniel Dunbar15245e52008-08-23 04:28:29 +000068
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +000069 /// SymtabTy - LLVM type for struct objc_symtab.
70 const llvm::StructType *SymtabTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +000071 /// SymtabPtrTy - LLVM type for struct objc_symtab *.
72 const llvm::Type *SymtabPtrTy;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +000073 /// ModuleTy - LLVM type for struct objc_module.
74 const llvm::StructType *ModuleTy;
Daniel Dunbar5eec6142008-08-12 03:39:23 +000075
Daniel Dunbarcffcdac2008-08-13 03:21:16 +000076 /// ProtocolTy - LLVM type for struct objc_protocol.
77 const llvm::StructType *ProtocolTy;
78 /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
79 const llvm::Type *ProtocolPtrTy;
80 /// ProtocolExtensionTy - LLVM type for struct
81 /// objc_protocol_extension.
82 const llvm::StructType *ProtocolExtensionTy;
83 /// ProtocolExtensionTy - LLVM type for struct
84 /// objc_protocol_extension *.
85 const llvm::Type *ProtocolExtensionPtrTy;
86 /// MethodDescriptionTy - LLVM type for struct
87 /// objc_method_description.
88 const llvm::StructType *MethodDescriptionTy;
89 /// MethodDescriptionListTy - LLVM type for struct
90 /// objc_method_description_list.
91 const llvm::StructType *MethodDescriptionListTy;
92 /// MethodDescriptionListPtrTy - LLVM type for struct
93 /// objc_method_description_list *.
94 const llvm::Type *MethodDescriptionListPtrTy;
Daniel Dunbara6eb6b72008-08-23 00:19:03 +000095 /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
96 /// in GCC parlance).
97 const llvm::StructType *PropertyTy;
98 /// PropertyListTy - LLVM type for struct objc_property_list
99 /// (_prop_list_t in GCC parlance).
100 const llvm::StructType *PropertyListTy;
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000101 /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
102 const llvm::Type *PropertyListPtrTy;
103 /// ProtocolListTy - LLVM type for struct objc_property_list.
104 const llvm::Type *ProtocolListTy;
105 /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
106 const llvm::Type *ProtocolListPtrTy;
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000107 /// CategoryTy - LLVM type for struct objc_category.
108 const llvm::StructType *CategoryTy;
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000109 /// ClassTy - LLVM type for struct objc_class.
110 const llvm::StructType *ClassTy;
111 /// ClassPtrTy - LLVM type for struct objc_class *.
112 const llvm::Type *ClassPtrTy;
113 /// ClassExtensionTy - LLVM type for struct objc_class_ext.
114 const llvm::StructType *ClassExtensionTy;
115 /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
116 const llvm::Type *ClassExtensionPtrTy;
117 /// CacheTy - LLVM type for struct objc_cache.
118 const llvm::Type *CacheTy;
119 /// CachePtrTy - LLVM type for struct objc_cache *.
120 const llvm::Type *CachePtrTy;
121 // IvarTy - LLVM type for struct objc_ivar.
122 const llvm::StructType *IvarTy;
123 /// IvarListTy - LLVM type for struct objc_ivar_list.
124 const llvm::Type *IvarListTy;
125 /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
126 const llvm::Type *IvarListPtrTy;
127 // MethodTy - LLVM type for struct objc_method.
128 const llvm::StructType *MethodTy;
129 /// MethodListTy - LLVM type for struct objc_method_list.
130 const llvm::Type *MethodListTy;
131 /// MethodListPtrTy - LLVM type for struct objc_method_list *.
132 const llvm::Type *MethodListPtrTy;
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000133
Anders Carlsson58d16242008-08-31 04:05:03 +0000134 llvm::Function *EnumerationMutationFn;
Anders Carlsson9acb0a42008-09-09 10:10:21 +0000135
136 /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
137 const llvm::Type *ExceptionDataTy;
138
139 /// ExceptionThrowFn - LLVM objc_exception_throw function.
140 llvm::Function *ExceptionThrowFn;
141
142 /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
143 llvm::Function *ExceptionTryEnterFn;
144
145 /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
146 llvm::Function *ExceptionTryExitFn;
147
148 /// ExceptionExtractFn - LLVM objc_exception_extract function.
149 llvm::Function *ExceptionExtractFn;
150
151 /// ExceptionMatchFn - LLVM objc_exception_match function.
152 llvm::Function *ExceptionMatchFn;
153
154 /// SetJmpFn - LLVM _setjmp function.
155 llvm::Function *SetJmpFn;
156
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000157public:
158 ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
159 ~ObjCTypesHelper();
160
Daniel Dunbar49f5a0d2008-09-09 23:48:28 +0000161 llvm::Value *getMessageSendFn(bool IsSuper, bool isStret,
162 const llvm::Type *ReturnTy);
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000163};
164
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000165class CGObjCMac : public CodeGen::CGObjCRuntime {
166private:
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000167 CodeGen::CodeGenModule &CGM;
168 ObjCTypesHelper ObjCTypes;
169 /// ObjCABI - FIXME: Not sure yet.
170 unsigned ObjCABI;
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000171
Daniel Dunbar8ede0052008-08-25 06:02:07 +0000172 /// LazySymbols - Symbols to generate a lazy reference for. See
173 /// DefinedSymbols and FinishModule().
174 std::set<IdentifierInfo*> LazySymbols;
175
176 /// DefinedSymbols - External symbols which are defined by this
177 /// module. The symbols in this list and LazySymbols are used to add
178 /// special linker symbols which ensure that Objective-C modules are
179 /// linked properly.
180 std::set<IdentifierInfo*> DefinedSymbols;
181
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000182 /// ClassNames - uniqued class names.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000183 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000184
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000185 /// MethodVarNames - uniqued method variable names.
186 llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
187
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000188 /// MethodVarTypes - uniqued method type signatures. We have to use
189 /// a StringMap here because have no other unique reference.
190 llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
191
Daniel Dunbar12996f52008-08-26 21:51:14 +0000192 /// MethodDefinitions - map of methods which have been defined in
193 /// this translation unit.
194 llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
195
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000196 /// PropertyNames - uniqued method variable names.
197 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
198
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000199 /// ClassReferences - uniqued class references.
200 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
201
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000202 /// SelectorReferences - uniqued selector references.
203 llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
204
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000205 /// Protocols - Protocols for which an objc_protocol structure has
206 /// been emitted. Forward declarations are handled by creating an
207 /// empty structure whose initializer is filled in when/if defined.
208 llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
209
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000210 /// DefinedClasses - List of defined classes.
211 std::vector<llvm::GlobalValue*> DefinedClasses;
212
213 /// DefinedCategories - List of defined categories.
214 std::vector<llvm::GlobalValue*> DefinedCategories;
215
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000216 /// UsedGlobals - List of globals to pack into the llvm.used metadata
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000217 /// to prevent them from being clobbered.
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000218 std::vector<llvm::GlobalVariable*> UsedGlobals;
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000219
220 /// EmitImageInfo - Emit the image info marker used to encode some module
221 /// level information.
222 void EmitImageInfo();
223
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000224 /// EmitModuleInfo - Another marker encoding module level
225 /// information.
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000226 void EmitModuleInfo();
227
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000228 /// EmitModuleSymols - Emit module symbols, the list of defined
229 /// classes and categories. The result has type SymtabPtrTy.
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000230 llvm::Constant *EmitModuleSymbols();
231
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000232 /// FinishModule - Write out global data structures at the end of
233 /// processing a translation unit.
234 void FinishModule();
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000235
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000236 /// EmitClassExtension - Generate the class extension structure used
237 /// to store the weak ivar layout and properties. The return value
238 /// has type ClassExtensionPtrTy.
239 llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
240
241 /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
242 /// for the given class.
243 llvm::Value *EmitClassRef(llvm::IRBuilder<> &Builder,
244 const ObjCInterfaceDecl *ID);
245
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000246 CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000247 QualType ResultType,
248 Selector Sel,
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000249 llvm::Value *Arg0,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000250 QualType Arg0Ty,
251 bool IsSuper,
252 const CallArgList &CallArgs);
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000253
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000254 /// EmitIvarList - Emit the ivar list for the given
255 /// implementation. If ForClass is true the list of class ivars
256 /// (i.e. metaclass ivars) is emitted, otherwise the list of
257 /// interface ivars will be emitted. The return value has type
258 /// IvarListPtrTy.
259 llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
260 bool ForClass,
261 const llvm::Type *InterfaceTy);
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000262
263 /// EmitMetaClass - Emit a forward reference to the class structure
264 /// for the metaclass of the given interface. The return value has
265 /// type ClassPtrTy.
266 llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
267
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000268 /// EmitMetaClass - Emit a class structure for the metaclass of the
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000269 /// given implementation. The return value has type ClassPtrTy.
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000270 llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
271 llvm::Constant *Protocols,
Daniel Dunbar12996f52008-08-26 21:51:14 +0000272 const llvm::Type *InterfaceTy,
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000273 const ConstantVector &Methods);
274
275 llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
276
277 llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000278
279 /// EmitMethodList - Emit the method list for the given
Daniel Dunbar6b57d432008-08-26 08:29:31 +0000280 /// implementation. The return value has type MethodListPtrTy.
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000281 llvm::Constant *EmitMethodList(const std::string &Name,
282 const char *Section,
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000283 const ConstantVector &Methods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000284
285 /// EmitMethodDescList - Emit a method description list for a list of
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000286 /// method declarations.
287 /// - TypeName: The name for the type containing the methods.
288 /// - IsProtocol: True iff these methods are for a protocol.
289 /// - ClassMethds: True iff these are class methods.
290 /// - Required: When true, only "required" methods are
291 /// listed. Similarly, when false only "optional" methods are
292 /// listed. For classes this should always be true.
293 /// - begin, end: The method list to output.
294 ///
295 /// The return value has type MethodDescriptionListPtrTy.
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000296 llvm::Constant *EmitMethodDescList(const std::string &Name,
297 const char *Section,
298 const ConstantVector &Methods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000299
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000300 /// EmitPropertyList - Emit the given property list. The return
301 /// value has type PropertyListPtrTy.
302 llvm::Constant *EmitPropertyList(const std::string &Name,
Daniel Dunbar698d6f32008-08-28 04:38:10 +0000303 const Decl *Container,
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000304 ObjCPropertyDecl * const *begin,
305 ObjCPropertyDecl * const *end);
306
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000307 /// EmitProtocolExtension - Generate the protocol extension
308 /// structure used to store optional instance and class methods, and
309 /// protocol properties. The return value has type
310 /// ProtocolExtensionPtrTy.
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000311 llvm::Constant *
312 EmitProtocolExtension(const ObjCProtocolDecl *PD,
313 const ConstantVector &OptInstanceMethods,
314 const ConstantVector &OptClassMethods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000315
316 /// EmitProtocolList - Generate the list of referenced
317 /// protocols. The return value has type ProtocolListPtrTy.
Daniel Dunbar67e778b2008-08-21 21:57:41 +0000318 llvm::Constant *EmitProtocolList(const std::string &Name,
319 ObjCProtocolDecl::protocol_iterator begin,
320 ObjCProtocolDecl::protocol_iterator end);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000321
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000322 /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
323 /// for the given selector.
324 llvm::Value *EmitSelector(llvm::IRBuilder<> &Builder, Selector Sel);
325
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000326 /// GetProtocolRef - Return a reference to the internal protocol
327 /// description, creating an empty one if it has not been
328 /// defined. The return value has type pointer-to ProtocolTy.
329 llvm::GlobalVariable *GetProtocolRef(const ObjCProtocolDecl *PD);
330
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000331 /// GetClassName - Return a unique constant for the given selector's
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000332 /// name. The return value has type char *.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000333 llvm::Constant *GetClassName(IdentifierInfo *Ident);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +0000334
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000335 /// GetMethodVarName - Return a unique constant for the given
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000336 /// selector's name. The return value has type char *.
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000337 llvm::Constant *GetMethodVarName(Selector Sel);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000338 llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000339 llvm::Constant *GetMethodVarName(const std::string &Name);
Daniel Dunbar1be1df32008-08-11 21:35:06 +0000340
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000341 /// GetMethodVarType - Return a unique constant for the given
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000342 /// selector's name. The return value has type char *.
343
344 // FIXME: This is a horrible name.
Daniel Dunbar12996f52008-08-26 21:51:14 +0000345 llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000346 llvm::Constant *GetMethodVarType(const std::string &Name);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000347
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000348 /// GetPropertyName - Return a unique constant for the given
349 /// name. The return value has type char *.
350 llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
351
Daniel Dunbar698d6f32008-08-28 04:38:10 +0000352 // FIXME: This can be dropped once string functions are unified.
353 llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
354 const Decl *Container);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000355
Daniel Dunbarace33292008-08-16 03:19:19 +0000356 /// GetNameForMethod - Return a name for the given method.
357 /// \param[out] NameOut - The return value.
358 void GetNameForMethod(const ObjCMethodDecl *OMD,
359 std::string &NameOut);
360
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000361public:
362 CGObjCMac(CodeGen::CodeGenModule &cgm);
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000363 virtual llvm::Constant *GenerateConstantString(const std::string &String);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000364
Daniel Dunbara04840b2008-08-23 03:46:30 +0000365 virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000366 QualType ResultType,
367 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000368 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000369 bool IsClassMessage,
370 const CallArgList &CallArgs);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000371
Daniel Dunbara04840b2008-08-23 03:46:30 +0000372 virtual CodeGen::RValue
373 GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000374 QualType ResultType,
375 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000376 const ObjCInterfaceDecl *Class,
377 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000378 bool IsClassMessage,
379 const CallArgList &CallArgs);
Daniel Dunbar434627a2008-08-16 00:25:02 +0000380
381 virtual llvm::Value *GetClass(llvm::IRBuilder<> &Builder,
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000382 const ObjCInterfaceDecl *ID);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000383
384 virtual llvm::Value *GetSelector(llvm::IRBuilder<> &Builder, Selector Sel);
385
Daniel Dunbarac93e472008-08-15 22:20:32 +0000386 virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000387
Daniel Dunbarac93e472008-08-15 22:20:32 +0000388 virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000389
Daniel Dunbarac93e472008-08-15 22:20:32 +0000390 virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000391
392 virtual llvm::Value *GenerateProtocolRef(llvm::IRBuilder<> &Builder,
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000393 const ObjCProtocolDecl *PD);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000394
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000395 virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000396
397 virtual llvm::Function *ModuleInitFunction();
Anders Carlsson58d16242008-08-31 04:05:03 +0000398 virtual llvm::Function *EnumerationMutationFunction();
Anders Carlssonb01a2112008-09-09 10:04:29 +0000399
400 virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
401 const ObjCAtTryStmt &S);
402 virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
403 const ObjCAtThrowStmt &S);
404
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000405};
406} // end anonymous namespace
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000407
408/* *** Helper Functions *** */
409
410/// getConstantGEP() - Help routine to construct simple GEPs.
411static llvm::Constant *getConstantGEP(llvm::Constant *C,
412 unsigned idx0,
413 unsigned idx1) {
414 llvm::Value *Idxs[] = {
415 llvm::ConstantInt::get(llvm::Type::Int32Ty, idx0),
416 llvm::ConstantInt::get(llvm::Type::Int32Ty, idx1)
417 };
418 return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
419}
420
421/* *** CGObjCMac Public Interface *** */
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000422
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000423CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm)
424 : CGM(cgm),
425 ObjCTypes(cgm),
426 ObjCABI(1)
427{
428 // FIXME: How does this get set in GCC? And what does it even mean?
429 if (ObjCTypes.LongTy != CGM.getTypes().ConvertType(CGM.getContext().IntTy))
430 ObjCABI = 2;
431
432 EmitImageInfo();
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000433}
434
Daniel Dunbar434627a2008-08-16 00:25:02 +0000435/// GetClass - Return a reference to the class for the given interface
436/// decl.
437llvm::Value *CGObjCMac::GetClass(llvm::IRBuilder<> &Builder,
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000438 const ObjCInterfaceDecl *ID) {
439 return EmitClassRef(Builder, ID);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000440}
441
442/// GetSelector - Return the pointer to the unique'd string for this selector.
443llvm::Value *CGObjCMac::GetSelector(llvm::IRBuilder<> &Builder, Selector Sel) {
Daniel Dunbar5eec6142008-08-12 03:39:23 +0000444 return EmitSelector(Builder, Sel);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000445}
446
Daniel Dunbardaf4ad42008-08-12 00:12:39 +0000447/// Generate a constant CFString object.
448/*
449 struct __builtin_CFString {
450 const int *isa; // point to __CFConstantStringClassReference
451 int flags;
452 const char *str;
453 long length;
454 };
455*/
456
457llvm::Constant *CGObjCMac::GenerateConstantString(const std::string &String) {
Daniel Dunbardbdb9512008-08-23 18:37:06 +0000458 return CGM.GetAddrOfConstantCFString(String);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000459}
460
461/// Generates a message send where the super is the receiver. This is
462/// a message send to self with special delivery semantics indicating
463/// which class's method should be called.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000464CodeGen::RValue
465CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000466 QualType ResultType,
467 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000468 const ObjCInterfaceDecl *Class,
469 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000470 bool IsClassMessage,
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +0000471 const CodeGen::CallArgList &CallArgs) {
Daniel Dunbar15245e52008-08-23 04:28:29 +0000472 // Create and init a super structure; this is a (receiver, class)
473 // pair we will pass to objc_msgSendSuper.
474 llvm::Value *ObjCSuper =
475 CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
476 llvm::Value *ReceiverAsObject =
477 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
478 CGF.Builder.CreateStore(ReceiverAsObject,
479 CGF.Builder.CreateStructGEP(ObjCSuper, 0));
Daniel Dunbar15245e52008-08-23 04:28:29 +0000480
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000481 // If this is a class message the metaclass is passed as the target.
482 llvm::Value *Target;
483 if (IsClassMessage) {
484 llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
485 llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
486 llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
487 Target = Super;
488 } else {
489 Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
490 }
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000491 // FIXME: We shouldn't need to do this cast, rectify the ASTContext
492 // and ObjCTypes types.
493 const llvm::Type *ClassTy =
494 CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
495 Target = CGF.Builder.CreateBitCast(Target, ClassTy);
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000496 CGF.Builder.CreateStore(Target,
497 CGF.Builder.CreateStructGEP(ObjCSuper, 1));
498
Daniel Dunbardd851282008-08-30 05:35:15 +0000499 return EmitMessageSend(CGF, ResultType, Sel,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000500 ObjCSuper, ObjCTypes.SuperPtrCTy,
501 true, CallArgs);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000502}
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000503
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000504/// Generate code for a message send expression.
Daniel Dunbara04840b2008-08-23 03:46:30 +0000505CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000506 QualType ResultType,
507 Selector Sel,
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +0000508 llvm::Value *Receiver,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000509 bool IsClassMessage,
510 const CallArgList &CallArgs) {
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000511 llvm::Value *Arg0 =
512 CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy, "tmp");
Daniel Dunbardd851282008-08-30 05:35:15 +0000513 return EmitMessageSend(CGF, ResultType, Sel,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000514 Arg0, CGF.getContext().getObjCIdType(),
515 false, CallArgs);
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000516}
517
518CodeGen::RValue CGObjCMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
Daniel Dunbardd851282008-08-30 05:35:15 +0000519 QualType ResultType,
520 Selector Sel,
Daniel Dunbar87062ff2008-08-23 09:25:55 +0000521 llvm::Value *Arg0,
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000522 QualType Arg0Ty,
523 bool IsSuper,
524 const CallArgList &CallArgs) {
525 CallArgList ActualArgs;
Daniel Dunbar0a2da0f2008-09-09 01:06:48 +0000526 ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
527 ActualArgs.push_back(std::make_pair(RValue::get(EmitSelector(CGF.Builder,
528 Sel)),
Daniel Dunbar0ed60b02008-08-30 03:02:31 +0000529 CGF.getContext().getObjCSelType()));
530 ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
Daniel Dunbarac93e472008-08-15 22:20:32 +0000531
Daniel Dunbar49f5a0d2008-09-09 23:48:28 +0000532 llvm::Value *Fn =
533 ObjCTypes.getMessageSendFn(IsSuper,
534 CGF.ReturnTypeUsesSret(ResultType),
535 CGM.getTypes().ConvertType(ResultType));
536 return CGF.EmitCall(Fn, ResultType, ActualArgs);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000537}
538
539llvm::Value *CGObjCMac::GenerateProtocolRef(llvm::IRBuilder<> &Builder,
Daniel Dunbar84bb85f2008-08-13 00:59:25 +0000540 const ObjCProtocolDecl *PD) {
Daniel Dunbarb3518152008-09-04 04:33:15 +0000541 // FIXME: I don't understand why gcc generates this, or where it is
542 // resolved. Investigate. Its also wasteful to look this up over and
543 // over.
544 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
545
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000546 return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
547 ObjCTypes.ExternalProtocolPtrTy);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000548}
549
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000550/*
551 // APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
552 struct _objc_protocol {
553 struct _objc_protocol_extension *isa;
554 char *protocol_name;
555 struct _objc_protocol_list *protocol_list;
556 struct _objc__method_prototype_list *instance_methods;
557 struct _objc__method_prototype_list *class_methods
558 };
559
560 See EmitProtocolExtension().
561*/
562void CGObjCMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
Daniel Dunbar8ede0052008-08-25 06:02:07 +0000563 // FIXME: I don't understand why gcc generates this, or where it is
564 // resolved. Investigate. Its also wasteful to look this up over and
565 // over.
566 LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
567
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000568 const char *ProtocolName = PD->getName();
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000569
570 // Construct method lists.
571 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
572 std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
573 for (ObjCProtocolDecl::instmeth_iterator i = PD->instmeth_begin(),
574 e = PD->instmeth_end(); i != e; ++i) {
575 ObjCMethodDecl *MD = *i;
576 llvm::Constant *C = GetMethodDescriptionConstant(MD);
577 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
578 OptInstanceMethods.push_back(C);
579 } else {
580 InstanceMethods.push_back(C);
581 }
582 }
583
584 for (ObjCProtocolDecl::classmeth_iterator i = PD->classmeth_begin(),
585 e = PD->classmeth_end(); i != e; ++i) {
586 ObjCMethodDecl *MD = *i;
587 llvm::Constant *C = GetMethodDescriptionConstant(MD);
588 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
589 OptClassMethods.push_back(C);
590 } else {
591 ClassMethods.push_back(C);
592 }
593 }
594
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000595 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000596 Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000597 Values[1] = GetClassName(PD->getIdentifier());
Daniel Dunbar67e778b2008-08-21 21:57:41 +0000598 Values[2] =
599 EmitProtocolList(std::string("\01L_OBJC_PROTOCOL_REFS_")+PD->getName(),
600 PD->protocol_begin(),
601 PD->protocol_end());
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000602 Values[3] =
603 EmitMethodDescList(std::string("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_")
604 + PD->getName(),
605 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
606 InstanceMethods);
607 Values[4] =
608 EmitMethodDescList(std::string("\01L_OBJC_PROTOCOL_CLASS_METHODS_")
609 + PD->getName(),
610 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
611 ClassMethods);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000612 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
613 Values);
614
615 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
616 if (Entry) {
617 // Already created, just update the initializer
618 Entry->setInitializer(Init);
619 } else {
620 Entry =
621 new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false,
622 llvm::GlobalValue::InternalLinkage,
623 Init,
624 std::string("\01L_OBJC_PROTOCOL_")+ProtocolName,
625 &CGM.getModule());
626 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
627 UsedGlobals.push_back(Entry);
628 // FIXME: Is this necessary? Why only for protocol?
629 Entry->setAlignment(4);
630 }
631}
632
633llvm::GlobalVariable *CGObjCMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
634 llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
635
636 if (!Entry) {
637 std::vector<llvm::Constant*> Values(5);
638 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
639 Values[1] = GetClassName(PD->getIdentifier());
640 Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
641 Values[3] = Values[4] =
642 llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
643 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
644 Values);
645
646 Entry =
647 new llvm::GlobalVariable(ObjCTypes.ProtocolTy, false,
648 llvm::GlobalValue::InternalLinkage,
649 Init,
650 std::string("\01L_OBJC_PROTOCOL_")+PD->getName(),
651 &CGM.getModule());
652 Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
653 UsedGlobals.push_back(Entry);
654 // FIXME: Is this necessary? Why only for protocol?
655 Entry->setAlignment(4);
656 }
657
658 return Entry;
659}
660
661/*
662 struct _objc_protocol_extension {
663 uint32_t size;
664 struct objc_method_description_list *optional_instance_methods;
665 struct objc_method_description_list *optional_class_methods;
666 struct objc_property_list *instance_properties;
667 };
668*/
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000669llvm::Constant *
670CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
671 const ConstantVector &OptInstanceMethods,
672 const ConstantVector &OptClassMethods) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000673 uint64_t Size =
674 CGM.getTargetData().getABITypeSize(ObjCTypes.ProtocolExtensionTy);
675 std::vector<llvm::Constant*> Values(4);
676 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000677 Values[1] =
678 EmitMethodDescList(std::string("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_")
679 + PD->getName(),
680 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
681 OptInstanceMethods);
682 Values[2] =
683 EmitMethodDescList(std::string("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_")
684 + PD->getName(),
685 "__OBJC,__cat_cls_meth,regular,no_dead_strip",
686 OptClassMethods);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000687 Values[3] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_PROTO_LIST_") +
688 PD->getName(),
Daniel Dunbar698d6f32008-08-28 04:38:10 +0000689 0,
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000690 PD->classprop_begin(),
691 PD->classprop_end());
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000692
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000693 // Return null if no extension bits are used.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000694 if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
695 Values[3]->isNullValue())
696 return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
697
698 llvm::Constant *Init =
699 llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
700 llvm::GlobalVariable *GV =
701 new llvm::GlobalVariable(ObjCTypes.ProtocolExtensionTy, false,
702 llvm::GlobalValue::InternalLinkage,
703 Init,
704 (std::string("\01L_OBJC_PROTOCOLEXT_") +
705 PD->getName()),
706 &CGM.getModule());
707 // No special section, but goes in llvm.used
708 UsedGlobals.push_back(GV);
709
710 return GV;
711}
712
713/*
714 struct objc_protocol_list {
715 struct objc_protocol_list *next;
716 long count;
717 Protocol *list[];
718 };
719*/
Daniel Dunbar67e778b2008-08-21 21:57:41 +0000720llvm::Constant *
721CGObjCMac::EmitProtocolList(const std::string &Name,
722 ObjCProtocolDecl::protocol_iterator begin,
723 ObjCProtocolDecl::protocol_iterator end) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000724 std::vector<llvm::Constant*> ProtocolRefs;
725
Daniel Dunbar67e778b2008-08-21 21:57:41 +0000726 for (; begin != end; ++begin)
727 ProtocolRefs.push_back(GetProtocolRef(*begin));
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000728
729 // Just return null for empty protocol lists
730 if (ProtocolRefs.empty())
731 return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
732
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000733 // This list is null terminated.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000734 ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
735
736 std::vector<llvm::Constant*> Values(3);
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000737 // This field is only used by the runtime.
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000738 Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
739 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
740 Values[2] =
741 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
742 ProtocolRefs.size()),
743 ProtocolRefs);
744
745 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
746 llvm::GlobalVariable *GV =
747 new llvm::GlobalVariable(Init->getType(), false,
748 llvm::GlobalValue::InternalLinkage,
749 Init,
Daniel Dunbar67e778b2008-08-21 21:57:41 +0000750 Name,
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000751 &CGM.getModule());
752 GV->setSection("__OBJC,__cat_cls_meth,regular,no_dead_strip");
753 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
754}
755
756/*
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000757 struct _objc_property {
758 const char * const name;
759 const char * const attributes;
760 };
761
762 struct _objc_property_list {
763 uint32_t entsize; // sizeof (struct _objc_property)
764 uint32_t prop_count;
765 struct _objc_property[prop_count];
766 };
767*/
768llvm::Constant *CGObjCMac::EmitPropertyList(const std::string &Name,
Daniel Dunbar698d6f32008-08-28 04:38:10 +0000769 const Decl *Container,
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000770 ObjCPropertyDecl * const *begin,
771 ObjCPropertyDecl * const *end) {
772 std::vector<llvm::Constant*> Properties, Prop(2);
773 for (; begin != end; ++begin) {
774 const ObjCPropertyDecl *PD = *begin;
775 Prop[0] = GetPropertyName(PD->getIdentifier());
Daniel Dunbar698d6f32008-08-28 04:38:10 +0000776 Prop[1] = GetPropertyTypeString(PD, Container);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000777 Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
778 Prop));
779 }
780
781 // Return null for empty list.
782 if (Properties.empty())
783 return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
784
785 unsigned PropertySize =
786 CGM.getTargetData().getABITypeSize(ObjCTypes.PropertyTy);
787 std::vector<llvm::Constant*> Values(3);
788 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
789 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
790 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
791 Properties.size());
792 Values[2] = llvm::ConstantArray::get(AT, Properties);
793 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
794
795 llvm::GlobalVariable *GV =
796 new llvm::GlobalVariable(Init->getType(), false,
797 llvm::GlobalValue::InternalLinkage,
798 Init,
799 Name,
800 &CGM.getModule());
801 // No special section on property lists?
802 UsedGlobals.push_back(GV);
803 return llvm::ConstantExpr::getBitCast(GV,
804 ObjCTypes.PropertyListPtrTy);
805
806}
807
808/*
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000809 struct objc_method_description_list {
810 int count;
811 struct objc_method_description list[];
812 };
813*/
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000814llvm::Constant *
815CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
816 std::vector<llvm::Constant*> Desc(2);
817 Desc[0] = llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
818 ObjCTypes.SelectorPtrTy);
819 Desc[1] = GetMethodVarType(MD);
820 return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
821 Desc);
822}
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000823
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000824llvm::Constant *CGObjCMac::EmitMethodDescList(const std::string &Name,
825 const char *Section,
826 const ConstantVector &Methods) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000827 // Return null for empty list.
828 if (Methods.empty())
829 return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
830
831 std::vector<llvm::Constant*> Values(2);
832 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
833 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
834 Methods.size());
835 Values[1] = llvm::ConstantArray::get(AT, Methods);
836 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
837
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000838 llvm::GlobalVariable *GV =
839 new llvm::GlobalVariable(Init->getType(), false,
840 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000841 Init, Name, &CGM.getModule());
842 GV->setSection(Section);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +0000843 UsedGlobals.push_back(GV);
844 return llvm::ConstantExpr::getBitCast(GV,
845 ObjCTypes.MethodDescriptionListPtrTy);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000846}
847
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000848/*
849 struct _objc_category {
850 char *category_name;
851 char *class_name;
852 struct _objc_method_list *instance_methods;
853 struct _objc_method_list *class_methods;
854 struct _objc_protocol_list *protocols;
855 uint32_t size; // <rdar://4585769>
856 struct _objc_property_list *instance_properties;
857 };
858 */
Daniel Dunbarac93e472008-08-15 22:20:32 +0000859void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000860 unsigned Size = CGM.getTargetData().getABITypeSize(ObjCTypes.CategoryTy);
861
Daniel Dunbar0cd49032008-08-26 23:03:11 +0000862 // FIXME: This is poor design, the OCD should have a pointer to the
863 // category decl. Additionally, note that Category can be null for
864 // the @implementation w/o an @interface case. Sema should just
865 // create one for us as it does for @implementation so everyone else
866 // can live life under a clear blue sky.
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000867 const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
Daniel Dunbar0cd49032008-08-26 23:03:11 +0000868 const ObjCCategoryDecl *Category =
869 Interface->FindCategoryDeclaration(OCD->getIdentifier());
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000870 std::string ExtName(std::string(Interface->getName()) +
871 "_" +
872 OCD->getName());
873
Daniel Dunbar12996f52008-08-26 21:51:14 +0000874 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
875 for (ObjCCategoryImplDecl::instmeth_iterator i = OCD->instmeth_begin(),
876 e = OCD->instmeth_end(); i != e; ++i) {
877 // Instance methods should always be defined.
878 InstanceMethods.push_back(GetMethodConstant(*i));
879 }
880 for (ObjCCategoryImplDecl::classmeth_iterator i = OCD->classmeth_begin(),
881 e = OCD->classmeth_end(); i != e; ++i) {
882 // Class methods should always be defined.
883 ClassMethods.push_back(GetMethodConstant(*i));
884 }
885
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000886 std::vector<llvm::Constant*> Values(7);
887 Values[0] = GetClassName(OCD->getIdentifier());
888 Values[1] = GetClassName(Interface->getIdentifier());
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000889 Values[2] =
890 EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") +
891 ExtName,
892 "__OBJC,__cat_inst_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +0000893 InstanceMethods);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +0000894 Values[3] =
895 EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName,
896 "__OBJC,__cat_class_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +0000897 ClassMethods);
Daniel Dunbarfe131f02008-08-27 02:31:56 +0000898 if (Category) {
899 Values[4] =
900 EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName,
901 Category->protocol_begin(),
902 Category->protocol_end());
903 } else {
904 Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
905 }
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000906 Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar0cd49032008-08-26 23:03:11 +0000907
908 // If there is no category @interface then there can be no properties.
909 if (Category) {
910 Values[6] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_LIST_") + ExtName,
Daniel Dunbar698d6f32008-08-28 04:38:10 +0000911 OCD,
Daniel Dunbar0cd49032008-08-26 23:03:11 +0000912 Category->classprop_begin(),
913 Category->classprop_end());
914 } else {
915 Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
916 }
Daniel Dunbar4246a8b2008-08-22 20:34:54 +0000917
918 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
919 Values);
920
921 llvm::GlobalVariable *GV =
922 new llvm::GlobalVariable(ObjCTypes.CategoryTy, false,
923 llvm::GlobalValue::InternalLinkage,
924 Init,
925 std::string("\01L_OBJC_CATEGORY_")+ExtName,
926 &CGM.getModule());
927 GV->setSection("__OBJC,__category,regular,no_dead_strip");
928 UsedGlobals.push_back(GV);
929 DefinedCategories.push_back(GV);
Daniel Dunbar8c85fac2008-08-11 02:45:11 +0000930}
931
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000932// FIXME: Get from somewhere?
933enum ClassFlags {
934 eClassFlags_Factory = 0x00001,
935 eClassFlags_Meta = 0x00002,
936 // <rdr://5142207>
937 eClassFlags_HasCXXStructors = 0x02000,
938 eClassFlags_Hidden = 0x20000,
939 eClassFlags_ABI2_Hidden = 0x00010,
940 eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
941};
942
943// <rdr://5142207&4705298&4843145>
944static bool IsClassHidden(const ObjCInterfaceDecl *ID) {
945 if (const VisibilityAttr *attr = ID->getAttr<VisibilityAttr>()) {
946 // FIXME: Support -fvisibility
947 switch (attr->getVisibility()) {
948 default:
949 assert(0 && "Unknown visibility");
950 return false;
951 case VisibilityAttr::DefaultVisibility:
952 case VisibilityAttr::ProtectedVisibility: // FIXME: What do we do here?
953 return false;
954 case VisibilityAttr::HiddenVisibility:
955 return true;
956 }
957 } else {
958 return false; // FIXME: Support -fvisibility
959 }
960}
961
962/*
963 struct _objc_class {
964 Class isa;
965 Class super_class;
966 const char *name;
967 long version;
968 long info;
969 long instance_size;
970 struct _objc_ivar_list *ivars;
971 struct _objc_method_list *methods;
972 struct _objc_cache *cache;
973 struct _objc_protocol_list *protocols;
974 // Objective-C 1.0 extensions (<rdr://4585769>)
975 const char *ivar_layout;
976 struct _objc_class_ext *ext;
977 };
978
979 See EmitClassExtension();
980 */
981void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
Daniel Dunbar8ede0052008-08-25 06:02:07 +0000982 DefinedSymbols.insert(ID->getIdentifier());
983
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000984 const char *ClassName = ID->getName();
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000985 // FIXME: Gross
986 ObjCInterfaceDecl *Interface =
987 const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
Daniel Dunbar67e778b2008-08-21 21:57:41 +0000988 llvm::Constant *Protocols =
989 EmitProtocolList(std::string("\01L_OBJC_CLASS_PROTOCOLS_") + ID->getName(),
990 Interface->protocol_begin(),
991 Interface->protocol_end());
Daniel Dunbarb050fa62008-08-21 04:36:09 +0000992 const llvm::Type *InterfaceTy =
993 CGM.getTypes().ConvertType(CGM.getContext().getObjCInterfaceType(Interface));
994 unsigned Flags = eClassFlags_Factory;
995 unsigned Size = CGM.getTargetData().getABITypeSize(InterfaceTy);
996
997 // FIXME: Set CXX-structors flag.
998 if (IsClassHidden(ID->getClassInterface()))
999 Flags |= eClassFlags_Hidden;
1000
Daniel Dunbar12996f52008-08-26 21:51:14 +00001001 std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
1002 for (ObjCImplementationDecl::instmeth_iterator i = ID->instmeth_begin(),
1003 e = ID->instmeth_end(); i != e; ++i) {
1004 // Instance methods should always be defined.
1005 InstanceMethods.push_back(GetMethodConstant(*i));
1006 }
1007 for (ObjCImplementationDecl::classmeth_iterator i = ID->classmeth_begin(),
1008 e = ID->classmeth_end(); i != e; ++i) {
1009 // Class methods should always be defined.
1010 ClassMethods.push_back(GetMethodConstant(*i));
1011 }
1012
1013 for (ObjCImplementationDecl::propimpl_iterator i = ID->propimpl_begin(),
1014 e = ID->propimpl_end(); i != e; ++i) {
1015 ObjCPropertyImplDecl *PID = *i;
1016
1017 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
1018 ObjCPropertyDecl *PD = PID->getPropertyDecl();
1019
1020 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
1021 if (llvm::Constant *C = GetMethodConstant(MD))
1022 InstanceMethods.push_back(C);
1023 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
1024 if (llvm::Constant *C = GetMethodConstant(MD))
1025 InstanceMethods.push_back(C);
1026 }
1027 }
1028
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001029 std::vector<llvm::Constant*> Values(12);
Daniel Dunbar12996f52008-08-26 21:51:14 +00001030 Values[ 0] = EmitMetaClass(ID, Protocols, InterfaceTy, ClassMethods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001031 if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001032 // Record a reference to the super class.
1033 LazySymbols.insert(Super->getIdentifier());
1034
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001035 Values[ 1] =
1036 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
1037 ObjCTypes.ClassPtrTy);
1038 } else {
1039 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
1040 }
1041 Values[ 2] = GetClassName(ID->getIdentifier());
1042 // Version is always 0.
1043 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
1044 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
1045 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
1046 Values[ 6] = EmitIvarList(ID, false, InterfaceTy);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001047 Values[ 7] =
1048 EmitMethodList(std::string("\01L_OBJC_INSTANCE_METHODS_") + ID->getName(),
1049 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +00001050 InstanceMethods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001051 // cache is always NULL.
1052 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
1053 Values[ 9] = Protocols;
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001054 // FIXME: Set ivar_layout
1055 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001056 Values[11] = EmitClassExtension(ID);
1057 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
1058 Values);
1059
1060 llvm::GlobalVariable *GV =
1061 new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1062 llvm::GlobalValue::InternalLinkage,
1063 Init,
1064 std::string("\01L_OBJC_CLASS_")+ClassName,
1065 &CGM.getModule());
1066 GV->setSection("__OBJC,__class,regular,no_dead_strip");
1067 UsedGlobals.push_back(GV);
1068 // FIXME: Why?
1069 GV->setAlignment(32);
1070 DefinedClasses.push_back(GV);
1071}
1072
1073llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
1074 llvm::Constant *Protocols,
Daniel Dunbar12996f52008-08-26 21:51:14 +00001075 const llvm::Type *InterfaceTy,
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001076 const ConstantVector &Methods) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001077 const char *ClassName = ID->getName();
1078 unsigned Flags = eClassFlags_Meta;
1079 unsigned Size = CGM.getTargetData().getABITypeSize(ObjCTypes.ClassTy);
1080
1081 if (IsClassHidden(ID->getClassInterface()))
1082 Flags |= eClassFlags_Hidden;
1083
1084 std::vector<llvm::Constant*> Values(12);
1085 // The isa for the metaclass is the root of the hierarchy.
1086 const ObjCInterfaceDecl *Root = ID->getClassInterface();
1087 while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
1088 Root = Super;
1089 Values[ 0] =
1090 llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
1091 ObjCTypes.ClassPtrTy);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001092 // The super class for the metaclass is emitted as the name of the
1093 // super class. The runtime fixes this up to point to the
1094 // *metaclass* for the super class.
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001095 if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
1096 Values[ 1] =
1097 llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
1098 ObjCTypes.ClassPtrTy);
1099 } else {
1100 Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
1101 }
1102 Values[ 2] = GetClassName(ID->getIdentifier());
1103 // Version is always 0.
1104 Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
1105 Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
1106 Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
1107 Values[ 6] = EmitIvarList(ID, true, InterfaceTy);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001108 Values[ 7] =
1109 EmitMethodList(std::string("\01L_OBJC_CLASS_METHODS_") + ID->getName(),
1110 "__OBJC,__inst_meth,regular,no_dead_strip",
Daniel Dunbar12996f52008-08-26 21:51:14 +00001111 Methods);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001112 // cache is always NULL.
1113 Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
1114 Values[ 9] = Protocols;
1115 // ivar_layout for metaclass is always NULL.
1116 Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
1117 // The class extension is always unused for metaclasses.
1118 Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
1119 llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
1120 Values);
1121
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001122 std::string Name("\01L_OBJC_METACLASS_");
1123 Name += ClassName;
1124
1125 // Check for a forward reference.
1126 llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
1127 if (GV) {
1128 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
1129 "Forward metaclass reference has incorrect type.");
1130 GV->setLinkage(llvm::GlobalValue::InternalLinkage);
1131 GV->setInitializer(Init);
1132 } else {
1133 GV = new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1134 llvm::GlobalValue::InternalLinkage,
1135 Init, Name,
1136 &CGM.getModule());
1137 }
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001138 GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
1139 UsedGlobals.push_back(GV);
1140 // FIXME: Why?
1141 GV->setAlignment(32);
1142
1143 return GV;
1144}
1145
Daniel Dunbarb1ee5d62008-08-25 08:19:24 +00001146llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
1147 std::string Name("\01L_OBJC_METACLASS_");
1148 Name += ID->getName();
1149
1150 // FIXME: Should we look these up somewhere other than the
1151 // module. Its a bit silly since we only generate these while
1152 // processing an implementation, so exactly one pointer would work
1153 // if know when we entered/exitted an implementation block.
1154
1155 // Check for an existing forward reference.
1156 if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name)) {
1157 assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
1158 "Forward metaclass reference has incorrect type.");
1159 return GV;
1160 } else {
1161 // Generate as an external reference to keep a consistent
1162 // module. This will be patched up when we emit the metaclass.
1163 return new llvm::GlobalVariable(ObjCTypes.ClassTy, false,
1164 llvm::GlobalValue::ExternalLinkage,
1165 0,
1166 Name,
1167 &CGM.getModule());
1168 }
1169}
1170
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001171/*
1172 struct objc_class_ext {
1173 uint32_t size;
1174 const char *weak_ivar_layout;
1175 struct _objc_property_list *properties;
1176 };
1177*/
1178llvm::Constant *
1179CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
1180 uint64_t Size =
1181 CGM.getTargetData().getABITypeSize(ObjCTypes.ClassExtensionTy);
1182
1183 std::vector<llvm::Constant*> Values(3);
1184 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001185 // FIXME: Output weak_ivar_layout string.
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001186 Values[1] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001187 Values[2] = EmitPropertyList(std::string("\01L_OBJC_$_PROP_LIST_") +
1188 ID->getName(),
Daniel Dunbar698d6f32008-08-28 04:38:10 +00001189 ID,
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001190 ID->getClassInterface()->classprop_begin(),
1191 ID->getClassInterface()->classprop_end());
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001192
1193 // Return null if no extension bits are used.
1194 if (Values[1]->isNullValue() && Values[2]->isNullValue())
1195 return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
1196
1197 llvm::Constant *Init =
1198 llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
1199 llvm::GlobalVariable *GV =
1200 new llvm::GlobalVariable(ObjCTypes.ClassExtensionTy, false,
1201 llvm::GlobalValue::InternalLinkage,
1202 Init,
1203 (std::string("\01L_OBJC_CLASSEXT_") +
1204 ID->getName()),
1205 &CGM.getModule());
1206 // No special section, but goes in llvm.used
1207 UsedGlobals.push_back(GV);
1208
1209 return GV;
1210}
1211
1212/*
1213 struct objc_ivar {
1214 char *ivar_name;
1215 char *ivar_type;
1216 int ivar_offset;
1217 };
1218
1219 struct objc_ivar_list {
1220 int ivar_count;
1221 struct objc_ivar list[count];
1222 };
1223 */
1224llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
1225 bool ForClass,
1226 const llvm::Type *InterfaceTy) {
1227 std::vector<llvm::Constant*> Ivars, Ivar(3);
1228
1229 // When emitting the root class GCC emits ivar entries for the
1230 // actual class structure. It is not clear if we need to follow this
1231 // behavior; for now lets try and get away with not doing it. If so,
1232 // the cleanest solution would be to make up an ObjCInterfaceDecl
1233 // for the class.
1234 if (ForClass)
1235 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
1236
1237 const llvm::StructLayout *Layout =
1238 CGM.getTargetData().getStructLayout(cast<llvm::StructType>(InterfaceTy));
1239 for (ObjCInterfaceDecl::ivar_iterator
1240 i = ID->getClassInterface()->ivar_begin(),
1241 e = ID->getClassInterface()->ivar_end(); i != e; ++i) {
1242 ObjCIvarDecl *V = *i;
1243 unsigned Offset =
1244 Layout->getElementOffset(CGM.getTypes().getLLVMFieldNo(V));
1245 std::string TypeStr;
1246 llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes;
1247 Ivar[0] = GetMethodVarName(V->getIdentifier());
1248 CGM.getContext().getObjCEncodingForType(V->getType(), TypeStr,
1249 EncodingRecordTypes);
1250 Ivar[1] = GetMethodVarType(TypeStr);
1251 Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy, Offset);
1252 Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy,
1253 Ivar));
1254 }
1255
1256 // Return null for empty list.
1257 if (Ivars.empty())
1258 return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
1259
1260 std::vector<llvm::Constant*> Values(2);
1261 Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
1262 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
1263 Ivars.size());
1264 Values[1] = llvm::ConstantArray::get(AT, Ivars);
1265 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1266
1267 const char *Prefix = (ForClass ? "\01L_OBJC_CLASS_VARIABLES_" :
1268 "\01L_OBJC_INSTANCE_VARIABLES_");
1269 llvm::GlobalVariable *GV =
1270 new llvm::GlobalVariable(Init->getType(), false,
1271 llvm::GlobalValue::InternalLinkage,
1272 Init,
1273 std::string(Prefix) + ID->getName(),
1274 &CGM.getModule());
1275 if (ForClass) {
1276 GV->setSection("__OBJC,__cls_vars,regular,no_dead_strip");
1277 // FIXME: Why is this only here?
1278 GV->setAlignment(32);
1279 } else {
1280 GV->setSection("__OBJC,__instance_vars,regular,no_dead_strip");
1281 }
1282 UsedGlobals.push_back(GV);
1283 return llvm::ConstantExpr::getBitCast(GV,
1284 ObjCTypes.IvarListPtrTy);
1285}
1286
1287/*
1288 struct objc_method {
1289 SEL method_name;
1290 char *method_types;
1291 void *method;
1292 };
1293
1294 struct objc_method_list {
1295 struct objc_method_list *obsolete;
1296 int count;
1297 struct objc_method methods_list[count];
1298 };
1299*/
Daniel Dunbar12996f52008-08-26 21:51:14 +00001300
1301/// GetMethodConstant - Return a struct objc_method constant for the
1302/// given method if it has been defined. The result is null if the
1303/// method has not been defined. The return value has type MethodPtrTy.
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001304llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
Daniel Dunbar12996f52008-08-26 21:51:14 +00001305 // FIXME: Use DenseMap::lookup
1306 llvm::Function *Fn = MethodDefinitions[MD];
1307 if (!Fn)
1308 return 0;
1309
1310 std::vector<llvm::Constant*> Method(3);
1311 Method[0] =
1312 llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
1313 ObjCTypes.SelectorPtrTy);
1314 Method[1] = GetMethodVarType(MD);
1315 Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
1316 return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
1317}
1318
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001319llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,
1320 const char *Section,
Daniel Dunbarfe131f02008-08-27 02:31:56 +00001321 const ConstantVector &Methods) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001322 // Return null for empty list.
1323 if (Methods.empty())
1324 return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
1325
1326 std::vector<llvm::Constant*> Values(3);
1327 Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
1328 Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
1329 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
1330 Methods.size());
1331 Values[2] = llvm::ConstantArray::get(AT, Methods);
1332 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1333
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001334 llvm::GlobalVariable *GV =
1335 new llvm::GlobalVariable(Init->getType(), false,
1336 llvm::GlobalValue::InternalLinkage,
1337 Init,
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001338 Name,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001339 &CGM.getModule());
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001340 GV->setSection(Section);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001341 UsedGlobals.push_back(GV);
1342 return llvm::ConstantExpr::getBitCast(GV,
1343 ObjCTypes.MethodListPtrTy);
Daniel Dunbarace33292008-08-16 03:19:19 +00001344}
1345
1346llvm::Function *CGObjCMac::GenerateMethod(const ObjCMethodDecl *OMD) {
1347 const llvm::Type *ReturnTy =
1348 CGM.getTypes().ConvertReturnType(OMD->getResultType());
1349 const llvm::Type *SelfTy =
1350 CGM.getTypes().ConvertType(OMD->getSelfDecl()->getType());
1351
1352 std::vector<const llvm::Type*> ArgTys;
1353 ArgTys.reserve(1 + 2 + OMD->param_size());
1354
1355 // FIXME: This is not something we should have to be dealing with
1356 // here.
1357 bool useStructRet =
1358 CodeGen::CodeGenFunction::hasAggregateLLVMType(OMD->getResultType());
1359 if (useStructRet) {
1360 ArgTys.push_back(llvm::PointerType::getUnqual(ReturnTy));
1361 ReturnTy = llvm::Type::VoidTy;
1362 }
1363
1364 // Implicit arguments
1365 ArgTys.push_back(SelfTy);
1366 ArgTys.push_back(ObjCTypes.SelectorPtrTy);
1367
1368 for (ObjCMethodDecl::param_const_iterator
1369 i = OMD->param_begin(), e = OMD->param_end();
1370 i != e; ++i) {
1371 const llvm::Type *Ty = CGM.getTypes().ConvertType((*i)->getType());
Daniel Dunbara04840b2008-08-23 03:46:30 +00001372 if (Ty->isSingleValueType()) {
Daniel Dunbarace33292008-08-16 03:19:19 +00001373 ArgTys.push_back(Ty);
1374 } else {
1375 ArgTys.push_back(llvm::PointerType::getUnqual(Ty));
1376 }
1377 }
1378
1379 std::string Name;
1380 GetNameForMethod(OMD, Name);
1381
1382 llvm::Function *Method =
1383 llvm::Function::Create(llvm::FunctionType::get(ReturnTy,
1384 ArgTys,
1385 OMD->isVariadic()),
1386 llvm::GlobalValue::InternalLinkage,
1387 Name,
1388 &CGM.getModule());
Daniel Dunbar12996f52008-08-26 21:51:14 +00001389 MethodDefinitions.insert(std::make_pair(OMD, Method));
Daniel Dunbarace33292008-08-16 03:19:19 +00001390
Daniel Dunbara04840b2008-08-23 03:46:30 +00001391 unsigned Offset = 3; // Return plus self and selector implicit args.
1392 if (useStructRet) {
Daniel Dunbarace33292008-08-16 03:19:19 +00001393 Method->addParamAttr(1, llvm::ParamAttr::StructRet);
Daniel Dunbara04840b2008-08-23 03:46:30 +00001394 ++Offset;
1395 }
1396
1397 // FIXME: This is horrible, we need to be reusing the machinery in
1398 // CodeGenModule.cpp (SetFunctionAttributes).
1399 for (ObjCMethodDecl::param_const_iterator
1400 i = OMD->param_begin(), e = OMD->param_end();
1401 i != e; ++i, ++Offset) {
1402 const llvm::Type *Ty = CGM.getTypes().ConvertType((*i)->getType());
1403 if (!Ty->isSingleValueType())
1404 Method->addParamAttr(Offset, llvm::ParamAttr::ByVal);
1405 }
Daniel Dunbarace33292008-08-16 03:19:19 +00001406
1407 return Method;
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001408}
1409
1410llvm::Function *CGObjCMac::ModuleInitFunction() {
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001411 // Abuse this interface function as a place to finalize.
1412 FinishModule();
1413
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00001414 return NULL;
1415}
1416
Anders Carlsson58d16242008-08-31 04:05:03 +00001417llvm::Function *CGObjCMac::EnumerationMutationFunction()
1418{
1419 return ObjCTypes.EnumerationMutationFn;
1420}
1421
Anders Carlssonb01a2112008-09-09 10:04:29 +00001422void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
1423 const ObjCAtTryStmt &S)
1424{
Anders Carlssonfca6c292008-09-09 17:59:25 +00001425 // Allocate exception data.
1426 llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
1427 "exceptiondata.ptr");
1428
1429 // Allocate memory for the rethrow pointer.
1430 llvm::Value *RethrowPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy);
1431 CGF.Builder.CreateStore(llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy),
1432 RethrowPtr);
1433
1434 // Enter a new try block and call setjmp.
1435 CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
1436 llvm::Value *JmpBufPtr = CGF.Builder.CreateStructGEP(ExceptionData, 0,
1437 "jmpbufarray");
1438 JmpBufPtr = CGF.Builder.CreateStructGEP(JmpBufPtr, 0, "tmp");
1439 llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn,
1440 JmpBufPtr, "result");
1441
1442
1443 llvm::BasicBlock *FinallyBlock = llvm::BasicBlock::Create("finally");
1444
1445 llvm::BasicBlock *TryBlock = llvm::BasicBlock::Create("try");
1446 llvm::BasicBlock *ExceptionInTryBlock =
1447 llvm::BasicBlock::Create("exceptionintry");
1448
1449 // If setjmp returns 1, there was an exception in the @try block.
1450 llvm::Value *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
1451 llvm::Value *IsZero = CGF.Builder.CreateICmpEQ(SetJmpResult, Zero, "iszero");
1452 CGF.Builder.CreateCondBr(IsZero, TryBlock, ExceptionInTryBlock);
1453
1454 // Emit the @try block.
1455 CGF.EmitBlock(TryBlock);
1456 CGF.EmitStmt(S.getTryBody());
1457 CGF.Builder.CreateBr(FinallyBlock);
1458
1459 // Emit the "exception in @try" block.
1460 CGF.EmitBlock(ExceptionInTryBlock);
1461
1462 if (const ObjCAtCatchStmt* CatchStmt = S.getCatchStmts()) {
1463 // Allocate memory for the caught exception and extract it from the
1464 // exception data.
1465 llvm::Value *CaughtPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy);
1466 llvm::Value *Extract = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
1467 ExceptionData);
1468 CGF.Builder.CreateStore(Extract, CaughtPtr);
1469
1470 // Enter a new exception try block
1471 // (in case a @catch block throws an exception).
1472 CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
1473
1474 llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn,
1475 JmpBufPtr, "result");
1476
1477
1478 llvm::Value *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
1479 llvm::Value *IsZero = CGF.Builder.CreateICmpEQ(SetJmpResult, Zero,
1480 "iszero");
1481
1482 llvm::BasicBlock *CatchBlock = llvm::BasicBlock::Create("catch");
1483 llvm::BasicBlock *ExceptionInCatchBlock =
1484 llvm::BasicBlock::Create("exceptionincatch");
1485 CGF.Builder.CreateCondBr(IsZero, CatchBlock, ExceptionInCatchBlock);
1486
1487 CGF.EmitBlock(CatchBlock);
1488
1489 // Handle catch list
1490 for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
1491 llvm::BasicBlock *NextCatchBlock = llvm::BasicBlock::Create("nextcatch");
1492
1493 QualType T;
1494 bool MatchesAll = false;
1495
1496 // catch(...) always matches.
1497 if (CatchStmt->hasEllipsis())
1498 MatchesAll = true;
1499 else {
1500 const DeclStmt *DS = cast<DeclStmt>(CatchStmt->getCatchParamStmt());
1501 QualType PT = cast<ValueDecl>(DS->getDecl())->getType();
1502 T = PT->getAsPointerType()->getPointeeType();
1503
1504 // catch(id e) always matches.
1505 if (CGF.getContext().isObjCIdType(T))
1506 MatchesAll = true;
1507 }
1508
1509 if (MatchesAll) {
1510 CGF.EmitStmt(CatchStmt->getCatchBody());
1511 CGF.Builder.CreateBr(FinallyBlock);
1512
1513 CGF.EmitBlock(NextCatchBlock);
1514 break;
1515 }
1516
1517 const ObjCInterfaceType *ObjCType = T->getAsPointerToObjCInterfaceType();
1518 assert(ObjCType && "Catch parameter must have Objective-C type!");
1519
1520 // Check if the @catch block matches the exception object.
1521 llvm::Value *Class = EmitClassRef(CGF.Builder, ObjCType->getDecl());
1522
1523 llvm::Value *Caught = CGF.Builder.CreateLoad(CaughtPtr, "caught");
1524 llvm::Value *Match = CGF.Builder.CreateCall2(ObjCTypes.ExceptionMatchFn,
1525 Class, Caught, "match");
1526
1527 llvm::Value *DidMatch = CGF.Builder.CreateICmpNE(Match, Zero, "iszero");
1528
1529 llvm::BasicBlock *MatchedBlock = llvm::BasicBlock::Create("matched");
1530
1531 CGF.Builder.CreateCondBr(DidMatch, MatchedBlock, NextCatchBlock);
1532
1533 // Emit the @catch block.
1534 CGF.EmitBlock(MatchedBlock);
1535 CGF.EmitStmt(CatchStmt->getCatchBody());
1536 CGF.Builder.CreateBr(FinallyBlock);
1537
1538 CGF.EmitBlock(NextCatchBlock);
1539 }
1540
1541 // None of the handlers caught the exception, so store it and rethrow
1542 // it later.
1543 llvm::Value *Caught = CGF.Builder.CreateLoad(CaughtPtr, "caught");
1544 CGF.Builder.CreateStore(Caught, RethrowPtr);
1545 CGF.Builder.CreateCall(ObjCTypes.ExceptionTryExitFn,
1546 ExceptionData);
1547
1548 CGF.Builder.CreateBr(FinallyBlock);
1549
1550 CGF.EmitBlock(ExceptionInCatchBlock);
1551
1552 Extract = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
1553 ExceptionData);
1554 CGF.Builder.CreateStore(Extract, RethrowPtr);
1555 }
1556
1557 // Emit the @finally block.
1558 CGF.EmitBlock(FinallyBlock);
1559
1560 llvm::Value *Rethrow = CGF.Builder.CreateLoad(RethrowPtr);
1561 llvm::Value *ZeroPtr = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
1562
1563 llvm::Value *RethrowIsZero = CGF.Builder.CreateICmpEQ(Rethrow, ZeroPtr);
1564
1565 llvm::BasicBlock *TryExitBlock = llvm::BasicBlock::Create("tryexit");
1566 llvm::BasicBlock *AfterTryExitBlock =
1567 llvm::BasicBlock::Create("aftertryexit");
1568
1569 CGF.Builder.CreateCondBr(RethrowIsZero, TryExitBlock, AfterTryExitBlock);
1570 CGF.EmitBlock(TryExitBlock);
1571 CGF.Builder.CreateCall(ObjCTypes.ExceptionTryExitFn, ExceptionData);
1572 CGF.EmitBlock(AfterTryExitBlock);
1573
1574 if (const ObjCAtFinallyStmt* FinallyStmt = S.getFinallyStmt())
1575 CGF.EmitStmt(FinallyStmt->getFinallyBody());
1576
1577 llvm::Value *RethrowIsNotZero = CGF.Builder.CreateICmpNE(Rethrow, ZeroPtr);
1578
1579 llvm::BasicBlock *RethrowBlock = llvm::BasicBlock::Create("rethrow");
1580 llvm::BasicBlock *FinallyEndBlock = llvm::BasicBlock::Create("finallyend");
1581
1582 // If necessary, rethrow the exception.
1583 CGF.Builder.CreateCondBr(RethrowIsNotZero, RethrowBlock, FinallyEndBlock);
1584 CGF.EmitBlock(RethrowBlock);
1585 CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn, Rethrow);
1586 CGF.EmitBlock(FinallyEndBlock);
Anders Carlssonb01a2112008-09-09 10:04:29 +00001587}
1588
1589void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
1590 const ObjCAtThrowStmt &S)
1591{
Anders Carlsson05d7be72008-09-09 16:16:55 +00001592 llvm::Value *ExceptionAsObject;
1593
1594 if (const Expr *ThrowExpr = S.getThrowExpr()) {
1595 llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
1596 ExceptionAsObject =
1597 CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
1598 } else {
1599 assert(0 && "FIXME: rethrows not supported!");
1600 }
1601
1602 CGF.Builder.CreateCall(ObjCTypes.ExceptionThrowFn, ExceptionAsObject);
Anders Carlssonfca6c292008-09-09 17:59:25 +00001603 CGF.Builder.CreateUnreachable();
1604 CGF.EmitBlock(llvm::BasicBlock::Create("bb"));
Anders Carlssonb01a2112008-09-09 10:04:29 +00001605}
1606
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001607/* *** Private Interface *** */
1608
1609/// EmitImageInfo - Emit the image info marker used to encode some module
1610/// level information.
1611///
1612/// See: <rdr://4810609&4810587&4810587>
1613/// struct IMAGE_INFO {
1614/// unsigned version;
1615/// unsigned flags;
1616/// };
1617enum ImageInfoFlags {
1618 eImageInfo_FixAndContinue = (1 << 0), // FIXME: Not sure what this implies
1619 eImageInfo_GarbageCollected = (1 << 1),
1620 eImageInfo_GCOnly = (1 << 2)
1621};
1622
1623void CGObjCMac::EmitImageInfo() {
1624 unsigned version = 0; // Version is unused?
1625 unsigned flags = 0;
1626
1627 // FIXME: Fix and continue?
1628 if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
1629 flags |= eImageInfo_GarbageCollected;
1630 if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
1631 flags |= eImageInfo_GCOnly;
1632
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001633 // Emitted as int[2];
1634 llvm::Constant *values[2] = {
1635 llvm::ConstantInt::get(llvm::Type::Int32Ty, version),
1636 llvm::ConstantInt::get(llvm::Type::Int32Ty, flags)
1637 };
1638 llvm::ArrayType *AT = llvm::ArrayType::get(llvm::Type::Int32Ty, 2);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001639 llvm::GlobalVariable *GV =
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001640 new llvm::GlobalVariable(AT, true,
1641 llvm::GlobalValue::InternalLinkage,
1642 llvm::ConstantArray::get(AT, values, 2),
1643 "\01L_OBJC_IMAGE_INFO",
1644 &CGM.getModule());
1645
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00001646 if (ObjCABI == 1) {
1647 GV->setSection("__OBJC, __image_info,regular");
1648 } else {
1649 GV->setSection("__DATA, __objc_imageinfo, regular, no_dead_strip");
1650 }
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001651
1652 UsedGlobals.push_back(GV);
1653}
1654
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001655
1656// struct objc_module {
1657// unsigned long version;
1658// unsigned long size;
1659// const char *name;
1660// Symtab symtab;
1661// };
1662
1663// FIXME: Get from somewhere
1664static const int ModuleVersion = 7;
1665
1666void CGObjCMac::EmitModuleInfo() {
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001667 uint64_t Size = CGM.getTargetData().getABITypeSize(ObjCTypes.ModuleTy);
1668
1669 std::vector<llvm::Constant*> Values(4);
1670 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
1671 Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
Daniel Dunbarac93e472008-08-15 22:20:32 +00001672 // This used to be the filename, now it is unused. <rdr://4327263>
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001673 Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001674 Values[3] = EmitModuleSymbols();
1675
1676 llvm::GlobalVariable *GV =
1677 new llvm::GlobalVariable(ObjCTypes.ModuleTy, false,
1678 llvm::GlobalValue::InternalLinkage,
1679 llvm::ConstantStruct::get(ObjCTypes.ModuleTy,
1680 Values),
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001681 "\01L_OBJC_MODULES",
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001682 &CGM.getModule());
1683 GV->setSection("__OBJC,__module_info,regular,no_dead_strip");
1684 UsedGlobals.push_back(GV);
1685}
1686
1687llvm::Constant *CGObjCMac::EmitModuleSymbols() {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001688 unsigned NumClasses = DefinedClasses.size();
1689 unsigned NumCategories = DefinedCategories.size();
1690
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001691 // Return null if no symbols were defined.
1692 if (!NumClasses && !NumCategories)
1693 return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
1694
1695 std::vector<llvm::Constant*> Values(5);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001696 Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
1697 Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
1698 Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
1699 Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
1700
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001701 // The runtime expects exactly the list of defined classes followed
1702 // by the list of defined categories, in a single array.
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001703 std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001704 for (unsigned i=0; i<NumClasses; i++)
1705 Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
1706 ObjCTypes.Int8PtrTy);
1707 for (unsigned i=0; i<NumCategories; i++)
1708 Symbols[NumClasses + i] =
1709 llvm::ConstantExpr::getBitCast(DefinedCategories[i],
1710 ObjCTypes.Int8PtrTy);
1711
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001712 Values[4] =
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00001713 llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001714 NumClasses + NumCategories),
1715 Symbols);
1716
1717 llvm::Constant *Init = llvm::ConstantStruct::get(Values);
1718
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001719 llvm::GlobalVariable *GV =
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001720 new llvm::GlobalVariable(Init->getType(), false,
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001721 llvm::GlobalValue::InternalLinkage,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001722 Init,
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001723 "\01L_OBJC_SYMBOLS",
1724 &CGM.getModule());
1725 GV->setSection("__OBJC,__symbols,regular,no_dead_strip");
1726 UsedGlobals.push_back(GV);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001727 return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
1728}
1729
1730llvm::Value *CGObjCMac::EmitClassRef(llvm::IRBuilder<> &Builder,
1731 const ObjCInterfaceDecl *ID) {
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001732 LazySymbols.insert(ID->getIdentifier());
1733
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001734 llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
1735
1736 if (!Entry) {
1737 llvm::Constant *Casted =
1738 llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
1739 ObjCTypes.ClassPtrTy);
1740 Entry =
1741 new llvm::GlobalVariable(ObjCTypes.ClassPtrTy, false,
1742 llvm::GlobalValue::InternalLinkage,
1743 Casted, "\01L_OBJC_CLASS_REFERENCES_",
1744 &CGM.getModule());
1745 Entry->setSection("__OBJC,__cls_refs,literal_pointers,no_dead_strip");
1746 UsedGlobals.push_back(Entry);
1747 }
1748
1749 return Builder.CreateLoad(Entry, false, "tmp");
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001750}
1751
Daniel Dunbar5eec6142008-08-12 03:39:23 +00001752llvm::Value *CGObjCMac::EmitSelector(llvm::IRBuilder<> &Builder, Selector Sel) {
1753 llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
1754
1755 if (!Entry) {
1756 llvm::Constant *Casted =
1757 llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
1758 ObjCTypes.SelectorPtrTy);
1759 Entry =
1760 new llvm::GlobalVariable(ObjCTypes.SelectorPtrTy, false,
1761 llvm::GlobalValue::InternalLinkage,
1762 Casted, "\01L_OBJC_SELECTOR_REFERENCES_",
1763 &CGM.getModule());
1764 Entry->setSection("__OBJC,__message_refs,literal_pointers,no_dead_strip");
1765 UsedGlobals.push_back(Entry);
1766 }
1767
1768 return Builder.CreateLoad(Entry, false, "tmp");
1769}
1770
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001771llvm::Constant *CGObjCMac::GetClassName(IdentifierInfo *Ident) {
1772 llvm::GlobalVariable *&Entry = ClassNames[Ident];
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001773
1774 if (!Entry) {
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001775 llvm::Constant *C = llvm::ConstantArray::get(Ident->getName());
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001776 Entry =
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001777 new llvm::GlobalVariable(C->getType(), false,
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001778 llvm::GlobalValue::InternalLinkage,
1779 C, "\01L_OBJC_CLASS_NAME_",
1780 &CGM.getModule());
1781 Entry->setSection("__TEXT,__cstring,cstring_literals");
1782 UsedGlobals.push_back(Entry);
1783 }
1784
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001785 return getConstantGEP(Entry, 0, 0);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001786}
1787
Daniel Dunbar5eec6142008-08-12 03:39:23 +00001788llvm::Constant *CGObjCMac::GetMethodVarName(Selector Sel) {
1789 llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
1790
1791 if (!Entry) {
1792 llvm::Constant *C = llvm::ConstantArray::get(Sel.getName());
1793 Entry =
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001794 new llvm::GlobalVariable(C->getType(), false,
Daniel Dunbar5eec6142008-08-12 03:39:23 +00001795 llvm::GlobalValue::InternalLinkage,
1796 C, "\01L_OBJC_METH_VAR_NAME_",
1797 &CGM.getModule());
1798 Entry->setSection("__TEXT,__cstring,cstring_literals");
1799 UsedGlobals.push_back(Entry);
1800 }
1801
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001802 return getConstantGEP(Entry, 0, 0);
1803}
1804
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001805// FIXME: Merge into a single cstring creation function.
1806llvm::Constant *CGObjCMac::GetMethodVarName(IdentifierInfo *ID) {
1807 return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
1808}
1809
1810// FIXME: Merge into a single cstring creation function.
1811llvm::Constant *CGObjCMac::GetMethodVarName(const std::string &Name) {
1812 return GetMethodVarName(&CGM.getContext().Idents.get(Name));
1813}
1814
1815llvm::Constant *CGObjCMac::GetMethodVarType(const std::string &Name) {
1816 llvm::GlobalVariable *&Entry = MethodVarTypes[Name];
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001817
1818 if (!Entry) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001819 llvm::Constant *C = llvm::ConstantArray::get(Name);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001820 Entry =
1821 new llvm::GlobalVariable(C->getType(), false,
1822 llvm::GlobalValue::InternalLinkage,
1823 C, "\01L_OBJC_METH_VAR_TYPE_",
1824 &CGM.getModule());
1825 Entry->setSection("__TEXT,__cstring,cstring_literals");
1826 UsedGlobals.push_back(Entry);
1827 }
1828
1829 return getConstantGEP(Entry, 0, 0);
Daniel Dunbar5eec6142008-08-12 03:39:23 +00001830}
1831
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001832// FIXME: Merge into a single cstring creation function.
Daniel Dunbar12996f52008-08-26 21:51:14 +00001833llvm::Constant *CGObjCMac::GetMethodVarType(const ObjCMethodDecl *D) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001834 std::string TypeStr;
Daniel Dunbar12996f52008-08-26 21:51:14 +00001835 CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
1836 TypeStr);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001837 return GetMethodVarType(TypeStr);
1838}
1839
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001840// FIXME: Merge into a single cstring creation function.
1841llvm::Constant *CGObjCMac::GetPropertyName(IdentifierInfo *Ident) {
1842 llvm::GlobalVariable *&Entry = PropertyNames[Ident];
1843
1844 if (!Entry) {
1845 llvm::Constant *C = llvm::ConstantArray::get(Ident->getName());
1846 Entry =
1847 new llvm::GlobalVariable(C->getType(), false,
1848 llvm::GlobalValue::InternalLinkage,
1849 C, "\01L_OBJC_PROP_NAME_ATTR_",
1850 &CGM.getModule());
1851 Entry->setSection("__TEXT,__cstring,cstring_literals");
1852 UsedGlobals.push_back(Entry);
1853 }
1854
1855 return getConstantGEP(Entry, 0, 0);
1856}
1857
1858// FIXME: Merge into a single cstring creation function.
Daniel Dunbar698d6f32008-08-28 04:38:10 +00001859// FIXME: This Decl should be more precise.
1860llvm::Constant *CGObjCMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
1861 const Decl *Container) {
1862 std::string TypeStr;
1863 CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001864 return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
1865}
1866
Daniel Dunbarace33292008-08-16 03:19:19 +00001867void CGObjCMac::GetNameForMethod(const ObjCMethodDecl *D,
1868 std::string &NameOut) {
1869 // FIXME: Find the mangling GCC uses.
1870 std::stringstream s;
1871 s << (D->isInstance() ? "-" : "+");
1872 s << "[";
1873 s << D->getClassInterface()->getName();
1874 s << " ";
1875 s << D->getSelector().getName();
1876 s << "]";
1877 NameOut = s.str();
1878}
1879
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001880void CGObjCMac::FinishModule() {
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001881 EmitModuleInfo();
1882
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001883 std::vector<llvm::Constant*> Used;
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001884
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001885 for (std::vector<llvm::GlobalVariable*>::iterator i = UsedGlobals.begin(),
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001886 e = UsedGlobals.end(); i != e; ++i) {
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001887 Used.push_back(llvm::ConstantExpr::getBitCast(*i, ObjCTypes.Int8PtrTy));
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001888 }
1889
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001890 llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Used.size());
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001891 llvm::GlobalValue *GV =
1892 new llvm::GlobalVariable(AT, false,
1893 llvm::GlobalValue::AppendingLinkage,
1894 llvm::ConstantArray::get(AT, Used),
1895 "llvm.used",
1896 &CGM.getModule());
1897
1898 GV->setSection("llvm.metadata");
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001899
1900 // Add assembler directives to add lazy undefined symbol references
1901 // for classes which are referenced but not defined. This is
1902 // important for correct linker interaction.
1903
1904 // FIXME: Uh, this isn't particularly portable.
1905 std::stringstream s;
1906 for (std::set<IdentifierInfo*>::iterator i = LazySymbols.begin(),
1907 e = LazySymbols.end(); i != e; ++i) {
1908 s << "\t.lazy_reference .objc_class_name_" << (*i)->getName() << "\n";
1909 }
1910 for (std::set<IdentifierInfo*>::iterator i = DefinedSymbols.begin(),
1911 e = DefinedSymbols.end(); i != e; ++i) {
Daniel Dunbar698d6f32008-08-28 04:38:10 +00001912 s << "\t.objc_class_name_" << (*i)->getName() << "=0\n"
Daniel Dunbar8ede0052008-08-25 06:02:07 +00001913 << "\t.globl .objc_class_name_" << (*i)->getName() << "\n";
1914 }
1915 CGM.getModule().appendModuleInlineAsm(s.str());
Daniel Dunbar1be1df32008-08-11 21:35:06 +00001916}
1917
1918/* *** */
1919
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00001920ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
Daniel Dunbardbdb9512008-08-23 18:37:06 +00001921 : CGM(cgm)
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00001922{
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001923 CodeGen::CodeGenTypes &Types = CGM.getTypes();
1924 ASTContext &Ctx = CGM.getContext();
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001925
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001926 ShortTy = Types.ConvertType(Ctx.ShortTy);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001927 IntTy = Types.ConvertType(Ctx.IntTy);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001928 LongTy = Types.ConvertType(Ctx.LongTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001929 Int8PtrTy = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
1930
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001931 ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
1932 SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001933
1934 // FIXME: It would be nice to unify this with the opaque type, so
1935 // that the IR comes out a bit cleaner.
1936 const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
1937 ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
Daniel Dunbarb8fe21b2008-08-12 06:48:42 +00001938
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001939 MethodDescriptionTy =
1940 llvm::StructType::get(SelectorPtrTy,
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001941 Int8PtrTy,
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001942 NULL);
1943 CGM.getModule().addTypeName("struct._objc_method_description",
1944 MethodDescriptionTy);
1945
1946 MethodDescriptionListTy =
1947 llvm::StructType::get(IntTy,
1948 llvm::ArrayType::get(MethodDescriptionTy, 0),
1949 NULL);
1950 CGM.getModule().addTypeName("struct._objc_method_description_list",
1951 MethodDescriptionListTy);
1952 MethodDescriptionListPtrTy =
1953 llvm::PointerType::getUnqual(MethodDescriptionListTy);
1954
Daniel Dunbara6eb6b72008-08-23 00:19:03 +00001955 PropertyTy = llvm::StructType::get(Int8PtrTy,
1956 Int8PtrTy,
1957 NULL);
1958 CGM.getModule().addTypeName("struct._objc_property",
1959 PropertyTy);
1960
1961 PropertyListTy = llvm::StructType::get(IntTy,
1962 IntTy,
1963 llvm::ArrayType::get(PropertyTy, 0),
1964 NULL);
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001965 CGM.getModule().addTypeName("struct._objc_property_list",
1966 PropertyListTy);
1967 PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
1968
1969 // Protocol description structures
1970
1971 ProtocolExtensionTy =
1972 llvm::StructType::get(Types.ConvertType(Ctx.IntTy),
1973 llvm::PointerType::getUnqual(MethodDescriptionListTy),
1974 llvm::PointerType::getUnqual(MethodDescriptionListTy),
1975 PropertyListPtrTy,
1976 NULL);
1977 CGM.getModule().addTypeName("struct._objc_protocol_extension",
1978 ProtocolExtensionTy);
1979 ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
1980
1981 // Handle recursive construction of Protocl and ProtocolList types
1982
1983 llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get();
1984 llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get();
1985
1986 T = llvm::StructType::get(llvm::PointerType::getUnqual(ProtocolListTyHolder),
1987 LongTy,
1988 llvm::ArrayType::get(ProtocolTyHolder, 0),
1989 NULL);
1990 cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
1991
1992 T = llvm::StructType::get(llvm::PointerType::getUnqual(ProtocolExtensionTy),
Daniel Dunbarb050fa62008-08-21 04:36:09 +00001993 Int8PtrTy,
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00001994 llvm::PointerType::getUnqual(ProtocolListTyHolder),
1995 MethodDescriptionListPtrTy,
1996 MethodDescriptionListPtrTy,
1997 NULL);
1998 cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
1999
2000 ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
2001 CGM.getModule().addTypeName("struct._objc_protocol_list",
2002 ProtocolListTy);
2003 ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
2004
2005 ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
2006 CGM.getModule().addTypeName("struct.__objc_protocol", ProtocolTy);
2007 ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002008
2009 // Class description structures
2010
2011 IvarTy = llvm::StructType::get(Int8PtrTy,
2012 Int8PtrTy,
2013 IntTy,
2014 NULL);
2015 CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
2016
2017 IvarListTy = llvm::OpaqueType::get();
2018 CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
2019 IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
2020
2021 MethodTy = llvm::StructType::get(SelectorPtrTy,
2022 Int8PtrTy,
2023 Int8PtrTy,
2024 NULL);
2025 CGM.getModule().addTypeName("struct._objc_method", MethodTy);
2026
2027 MethodListTy = llvm::OpaqueType::get();
2028 CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
2029 MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
2030
2031 CacheTy = llvm::OpaqueType::get();
2032 CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
2033 CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
2034
2035 ClassExtensionTy =
2036 llvm::StructType::get(IntTy,
2037 Int8PtrTy,
2038 PropertyListPtrTy,
2039 NULL);
2040 CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
2041 ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
2042
2043 llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get();
2044
2045 T = llvm::StructType::get(llvm::PointerType::getUnqual(ClassTyHolder),
2046 llvm::PointerType::getUnqual(ClassTyHolder),
2047 Int8PtrTy,
2048 LongTy,
2049 LongTy,
2050 LongTy,
2051 IvarListPtrTy,
2052 MethodListPtrTy,
2053 CachePtrTy,
2054 ProtocolListPtrTy,
2055 Int8PtrTy,
2056 ClassExtensionPtrTy,
2057 NULL);
2058 cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
2059
2060 ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
2061 CGM.getModule().addTypeName("struct._objc_class", ClassTy);
2062 ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
2063
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00002064 CategoryTy = llvm::StructType::get(Int8PtrTy,
2065 Int8PtrTy,
2066 MethodListPtrTy,
2067 MethodListPtrTy,
2068 ProtocolListPtrTy,
2069 IntTy,
2070 PropertyListPtrTy,
2071 NULL);
2072 CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
2073
Daniel Dunbar0ed60b02008-08-30 03:02:31 +00002074 // I'm not sure I like this. The implicit coordination is a bit
2075 // gross. We should solve this in a reasonable fashion because this
2076 // is a pretty common task (match some runtime data structure with
2077 // an LLVM data structure).
2078
2079 // FIXME: This is leaked.
2080 // FIXME: Merge with rewriter code?
2081 RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0,
2082 SourceLocation(),
Ted Kremenek2c984042008-09-05 01:34:33 +00002083 &Ctx.Idents.get("_objc_super"));
Daniel Dunbar0ed60b02008-08-30 03:02:31 +00002084 FieldDecl *FieldDecls[2];
2085 FieldDecls[0] = FieldDecl::Create(Ctx, SourceLocation(), 0,
2086 Ctx.getObjCIdType());
2087 FieldDecls[1] = FieldDecl::Create(Ctx, SourceLocation(), 0,
2088 Ctx.getObjCClassType());
Ted Kremenek46a837c2008-09-05 17:16:31 +00002089 RD->defineBody(Ctx, FieldDecls, 2);
Daniel Dunbar0ed60b02008-08-30 03:02:31 +00002090
2091 SuperCTy = Ctx.getTagDeclType(RD);
2092 SuperPtrCTy = Ctx.getPointerType(SuperCTy);
2093
2094 SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
Daniel Dunbar87062ff2008-08-23 09:25:55 +00002095 SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
Daniel Dunbar15245e52008-08-23 04:28:29 +00002096
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002097 // Global metadata structures
2098
2099 SymtabTy = llvm::StructType::get(LongTy,
2100 SelectorPtrTy,
2101 ShortTy,
2102 ShortTy,
Daniel Dunbar4246a8b2008-08-22 20:34:54 +00002103 llvm::ArrayType::get(Int8PtrTy, 0),
Daniel Dunbarb050fa62008-08-21 04:36:09 +00002104 NULL);
2105 CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
2106 SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
2107
2108 ModuleTy =
2109 llvm::StructType::get(LongTy,
2110 LongTy,
2111 Int8PtrTy,
2112 SymtabPtrTy,
2113 NULL);
2114 CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
Daniel Dunbar87062ff2008-08-23 09:25:55 +00002115
2116 // Message send functions
2117
2118 std::vector<const llvm::Type*> Params;
2119 Params.push_back(ObjectPtrTy);
2120 Params.push_back(SelectorPtrTy);
2121 MessageSendFn = llvm::Function::Create(llvm::FunctionType::get(ObjectPtrTy,
2122 Params,
2123 true),
2124 llvm::Function::ExternalLinkage,
2125 "objc_msgSend",
2126 &CGM.getModule());
2127
2128 Params.clear();
2129 Params.push_back(Int8PtrTy);
2130 Params.push_back(ObjectPtrTy);
2131 Params.push_back(SelectorPtrTy);
2132 MessageSendStretFn =
2133 llvm::Function::Create(llvm::FunctionType::get(llvm::Type::VoidTy,
2134 Params,
2135 true),
2136 llvm::Function::ExternalLinkage,
2137 "objc_msgSend_stret",
2138 &CGM.getModule());
2139
2140 Params.clear();
2141 Params.push_back(SuperPtrTy);
2142 Params.push_back(SelectorPtrTy);
2143 MessageSendSuperFn =
2144 llvm::Function::Create(llvm::FunctionType::get(ObjectPtrTy,
2145 Params,
2146 true),
2147 llvm::Function::ExternalLinkage,
2148 "objc_msgSendSuper",
2149 &CGM.getModule());
2150
2151 Params.clear();
2152 Params.push_back(Int8PtrTy);
2153 Params.push_back(SuperPtrTy);
2154 Params.push_back(SelectorPtrTy);
2155 MessageSendSuperStretFn =
2156 llvm::Function::Create(llvm::FunctionType::get(llvm::Type::VoidTy,
2157 Params,
2158 true),
2159 llvm::Function::ExternalLinkage,
2160 "objc_msgSendSuper_stret",
2161 &CGM.getModule());
Anders Carlsson58d16242008-08-31 04:05:03 +00002162
2163 // Enumeration mutation.
2164
2165 Params.clear();
2166 Params.push_back(ObjectPtrTy);
2167 EnumerationMutationFn =
2168 llvm::Function::Create(llvm::FunctionType::get(llvm::Type::VoidTy,
2169 Params,
2170 false),
2171 llvm::Function::ExternalLinkage,
2172 "objc_enumerationMutation",
2173 &CGM.getModule());
Anders Carlsson9acb0a42008-09-09 10:10:21 +00002174
2175 // FIXME: This is the size of the setjmp buffer and should be
2176 // target specific. 18 is what's used on 32-bit X86.
2177 uint64_t SetJmpBufferSize = 18;
2178
2179 // Exceptions
2180 const llvm::Type *StackPtrTy =
2181 llvm::PointerType::getUnqual(llvm::ArrayType::get(llvm::Type::Int8Ty, 4));
2182
2183 ExceptionDataTy =
2184 llvm::StructType::get(llvm::ArrayType::get(llvm::Type::Int32Ty,
2185 SetJmpBufferSize),
2186 StackPtrTy, NULL);
2187 CGM.getModule().addTypeName("struct._objc_exception_data",
2188 ExceptionDataTy);
2189
2190 Params.clear();
2191 Params.push_back(ObjectPtrTy);
2192 ExceptionThrowFn =
2193 llvm::Function::Create(llvm::FunctionType::get(llvm::Type::VoidTy,
2194 Params,
2195 false),
2196 llvm::Function::ExternalLinkage,
2197 "objc_exception_throw",
2198 &CGM.getModule());
2199
2200 Params.clear();
2201 Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
2202 ExceptionTryEnterFn =
2203 llvm::Function::Create(llvm::FunctionType::get(llvm::Type::VoidTy,
2204 Params,
2205 false),
2206 llvm::Function::ExternalLinkage,
2207 "objc_exception_try_enter",
2208 &CGM.getModule());
2209 ExceptionTryExitFn =
2210 llvm::Function::Create(llvm::FunctionType::get(llvm::Type::VoidTy,
2211 Params,
2212 false),
2213 llvm::Function::ExternalLinkage,
2214 "objc_exception_try_exit",
2215 &CGM.getModule());
2216 ExceptionExtractFn =
2217 llvm::Function::Create(llvm::FunctionType::get(ObjectPtrTy,
2218 Params,
2219 false),
2220 llvm::Function::ExternalLinkage,
2221 "objc_exception_extract",
2222 &CGM.getModule());
2223
2224 Params.clear();
2225 Params.push_back(ClassPtrTy);
2226 Params.push_back(ObjectPtrTy);
2227 ExceptionMatchFn =
2228 llvm::Function::Create(llvm::FunctionType::get(llvm::Type::Int32Ty,
2229 Params,
2230 false),
2231 llvm::Function::ExternalLinkage,
2232 "objc_exception_match",
2233 &CGM.getModule());
2234
2235 Params.clear();
2236 Params.push_back(llvm::PointerType::getUnqual(llvm::Type::Int32Ty));
2237 SetJmpFn =
2238 llvm::Function::Create(llvm::FunctionType::get(llvm::Type::Int32Ty,
2239 Params,
2240 false),
2241 llvm::Function::ExternalLinkage,
2242 "_setjmp",
2243 &CGM.getModule());
2244
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00002245}
2246
2247ObjCTypesHelper::~ObjCTypesHelper() {
2248}
2249
Daniel Dunbar87062ff2008-08-23 09:25:55 +00002250llvm::Value *ObjCTypesHelper::getMessageSendFn(bool IsSuper,
Daniel Dunbar49f5a0d2008-09-09 23:48:28 +00002251 bool IsStret,
Daniel Dunbar87062ff2008-08-23 09:25:55 +00002252 const llvm::Type *ReturnTy) {
2253 llvm::Function *F;
2254 llvm::FunctionType *CallFTy;
2255
2256 // FIXME: Should we be caching any of this?
Daniel Dunbar49f5a0d2008-09-09 23:48:28 +00002257 if (IsStret) {
Daniel Dunbar87062ff2008-08-23 09:25:55 +00002258 F = IsSuper ? MessageSendSuperStretFn : MessageSendStretFn;
2259 std::vector<const llvm::Type*> Params(3);
2260 Params[0] = llvm::PointerType::getUnqual(ReturnTy);
2261 Params[1] = IsSuper ? SuperPtrTy : ObjectPtrTy;
2262 Params[2] = SelectorPtrTy;
2263 CallFTy = llvm::FunctionType::get(llvm::Type::VoidTy, Params, true);
Daniel Dunbar952f4732008-08-29 17:28:43 +00002264 } else { // FIXME: floating point?
Daniel Dunbar87062ff2008-08-23 09:25:55 +00002265 F = IsSuper ? MessageSendSuperFn : MessageSendFn;
2266 std::vector<const llvm::Type*> Params(2);
2267 Params[0] = IsSuper ? SuperPtrTy : ObjectPtrTy;
2268 Params[1] = SelectorPtrTy;
2269 CallFTy = llvm::FunctionType::get(ReturnTy, Params, true);
Daniel Dunbar5eec6142008-08-12 03:39:23 +00002270 }
2271
Daniel Dunbar87062ff2008-08-23 09:25:55 +00002272 return llvm::ConstantExpr::getBitCast(F,
2273 llvm::PointerType::getUnqual(CallFTy));
Daniel Dunbar15245e52008-08-23 04:28:29 +00002274}
2275
Daniel Dunbardaf4ad42008-08-12 00:12:39 +00002276/* *** */
2277
Daniel Dunbarcffcdac2008-08-13 03:21:16 +00002278CodeGen::CGObjCRuntime *
2279CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
Daniel Dunbar8c85fac2008-08-11 02:45:11 +00002280 return new CGObjCMac(CGM);
2281}